Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/use i logger #305

Merged
merged 3 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading