Skip to content

Commit

Permalink
Fix/use ILogger (#305)
Browse files Browse the repository at this point in the history
  • Loading branch information
TTA777 authored Dec 3, 2024
1 parent 8fadec9 commit 586d2df
Show file tree
Hide file tree
Showing 25 changed files with 220 additions and 194 deletions.
5 changes: 0 additions & 5 deletions coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
<PackageReference Include="NetEscapades.Configuration.Validation" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="RestSharp" Version="112.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
<PackageReference Include="Serilog.Enrichers.CorrelationId" Version="3.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.3" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.5.1" />
<PackageReference Include="TimeZoneConverter" Version="6.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
Expand Down
38 changes: 20 additions & 18 deletions coffeecard/CoffeeCard.Library/Services/AccountService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using CoffeeCard.Models.Entities;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Microsoft.Extensions.Logging;

namespace CoffeeCard.Library.Services
{
Expand All @@ -25,11 +25,12 @@ public class AccountService : IAccountService
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ITokenService _tokenService;
private readonly ILoginLimiter _loginLimiter;
private readonly ILogger<AccountService> _logger;

public AccountService(CoffeeCardContext context, EnvironmentSettings environmentSettings,
ITokenService tokenService,
IEmailService emailService, IHashService hashService, IHttpContextAccessor httpContextAccessor,
ILoginLimiter loginLimiter, LoginLimiterSettings loginLimiterSettings)
ILoginLimiter loginLimiter, LoginLimiterSettings loginLimiterSettings, ILogger<AccountService> logger)
{
_context = context;
_environmentSettings = environmentSettings;
Expand All @@ -39,11 +40,12 @@ public AccountService(CoffeeCardContext context, EnvironmentSettings environment
_httpContextAccessor = httpContextAccessor;
_loginLimiter = loginLimiter;
_loginLimiterSettings = loginLimiterSettings;
_logger = logger;
}

public string Login(string email, string password, string version)
{
Log.Information("Logging in user with username: {username} version: {version}", email, version);
_logger.LogInformation("Logging in user with username: {username} version: {version}", email, version);

ValidateVersion(version);

Expand All @@ -52,22 +54,22 @@ public string Login(string email, string password, string version)
{
if (user.UserState == UserState.Deleted)
{
Log.Information("Login attempt with deleted user id = {id}", user.Id);
_logger.LogInformation("Login attempt with deleted user id = {id}", user.Id);
throw new ApiException("The username or password does not match",
StatusCodes.Status401Unauthorized);
}

if (!user.IsVerified)
{
Log.Information("E-mail not verified. E-mail = {username} from IP = {ipAddress} ", email,
_logger.LogInformation("E-mail not verified. E-mail = {username} from IP = {ipAddress} ", email,
_httpContextAccessor.HttpContext.Connection.RemoteIpAddress);
throw new ApiException("E-mail has not been verified", StatusCodes.Status403Forbidden);
}

if (_loginLimiterSettings.IsEnabled &&
!_loginLimiter.LoginAllowed(user)) //Login limiter is only called if it is enabled in the settings
{
Log.Warning(
_logger.LogWarning(
"Login attempts exceeding maximum allowed for e-mail = {username} from IP = {ipaddress} ",
email,
_httpContextAccessor.HttpContext.Connection.RemoteIpAddress);
Expand All @@ -94,7 +96,7 @@ public string Login(string email, string password, string version)
}
}

Log.Information("Unsuccessful login for e-mail = {username} from IP = {ipAddress} ", email,
_logger.LogInformation("Unsuccessful login for e-mail = {username} from IP = {ipAddress} ", email,
_httpContextAccessor.HttpContext.Connection.RemoteIpAddress);

throw new ApiException("The username or password does not match",
Expand All @@ -103,11 +105,11 @@ public string Login(string email, string password, string version)

public async Task<User> RegisterAccountAsync(string name, string email, string password, int programme = 1)
{
Log.Information("Trying to register new user. Name: {name} Email: {email}", name, email);
_logger.LogInformation("Trying to register new user. Name: {name} Email: {email}", name, email);

if (_context.Users.Any(x => x.Email == email))
{
Log.Information("Could not register user Name: {name}. Email:{email} already exists", name, email);
_logger.LogInformation("Could not register user Name: {name}. Email:{email} already exists", name, email);
throw new ApiException($"The email {email} is already being used by another user",
StatusCodes.Status409Conflict);
}
Expand Down Expand Up @@ -146,7 +148,7 @@ public async Task<User> RegisterAccountAsync(string name, string email, string p

public async Task<bool> VerifyRegistration(string token)
{
Log.Information("Trying to verify registration with token: {token}", token);
_logger.LogInformation("Trying to verify registration with token: {token}", token);

var email = _tokenService.ValidateVerificationTokenAndGetEmail(token);
var user = GetAccountByEmail(email);
Expand All @@ -163,20 +165,20 @@ public User UpdateAccount(IEnumerable<Claim> claims, UpdateUserDto userDto)
{
if (_context.Users.Any(x => x.Email == userDto.Email))
throw new ApiException($"The email {userDto.Email} is already in use!", 400);
Log.Information($"Changing email of user from {user.Email} to {userDto.Email}");
_logger.LogInformation("Changing email of user from {oldEmail} to {newEmail}", user.Email, userDto.Email);
user.Email = userDto.Email;
}

if (userDto.Name != null)
{
Log.Information($"Changing name of user from {user.Name} to {EscapeName(userDto.Name)}");
_logger.LogInformation("Changing name of user from {oldName} to {newName}", user.Name, EscapeName(userDto.Name));
user.Name = EscapeName(userDto.Name);
}

if (userDto.PrivacyActivated != null)
{
Log.Information(
$"Changing privacy of user from {user.PrivacyActivated} to {(bool)userDto.PrivacyActivated}");
_logger.LogInformation(
"Changing privacy of user from {oldPrivacy} to {newPrivacy}", user.PrivacyActivated, (bool)userDto.PrivacyActivated);
user.PrivacyActivated = (bool)userDto.PrivacyActivated;
}

Expand All @@ -185,7 +187,7 @@ public User UpdateAccount(IEnumerable<Claim> claims, UpdateUserDto userDto)
var programme = _context.Programmes.FirstOrDefault(x => x.Id == userDto.ProgrammeId);
if (programme == null)
throw new ApiException($"No programme with id {userDto.ProgrammeId} exists!", 400);
Log.Information($"Changing programme of user from {user.Programme.Id} to {programme.Id}");
_logger.LogInformation("Changing programme of user from {oldProgrammeId} to {newProgrammeId}", user.Programme.Id, programme.Id);
user.Programme = programme;
}

Expand All @@ -195,7 +197,7 @@ public User UpdateAccount(IEnumerable<Claim> claims, UpdateUserDto userDto)
var hashedPassword = _hashService.Hash(userDto.Password + salt);
user.Salt = salt;
user.Password = hashedPassword;
Log.Information("User changed password");
_logger.LogInformation("User changed password");
}

_context.SaveChanges();
Expand Down Expand Up @@ -246,13 +248,13 @@ public async Task<bool> RecoverUserAsync(string token, string newPassword)
var tokenObj = _tokenService.ReadToken(token);
if (tokenObj == null) return false;

Log.Information($"User tried to recover with token {token}");
_logger.LogInformation("User tried to recover with token {token}", token);
if (!await _tokenService.ValidateTokenIsUnusedAsync(token)) return false;

var user = GetAccountByClaims(tokenObj.Claims);
if (user == null) return false;

Log.Information($"{user.Email} tried to recover user");
_logger.LogInformation("{email} tried to recover user", user.Email);
var sha256Pw = _hashService.Hash(newPassword);
var salt = _hashService.GenerateSalt();
var hashedPassword = _hashService.Hash(sha256Pw + salt);
Expand Down
11 changes: 5 additions & 6 deletions coffeecard/CoffeeCard.Library/Services/EmailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
using CoffeeCard.Models.DataTransferObjects.User;
using CoffeeCard.Models.Entities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using MimeKit;
using RestSharp;
using RestSharp.Authenticators;
using Serilog;
using TimeZoneConverter;

namespace CoffeeCard.Library.Services
Expand All @@ -20,6 +18,7 @@ public class EmailService : IEmailService
private readonly EnvironmentSettings _environmentSettings;
private readonly IEmailSender _emailSender;
private readonly IMapperService _mapperService;
private readonly ILogger<EmailService> _logger;

public EmailService(IEmailSender emailSender, EnvironmentSettings environmentSettings,
IWebHostEnvironment env, IMapperService mapperService)
Expand Down Expand Up @@ -52,14 +51,14 @@ public async Task SendInvoiceAsync(UserDto user, PurchaseDto purchase)

message.Body = builder.ToMessageBody();

Log.Information("Sending invoice for PurchaseId {PurchaseId} to UserId {UserId}, E-mail {Email}", purchase.Id, user.Id, user.Email);
_logger.LogInformation("Sending invoice for PurchaseId {PurchaseId} to UserId {UserId}, E-mail {Email}", purchase.Id, user.Id, user.Email);

await _emailSender.SendEmailAsync(message);
}

public async Task SendRegistrationVerificationEmailAsync(User user, string token)
{
Log.Information("Sending registration verification email to {email} {userid}", user.Email, user.Id);
_logger.LogInformation("Sending registration verification email to {email} {userid}", user.Email, user.Id);
var message = new MimeMessage();
var builder = RetrieveTemplate("email_verify_registration.html");
const string endpoint = "verifyemail?token=";
Expand Down Expand Up @@ -92,7 +91,7 @@ public async Task SendVerificationEmailForLostPwAsync(User user, string token)

public async Task SendVerificationEmailForDeleteAccount(User user, string token)
{
Log.Information("Sending delete verification email to {email} {userid}", user.Email, user.Id);
_logger.LogInformation("Sending delete verification email to {email} {userid}", user.Email, user.Id);
var message = new MimeMessage();
var builder = RetrieveTemplate("email_verify_account_deletion.html");
const string endpoint = "verifydelete?token=";
Expand Down
8 changes: 5 additions & 3 deletions coffeecard/CoffeeCard.Library/Services/LoginLimiter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@
using System.Collections.Concurrent;
using CoffeeCard.Common.Configuration;
using CoffeeCard.Models.Entities;
using Serilog;
using Microsoft.Extensions.Logging;

namespace CoffeeCard.Library.Services
{
public class LoginLimiter : ILoginLimiter
{
private readonly ConcurrentDictionary<string, (DateTime, int)> _loginAttempts;
private readonly LoginLimiterSettings _loginLimiterSettings;
private readonly ILogger<LoginLimiter> _logger;

public LoginLimiter(LoginLimiterSettings loginLimiterSettings)
public LoginLimiter(LoginLimiterSettings loginLimiterSettings, ILogger<LoginLimiter> logger)
{
_loginAttempts = new ConcurrentDictionary<string, (DateTime, int)>();
_loginLimiterSettings = loginLimiterSettings;
_logger = logger;
}

/// <summary>
Expand All @@ -40,7 +42,7 @@ private void ResetUsersTimeoutPeriod(string email)
{
if (!_loginAttempts.TryGetValue(email, out var oldEntry)) return;
if (_loginAttempts.TryUpdate(email, (DateTime.UtcNow, oldEntry.Item2), oldEntry))
Log.Warning("The lockout period for {username} was reset, possible brute force attack", email);
_logger.LogWarning("The lockout period for {username} was reset, possible brute force attack", email);
}

/// <summary>
Expand Down
9 changes: 5 additions & 4 deletions coffeecard/CoffeeCard.Library/Services/MailgunEmailSender.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using System.Threading.Tasks;
using CoffeeCard.Common.Configuration;
using Microsoft.Extensions.Logging;
using MimeKit;
using RestSharp;
using RestSharp.Authenticators;
using Serilog;

namespace CoffeeCard.Library.Services;

public class MailgunEmailSender(MailgunSettings mailgunSettings, IRestClient restClient) : IEmailSender
public class MailgunEmailSender(MailgunSettings mailgunSettings, IRestClient restClient, ILogger<MailgunEmailSender> logger) : IEmailSender
{
private readonly ILogger<MailgunEmailSender> _logger = logger;

public async Task SendEmailAsync(MimeMessage mail)
{

Expand All @@ -25,7 +26,7 @@ public async Task SendEmailAsync(MimeMessage mail)

if (!response.IsSuccessful)
{
Log.Error(
_logger.LogError(
"Error sending request to Mailgun. StatusCode: {statusCode} ErrorMessage: {errorMessage}",
response.StatusCode,
response.ErrorMessage
Expand Down
12 changes: 7 additions & 5 deletions coffeecard/CoffeeCard.Library/Services/PurchaseService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@
using CoffeeCard.Models.Entities;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Microsoft.Extensions.Logging;

namespace CoffeeCard.Library.Services
{
public class PurchaseService : IPurchaseService
{
private readonly CoffeeCardContext _context;
private readonly ILogger<PurchaseService> _logger;

public PurchaseService(CoffeeCardContext context)
public PurchaseService(CoffeeCardContext context, ILogger<PurchaseService> logger)
{
_context = context;
_logger = logger;
}

public async Task<Purchase> RedeemVoucher(string voucherCode, IEnumerable<Claim> claims)
Expand Down Expand Up @@ -80,7 +82,7 @@ private async Task<Guid> GenerateUniqueOrderId()

public Purchase DeliverProductToUser(Purchase purchase, User user, string transactionId)
{
Log.Information(
_logger.LogInformation(
$"Delivering product ({purchase.ProductId}) to userId: {user.Id} with orderId: {purchase.OrderId}");
var product = _context.Products.FirstOrDefault(x => x.Id == purchase.ProductId);
if (product == null)
Expand All @@ -97,8 +99,8 @@ public Purchase DeliverProductToUser(Purchase purchase, User user, string transa
_context.Entry(user).State = EntityState.Modified;
_context.SaveChanges();

Log.Information(
$"Delivery of product ({purchase.ProductId}) to userId: {user.Id} with orderId: {purchase.OrderId} succeeded!");
_logger.LogInformation(
"Delivery of product ({productId}) to userId: {userId} with orderId: {purchaseId} succeeded!", purchase.ProductId, user.Id, purchase.OrderId);
return purchase;
}

Expand Down
8 changes: 5 additions & 3 deletions coffeecard/CoffeeCard.Library/Services/SmtpEmailSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
using System.Threading.Tasks;
using CoffeeCard.Common.Configuration;
using MailKit.Net.Smtp;
using Microsoft.Extensions.Logging;
using MimeKit;
using Serilog;

namespace CoffeeCard.Library.Services;

public class SmtpEmailSender(SmtpSettings smtpSettings) : IEmailSender
public class SmtpEmailSender(SmtpSettings smtpSettings, ILogger<SmtpEmailSender> logger) : IEmailSender
{
private readonly ILogger<SmtpEmailSender> _logger = logger;

public async Task SendEmailAsync(MimeMessage mail)
{
mail.From.Add(new MailboxAddress("Cafe Analog", "smtp@analogio.dk"));
Expand All @@ -22,7 +24,7 @@ public async Task SendEmailAsync(MimeMessage mail)
}
catch (Exception ex)
{
Log.Error("Error sending request to SMTP server. Error: {errorMessage}", ex.Message);
_logger.LogError("Error sending request to SMTP server. Error: {errorMessage}", ex.Message);
}
}
}
Loading

0 comments on commit 586d2df

Please sign in to comment.