diff --git a/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj b/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj index 4298834d..32d513fb 100644 --- a/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj +++ b/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj @@ -11,11 +11,6 @@ - - - - - diff --git a/coffeecard/CoffeeCard.Library/Services/AccountService.cs b/coffeecard/CoffeeCard.Library/Services/AccountService.cs index 71a723b0..0053375a 100644 --- a/coffeecard/CoffeeCard.Library/Services/AccountService.cs +++ b/coffeecard/CoffeeCard.Library/Services/AccountService.cs @@ -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 { @@ -25,11 +25,12 @@ public class AccountService : IAccountService private readonly IHttpContextAccessor _httpContextAccessor; private readonly ITokenService _tokenService; private readonly ILoginLimiter _loginLimiter; + private readonly ILogger _logger; public AccountService(CoffeeCardContext context, EnvironmentSettings environmentSettings, ITokenService tokenService, IEmailService emailService, IHashService hashService, IHttpContextAccessor httpContextAccessor, - ILoginLimiter loginLimiter, LoginLimiterSettings loginLimiterSettings) + ILoginLimiter loginLimiter, LoginLimiterSettings loginLimiterSettings, ILogger logger) { _context = context; _environmentSettings = environmentSettings; @@ -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); @@ -52,14 +54,14 @@ 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); } @@ -67,7 +69,7 @@ public string Login(string email, string password, string version) 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); @@ -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", @@ -103,11 +105,11 @@ public string Login(string email, string password, string version) public async Task 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); } @@ -146,7 +148,7 @@ public async Task RegisterAccountAsync(string name, string email, string p public async Task 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); @@ -163,20 +165,20 @@ public User UpdateAccount(IEnumerable 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; } @@ -185,7 +187,7 @@ public User UpdateAccount(IEnumerable 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; } @@ -195,7 +197,7 @@ public User UpdateAccount(IEnumerable 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(); @@ -246,13 +248,13 @@ public async Task 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); diff --git a/coffeecard/CoffeeCard.Library/Services/EmailService.cs b/coffeecard/CoffeeCard.Library/Services/EmailService.cs index bd419659..0da95ea0 100644 --- a/coffeecard/CoffeeCard.Library/Services/EmailService.cs +++ b/coffeecard/CoffeeCard.Library/Services/EmailService.cs @@ -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 @@ -20,6 +18,7 @@ public class EmailService : IEmailService private readonly EnvironmentSettings _environmentSettings; private readonly IEmailSender _emailSender; private readonly IMapperService _mapperService; + private readonly ILogger _logger; public EmailService(IEmailSender emailSender, EnvironmentSettings environmentSettings, IWebHostEnvironment env, IMapperService mapperService) @@ -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="; @@ -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="; diff --git a/coffeecard/CoffeeCard.Library/Services/LoginLimiter.cs b/coffeecard/CoffeeCard.Library/Services/LoginLimiter.cs index 2d897ef1..3257d507 100644 --- a/coffeecard/CoffeeCard.Library/Services/LoginLimiter.cs +++ b/coffeecard/CoffeeCard.Library/Services/LoginLimiter.cs @@ -2,7 +2,7 @@ using System.Collections.Concurrent; using CoffeeCard.Common.Configuration; using CoffeeCard.Models.Entities; -using Serilog; +using Microsoft.Extensions.Logging; namespace CoffeeCard.Library.Services { @@ -10,11 +10,13 @@ public class LoginLimiter : ILoginLimiter { private readonly ConcurrentDictionary _loginAttempts; private readonly LoginLimiterSettings _loginLimiterSettings; + private readonly ILogger _logger; - public LoginLimiter(LoginLimiterSettings loginLimiterSettings) + public LoginLimiter(LoginLimiterSettings loginLimiterSettings, ILogger logger) { _loginAttempts = new ConcurrentDictionary(); _loginLimiterSettings = loginLimiterSettings; + _logger = logger; } /// @@ -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); } /// diff --git a/coffeecard/CoffeeCard.Library/Services/MailgunEmailSender.cs b/coffeecard/CoffeeCard.Library/Services/MailgunEmailSender.cs index b44d664e..0351ddca 100644 --- a/coffeecard/CoffeeCard.Library/Services/MailgunEmailSender.cs +++ b/coffeecard/CoffeeCard.Library/Services/MailgunEmailSender.cs @@ -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 logger) : IEmailSender { + private readonly ILogger _logger = logger; + public async Task SendEmailAsync(MimeMessage mail) { @@ -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 diff --git a/coffeecard/CoffeeCard.Library/Services/PurchaseService.cs b/coffeecard/CoffeeCard.Library/Services/PurchaseService.cs index 04bd0895..5e62bec9 100644 --- a/coffeecard/CoffeeCard.Library/Services/PurchaseService.cs +++ b/coffeecard/CoffeeCard.Library/Services/PurchaseService.cs @@ -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 _logger; - public PurchaseService(CoffeeCardContext context) + public PurchaseService(CoffeeCardContext context, ILogger logger) { _context = context; + _logger = logger; } public async Task RedeemVoucher(string voucherCode, IEnumerable claims) @@ -80,7 +82,7 @@ private async Task 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) @@ -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; } diff --git a/coffeecard/CoffeeCard.Library/Services/SmtpEmailSender.cs b/coffeecard/CoffeeCard.Library/Services/SmtpEmailSender.cs index 4676bddf..711ddc88 100644 --- a/coffeecard/CoffeeCard.Library/Services/SmtpEmailSender.cs +++ b/coffeecard/CoffeeCard.Library/Services/SmtpEmailSender.cs @@ -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 logger) : IEmailSender { + private readonly ILogger _logger = logger; + public async Task SendEmailAsync(MimeMessage mail) { mail.From.Add(new MailboxAddress("Cafe Analog", "smtp@analogio.dk")); @@ -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); } } } \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Library/Services/TicketService.cs b/coffeecard/CoffeeCard.Library/Services/TicketService.cs index b479001a..601c525b 100644 --- a/coffeecard/CoffeeCard.Library/Services/TicketService.cs +++ b/coffeecard/CoffeeCard.Library/Services/TicketService.cs @@ -7,13 +7,12 @@ using CoffeeCard.Common.Errors; using CoffeeCard.Library.Persistence; using CoffeeCard.Library.Services.v2; -using CoffeeCard.Models.DataTransferObjects; using CoffeeCard.Models.DataTransferObjects.CoffeeCard; using CoffeeCard.Models.DataTransferObjects.Ticket; using CoffeeCard.Models.Entities; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; -using Serilog; +using Microsoft.Extensions.Logging; namespace CoffeeCard.Library.Services { @@ -23,13 +22,15 @@ public class TicketService : ITicketService private readonly IProductService _productService; private readonly IStatisticService _statisticService; private readonly CoffeeCardContext _context; + private readonly ILogger _logger; - public TicketService(CoffeeCardContext context, IAccountService accountService, IProductService productService, IStatisticService statisticService) + public TicketService(CoffeeCardContext context, IAccountService accountService, IProductService productService, IStatisticService statisticService, ILogger logger) { _context = context; _accountService = accountService; _productService = productService; _statisticService = statisticService; + _logger = logger; } public IEnumerable GetTickets(IEnumerable claims, bool used) @@ -48,10 +49,10 @@ public async Task UseTicket(IEnumerable claims, int productId) if (userIdClaim == null) throw new ApiException("The token is invalid!", 401); var userId = int.Parse(userIdClaim.Value); - Log.Information($"Using product with id, {productId}"); + _logger.LogInformation("Using product with id, {productId}", productId); var ticketId = GetFirstTicketIdFromProduct(productId, userId); - Log.Information($"Using ticket with id: {ticketId}"); + _logger.LogInformation("Using ticket with id: {ticketId}", ticketId); var usedTicket = ValidateTicket(ticketId, userId); UpdateTicket(usedTicket); @@ -67,7 +68,7 @@ public async Task> UseMultipleTickets(IEnumerable cla //Throws exception if the list is empty if (!dto.ProductIds.Any()) throw new ApiException("The list is empty", StatusCodes.Status400BadRequest); - Log.Information($"Using multiple tickets {string.Join(",", dto.ProductIds)}"); + _logger.LogInformation("Using multiple tickets {@productIds} ", dto.ProductIds); var userIdClaim = claims.FirstOrDefault(x => x.Type == Constants.UserId); if (userIdClaim == null) throw new ApiException("The token is invalid!", StatusCodes.Status401Unauthorized); var userId = int.Parse(userIdClaim.Value); @@ -109,11 +110,11 @@ public async Task> UseMultipleTickets(IEnumerable cla // update user experience usedTickets.ForEach(x => _accountService.UpdateExperience(userId, GetExperienceByTicket(x.ProductId))); _context.SaveChanges(); - Log.Information("All tickets were successfully used, updated and saved!"); + _logger.LogInformation("All tickets were successfully used, updated and saved!"); } else { - Log.Error($"All tickets could not be used :-( ticketIds: {string.Join(",", tickets)}"); + _logger.LogError("All tickets could not be used :-( ticketIds: {@tickets}", tickets); throw new ApiException("Could not use the supplied tickets - try again later or contact AnalogIO!", StatusCodes.Status400BadRequest); } @@ -179,7 +180,7 @@ private IEnumerable GetMultipleTicketsFromProduct(int productId, int use private Ticket ValidateTicket(int ticketId, int userId) { - Log.Information($"Validating that ticketId: {ticketId} belongs to userId: {userId} and is not used"); + _logger.LogInformation("Validating that ticketId: {ticketId} belongs to userId: {userId} and is not used", ticketId, userId); var ticket = _context.Tickets.Include(x => x.Purchase) .FirstOrDefault(x => x.Id == ticketId && x.Status == TicketStatus.Unused && x.Owner.Id == userId); if (ticket == null) throw new ApiException("The ticket is invalid", StatusCodes.Status400BadRequest); diff --git a/coffeecard/CoffeeCard.Library/Services/TokenService.cs b/coffeecard/CoffeeCard.Library/Services/TokenService.cs index 581d01e8..938b4e8f 100644 --- a/coffeecard/CoffeeCard.Library/Services/TokenService.cs +++ b/coffeecard/CoffeeCard.Library/Services/TokenService.cs @@ -10,8 +10,8 @@ using CoffeeCard.Library.Utils; using CoffeeCard.Models.Entities; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; -using Serilog; namespace CoffeeCard.Library.Services { @@ -19,11 +19,13 @@ public class TokenService : ITokenService { private readonly ClaimsUtilities _claimsUtilities; private readonly IdentitySettings _identitySettings; + private readonly ILogger _logger; - public TokenService(IdentitySettings identitySettings, ClaimsUtilities claimsUtilities) + public TokenService(IdentitySettings identitySettings, ClaimsUtilities claimsUtilities, ILogger logger) { _identitySettings = identitySettings; _claimsUtilities = claimsUtilities; + _logger = logger; } public string GenerateToken(IEnumerable claims) @@ -77,7 +79,7 @@ public bool ValidateToken(string tokenString) catch (Exception e) when (e is ArgumentException || e is SecurityTokenException) { - Log.Information("Received invalid token"); + _logger.LogInformation("Received invalid token"); return false; } @@ -105,7 +107,7 @@ public async Task ValidateTokenIsUnusedAsync(string tokenString) } catch (ArgumentException e) { - Log.Error(e, "Unable to read token. Exception thrown"); + _logger.LogError("Unable to read token. Exception thrown {ex}", e); return false; } } @@ -114,21 +116,21 @@ public string ValidateVerificationTokenAndGetEmail(string token) { if (!ValidateToken(token)) { - Log.Information("Token validation failed. DId not pass validation parameters"); + _logger.LogInformation("Token validation failed. DId not pass validation parameters"); throw new ApiException("The token is invalid!", StatusCodes.Status401Unauthorized); } var jwtToken = ReadToken(token); if (jwtToken.Claims.Any(x => x.Type == ClaimTypes.Role && x.Value != "verification_token")) { - Log.Information("Token validation failed. Not a verification token"); + _logger.LogInformation("Token validation failed. Not a verification token"); throw new ApiException("The token is invalid!", StatusCodes.Status401Unauthorized); } var emailClaim = jwtToken.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Email); if (emailClaim == null) { - Log.Information("Token validation failed. No email found in token"); + _logger.LogInformation("Token validation failed. No email found in token"); throw new ApiException("The token is invalid!", StatusCodes.Status401Unauthorized); } diff --git a/coffeecard/CoffeeCard.Library/Services/v2/AccountService.cs b/coffeecard/CoffeeCard.Library/Services/v2/AccountService.cs index c55fb8f5..a2ceb2fb 100644 --- a/coffeecard/CoffeeCard.Library/Services/v2/AccountService.cs +++ b/coffeecard/CoffeeCard.Library/Services/v2/AccountService.cs @@ -9,7 +9,7 @@ using CoffeeCard.Models.Entities; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; -using Serilog; +using Microsoft.Extensions.Logging; namespace CoffeeCard.Library.Services.v2 { @@ -19,22 +19,24 @@ public class AccountService : IAccountService private readonly IEmailService _emailService; private readonly IHashService _hashService; private readonly ITokenService _tokenService; + private readonly ILogger _logger; - public AccountService(CoffeeCardContext context, ITokenService tokenService, IEmailService emailService, IHashService hashService) + public AccountService(CoffeeCardContext context, ITokenService tokenService, IEmailService emailService, IHashService hashService, ILogger logger) { _context = context; _tokenService = tokenService; _emailService = emailService; _hashService = hashService; + _logger = logger; } public async Task RegisterAccountAsync(string name, string email, string password, int programme) { - 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); } @@ -82,20 +84,20 @@ public async Task UpdateAccountAsync(User user, UpdateUserRequest updateUs { if (_context.Users.Any(x => x.Email == updateUserRequest.Email)) throw new ApiException($"The email {updateUserRequest.Email} is already in use!", 400); - Log.Information($"Changing email of user from {user.Email} to {updateUserRequest.Email}"); + _logger.LogInformation("Changing email of user from {email} to {newEmail}", user.Email, updateUserRequest.Email); user.Email = updateUserRequest.Email; } if (updateUserRequest.Name != null) { - Log.Information($"Changing name of user from {user.Name} to {EscapeName(updateUserRequest.Name)}"); + _logger.LogInformation("Changing name of user from {oldName} to {newName}", user.Name, EscapeName(updateUserRequest.Name)); user.Name = EscapeName(updateUserRequest.Name); } if (updateUserRequest.PrivacyActivated != null) { - Log.Information( - $"Changing privacy of user from {user.PrivacyActivated} to {(bool)updateUserRequest.PrivacyActivated}"); + _logger.LogInformation( + "Changing privacy of user from {oldPrivacy} to {newPrivacy}", user.PrivacyActivated, (bool)updateUserRequest.PrivacyActivated); user.PrivacyActivated = (bool)updateUserRequest.PrivacyActivated; } @@ -104,7 +106,7 @@ public async Task UpdateAccountAsync(User user, UpdateUserRequest updateUs var programme = _context.Programmes.FirstOrDefault(x => x.Id == updateUserRequest.ProgrammeId); if (programme == null) throw new ApiException($"No programme with id {updateUserRequest.ProgrammeId} exists!", 400); - Log.Information($"Changing programme of user from {user.Programme.Id} to {programme.Id}"); + _logger.LogInformation("Changing programme of user from {oldProgramme} to {newProgramme}", user.Programme.Id, programme.Id); user.Programme = programme; } @@ -114,7 +116,7 @@ public async Task UpdateAccountAsync(User user, UpdateUserRequest updateUs var hashedPassword = _hashService.Hash(updateUserRequest.Password + salt); user.Salt = salt; user.Password = hashedPassword; - Log.Information("User changed password"); + _logger.LogInformation("User changed password"); } await _context.SaveChangesAsync(); @@ -146,7 +148,7 @@ public async Task RequestAnonymizationAsync(User user) public async Task AnonymizeAccountAsync(string token) { - Log.Information("Trying to verify deletion with token: {token}", token); + _logger.LogInformation("Trying to verify deletion with token: {token}", token); var email = _tokenService.ValidateVerificationTokenAndGetEmail(token); var user = await GetAccountByEmailAsync(email); @@ -263,7 +265,7 @@ private async Task GetUserByIdAsync(int id) if (user == null) { - Log.Error("No user was found by user id: {id}", id); + _logger.LogError("No user was found by user id: {id}", id); throw new EntityNotFoundException($"No user was found by user id: {id}"); } diff --git a/coffeecard/CoffeeCard.Library/Services/v2/MenuItemService.cs b/coffeecard/CoffeeCard.Library/Services/v2/MenuItemService.cs index d206423e..e40c9868 100644 --- a/coffeecard/CoffeeCard.Library/Services/v2/MenuItemService.cs +++ b/coffeecard/CoffeeCard.Library/Services/v2/MenuItemService.cs @@ -8,17 +8,19 @@ using CoffeeCard.Models.DataTransferObjects.v2.Products; using CoffeeCard.Models.Entities; using Microsoft.EntityFrameworkCore; -using Serilog; +using Microsoft.Extensions.Logging; namespace CoffeeCard.Library.Services.v2 { public sealed class MenuItemService : IMenuItemService { private readonly CoffeeCardContext _context; + private readonly ILogger _logger; - public MenuItemService(CoffeeCardContext context) + public MenuItemService(CoffeeCardContext context, ILogger logger) { _context = context; + _logger = logger; } public async Task> GetAllMenuItemsAsync() @@ -72,7 +74,7 @@ public async Task UpdateMenuItemAsync(int id, UpdateMenuItemRe if (menuItem == null) { - Log.Warning("No menu item was found by Menu Item Id: {Id}", id); + _logger.LogWarning("No menu item was found by Menu Item Id: {Id}", id); throw new EntityNotFoundException($"No menu item was found by Menu Item Id {id}"); } diff --git a/coffeecard/CoffeeCard.Library/Services/v2/ProductService.cs b/coffeecard/CoffeeCard.Library/Services/v2/ProductService.cs index cd16e9ea..a7c0a77f 100644 --- a/coffeecard/CoffeeCard.Library/Services/v2/ProductService.cs +++ b/coffeecard/CoffeeCard.Library/Services/v2/ProductService.cs @@ -8,18 +8,20 @@ using CoffeeCard.Models.DataTransferObjects.v2.Products; using CoffeeCard.Models.Entities; using Microsoft.EntityFrameworkCore; -using Serilog; using CoffeeCard.Library.Utils; +using Microsoft.Extensions.Logging; namespace CoffeeCard.Library.Services.v2 { public sealed class ProductService : IProductService { private readonly CoffeeCardContext _context; + private readonly ILogger _logger; - public ProductService(CoffeeCardContext context) + public ProductService(CoffeeCardContext context, ILogger logger) { _context = context; + _logger = logger; } public async Task> GetProductsForUserAsync(User user) @@ -57,7 +59,7 @@ public async Task GetProductAsync(int productId) if (product == null) { - Log.Error("No product was found by Product Id: {Id}", productId); + _logger.LogError("No product was found by Product Id: {Id}", productId); throw new EntityNotFoundException($"No product was found by Product Id: {productId}"); } diff --git a/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs b/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs index 187c615e..96167dd3 100644 --- a/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs +++ b/coffeecard/CoffeeCard.Library/Services/v2/PurchaseService.cs @@ -12,7 +12,7 @@ using CoffeeCard.Models.Entities; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; -using Serilog; +using Microsoft.Extensions.Logging; using Purchase = CoffeeCard.Models.Entities.Purchase; namespace CoffeeCard.Library.Services.v2 @@ -24,15 +24,17 @@ public sealed class PurchaseService : IPurchaseService private readonly IMobilePayPaymentsService _mobilePayPaymentsService; private readonly ITicketService _ticketService; private readonly IProductService _productService; + private readonly ILogger _logger; public PurchaseService(CoffeeCardContext context, IMobilePayPaymentsService mobilePayPaymentsService, - ITicketService ticketService, IEmailService emailService, IProductService productService) + ITicketService ticketService, IEmailService emailService, IProductService productService, ILogger logger) { _context = context; _mobilePayPaymentsService = mobilePayPaymentsService; _ticketService = ticketService; _emailService = emailService; _productService = productService; + _logger = logger; } public async Task InitiatePurchase(InitiatePurchaseRequest initiateRequest, User user) @@ -40,7 +42,7 @@ public async Task InitiatePurchase(InitiatePurchaseReq var product = await _productService.GetProductAsync(initiateRequest.ProductId); CheckUserIsAllowedToPurchaseProduct(user, initiateRequest, product); - Log.Information("Initiating purchase of ProductId {ProductId}, PaymentType {PurchaseType} by UserId {UserId}", initiateRequest.ProductId, initiateRequest.PaymentType, user.Id); + _logger.LogInformation("Initiating purchase of ProductId {ProductId}, PaymentType {PurchaseType} by UserId {UserId}", initiateRequest.ProductId, initiateRequest.PaymentType, user.Id); var (purchase, paymentDetails) = await InitiatePaymentAsync(initiateRequest, product, user); @@ -49,7 +51,7 @@ public async Task InitiatePurchase(InitiatePurchaseReq if (purchase.Status == PurchaseStatus.Completed) { - Log.Information("Purchase {PurchaseId} has state Completed. Issues tickets", purchase.Id); + _logger.LogInformation("Purchase {PurchaseId} has state Completed. Issues tickets", purchase.Id); await _ticketService.IssueTickets(purchase); } @@ -74,12 +76,12 @@ public async Task InitiatePurchase(InitiatePurchaseReq /// Product /// User is not entitled to purchase product /// PaymentType FreePurchase used for a non-free product - private static void CheckUserIsAllowedToPurchaseProduct(User user, InitiatePurchaseRequest initiateRequest, ProductResponse product) + private void CheckUserIsAllowedToPurchaseProduct(User user, InitiatePurchaseRequest initiateRequest, ProductResponse product) { //Product does not belong to same userGroup as user if (!product.AllowedUserGroups.Any(ug => ug == user.UserGroup)) { - Log.Warning( + _logger.LogWarning( "User {UserId} is not authorized to purchase Product Id: {ProductId} as user is not in Product User Group", user.Id, product.Id); throw new IllegalUserOperationException($"User is not entitled to purchase product '{product.Name}'"); @@ -87,7 +89,7 @@ private static void CheckUserIsAllowedToPurchaseProduct(User user, InitiatePurch if (initiateRequest.PaymentType == PaymentType.FreePurchase && product.Price != 0) { - Log.Warning( + _logger.LogWarning( "User tried to issue paid product to themselves, User {UserId}, Product {ProductId}", user.Id, product.Id); throw new ArgumentException($"Product '{product.Name}' is not free"); @@ -122,7 +124,7 @@ private static void CheckUserIsAllowedToPurchaseProduct(User user, InitiatePurch break; default: - Log.Error("Payment Type {PaymentType} is not handled in PurchaseService", purchaseRequest.PaymentType); + _logger.LogError("Payment Type {PaymentType} is not handled in PurchaseService", purchaseRequest.PaymentType); throw new ArgumentException($"Payment Type '{purchaseRequest.PaymentType}' is not handled"); } @@ -152,7 +154,7 @@ public async Task GetPurchase(int purchaseId, User user) .FirstOrDefaultAsync(); if (purchase == null) { - Log.Error("No purchase was found by Purchase Id: {Id} and User Id: {UId}", purchaseId, user.Id); + _logger.LogError("No purchase was found by Purchase Id: {Id} and User Id: {UId}", purchaseId, user.Id); throw new EntityNotFoundException( $"No purchase was found by Purchase Id: {purchaseId} and User Id: {user.Id}"); } @@ -177,7 +179,7 @@ public async Task> GetPurchases(int userId) .FirstOrDefaultAsync(); if (user == null) { - Log.Error("No user was found by User Id: {Id}", userId); + _logger.LogError("No user was found by User Id: {Id}", userId); throw new EntityNotFoundException($"No user was found by User Id: {userId}"); } @@ -210,14 +212,14 @@ public async Task HandleMobilePayPaymentUpdate(MobilePayWebhook webhook) .FirstOrDefaultAsync(); if (purchase == null) { - Log.Error("No purchase was found by TransactionId: {Id} from Webhook request", webhook.Data.Id); + _logger.LogError("No purchase was found by TransactionId: {Id} from Webhook request", webhook.Data.Id); throw new EntityNotFoundException( $"No purchase was found by Transaction Id: {webhook.Data.Id} from webhook request"); } if (purchase.Status == PurchaseStatus.Completed) { - Log.Warning( + _logger.LogWarning( "Purchase from Webhook request is already completed. Purchase Id: {PurchaseId}, Transaction Id: {TransactionId}", purchase.Id, webhook.Data.Id); return; @@ -242,7 +244,7 @@ public async Task HandleMobilePayPaymentUpdate(MobilePayWebhook webhook) break; } default: - Log.Error( + _logger.LogError( "Unknown EventType from Webhook request. Event Type: {EventType}, Purchase Id: {PurchaseId}, Transaction Id: {TransactionId}", eventTypeLowerCase, purchase.Id, webhook.Data.Id); throw new ArgumentException($"Event Type {eventTypeLowerCase} is not valid"); @@ -257,7 +259,7 @@ private async Task CompletePurchase(Purchase purchase) purchase.Status = PurchaseStatus.Completed; await _context.SaveChangesAsync(); - Log.Information("Completed purchase with Id {Id}, TransactionId {TransactionId}", purchase.Id, purchase.ExternalTransactionId); + _logger.LogInformation("Completed purchase with Id {Id}, TransactionId {TransactionId}", purchase.Id, purchase.ExternalTransactionId); await _emailService.SendInvoiceAsyncV2(purchase, purchase.PurchasedBy); } @@ -268,7 +270,7 @@ private async Task CancelPurchase(Purchase purchase) purchase.Status = PurchaseStatus.Cancelled; await _context.SaveChangesAsync(); - Log.Information("Purchase has been cancelled Purchase Id {PurchaseId}, Transaction Id {TransactionId}", + _logger.LogInformation("Purchase has been cancelled Purchase Id {PurchaseId}, Transaction Id {TransactionId}", purchase.Id, purchase.ExternalTransactionId); } @@ -346,21 +348,21 @@ public async Task RefundPurchase(int paymentId) // Does the purchase exist? if (purchase == null) { - Log.Error("No purchase was found by Purchase Id: {Id}", paymentId); + _logger.LogError("No purchase was found by Purchase Id: {Id}", paymentId); throw new EntityNotFoundException($"No purchase was found by Purchase Id: {paymentId}"); } // Is the purchase in a state where it can be refunded? if (purchase.Status != PurchaseStatus.Completed) { - Log.Error("Purchase {PurchaseId} is not in state Completed. Cannot refund", purchase.Id); + _logger.LogError("Purchase {PurchaseId} is not in state Completed. Cannot refund", purchase.Id); throw new IllegalUserOperationException($"Purchase {purchase.Id} is not in state Completed. Cannot refund"); } // Are all of the tickets unused (i.e. refundable)? if (purchase.Tickets.Any(t => !t.IsConsumable)) { - Log.Error("Purchase {PurchaseId} has tickets that are not unused. Cannot refund", purchase.Id); + _logger.LogError("Purchase {PurchaseId} has tickets that are not unused. Cannot refund", purchase.Id); throw new IllegalUserOperationException($"Purchase {purchase.Id} has tickets that are not unused. Cannot refund"); } @@ -370,7 +372,7 @@ public async Task RefundPurchase(int paymentId) var refundSuccess = await _mobilePayPaymentsService.RefundPayment(purchase, amountToRefund); if (!refundSuccess) { - Log.Error("Refund of Purchase {PurchaseId} failed", purchase.Id); + _logger.LogError("Refund of Purchase {PurchaseId} failed", purchase.Id); throw new InvalidOperationException($"Refund of Purchase {purchase.Id} failed"); } @@ -384,7 +386,7 @@ public async Task RefundPurchase(int paymentId) purchase.Status = PurchaseStatus.Refunded; await _context.SaveChangesAsync(); - Log.Information("Refunded Purchase {PurchaseId}", purchase.Id); + _logger.LogInformation("Refunded Purchase {PurchaseId}", purchase.Id); return new SimplePurchaseResponse { diff --git a/coffeecard/CoffeeCard.Library/Services/v2/TicketService.cs b/coffeecard/CoffeeCard.Library/Services/v2/TicketService.cs index dfced45c..265be827 100644 --- a/coffeecard/CoffeeCard.Library/Services/v2/TicketService.cs +++ b/coffeecard/CoffeeCard.Library/Services/v2/TicketService.cs @@ -7,7 +7,7 @@ using CoffeeCard.Models.DataTransferObjects.v2.Ticket; using CoffeeCard.Models.Entities; using Microsoft.EntityFrameworkCore; -using Serilog; +using Microsoft.Extensions.Logging; namespace CoffeeCard.Library.Services.v2 { @@ -15,11 +15,13 @@ public sealed class TicketService : ITicketService { private readonly CoffeeCardContext _context; private readonly IStatisticService _statisticService; + private readonly ILogger _logger; - public TicketService(CoffeeCardContext context, IStatisticService statisticService) + public TicketService(CoffeeCardContext context, IStatisticService statisticService, ILogger logger) { _context = context; _statisticService = statisticService; + _logger = logger; } public async Task IssueTickets(Purchase purchase) @@ -40,7 +42,7 @@ public async Task IssueTickets(Purchase purchase) await _context.Tickets.AddRangeAsync(tickets); await _context.SaveChangesAsync(); - Log.Information("Issued {NoTickets} Tickets for ProductId {ProductId}, PurchaseId {PurchaseId}", purchase.NumberOfTickets, purchase.ProductId, purchase.Id); + _logger.LogInformation("Issued {NoTickets} Tickets for ProductId {ProductId}, PurchaseId {PurchaseId}", purchase.NumberOfTickets, purchase.ProductId, purchase.Id); } public async Task> GetTicketsAsync(User user, bool includeUsed) @@ -65,7 +67,7 @@ public async Task> GetTicketsAsync(User user, bool i public async Task UseTicketAsync(User user, int productId) { - Log.Information("UserId {UserId} uses a ticket for ProductId {ProductId}", user.Id, productId); + _logger.LogInformation("UserId {UserId} uses a ticket for ProductId {ProductId}", user.Id, productId); var product = await GetProductIncludingMenuItemsFromIdAsync(productId); var ticket = await GetFirstTicketFromProductAsync(product, user.Id); @@ -92,7 +94,7 @@ public async Task UseTicketAsync(User user, int productId) public async Task UseTicketAsync(User user, int productId, int menuItemId) { - Log.Information($"UserId {user.Id} uses a ticket for MenuItemId {menuItemId} via ProductId {productId}"); + _logger.LogInformation("UserId {userId} uses a ticket for MenuItemId {menuItemId} via ProductId {productId}", user.Id, menuItemId, productId); var product = await GetProductIncludingMenuItemsFromIdAsync(productId); var ticket = await GetFirstTicketFromProductAsync(product, user.Id); diff --git a/coffeecard/CoffeeCard.Library/Services/v2/WebhookService.cs b/coffeecard/CoffeeCard.Library/Services/v2/WebhookService.cs index 426bb6f4..f6836fac 100644 --- a/coffeecard/CoffeeCard.Library/Services/v2/WebhookService.cs +++ b/coffeecard/CoffeeCard.Library/Services/v2/WebhookService.cs @@ -10,8 +10,7 @@ using CoffeeCard.Models.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; -using Microsoft.FeatureManagement; -using Serilog; +using Microsoft.Extensions.Logging; namespace CoffeeCard.Library.Services.v2 { @@ -26,6 +25,7 @@ public class WebhookService : IWebhookService private readonly IMobilePayWebhooksService _mobilePayWebhooksService; private readonly MobilePaySettingsV2 _mobilePaySettings; private readonly IMemoryCache _memoryCache; + private readonly ILogger _logger; public WebhookService(CoffeeCardContext context, IMobilePayWebhooksService mobilePayWebhooksService, MobilePaySettingsV2 mobilePaySettings, IMemoryCache memoryCache) @@ -54,7 +54,7 @@ public async Task GetSignatureKey() SlidingExpiration = TimeSpan.FromHours(2) }; - Log.Information("Set {SignatureKey} in Cache", MpSignatureKeyCacheKey); + _logger.LogInformation("Set {SignatureKey} in Cache", MpSignatureKeyCacheKey); _memoryCache.Set(MpSignatureKeyCacheKey, signatureKey, cacheExpiryOptions); } @@ -67,12 +67,12 @@ public async Task EnsureWebhookIsRegistered() if (await webhooks.AnyAsync()) { await SyncWebhook(await webhooks.FirstAsync()); - Log.Information("A MobilePay Webhook was already registered. Configuration has been synced"); + _logger.LogInformation("A MobilePay Webhook was already registered. Configuration has been synced"); } else { await RegisterWebhook(); - Log.Information("A MobilePay Webhook has been registered"); + _logger.LogInformation("A MobilePay Webhook has been registered"); } } diff --git a/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj b/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj index db7a4fd9..b682722d 100644 --- a/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj +++ b/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj @@ -7,7 +7,6 @@ - diff --git a/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayPaymentsService.cs b/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayPaymentsService.cs index 6a08fc82..edc97127 100644 --- a/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayPaymentsService.cs +++ b/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayPaymentsService.cs @@ -6,7 +6,7 @@ using CoffeeCard.Models.DataTransferObjects.v2.MobilePay; using CoffeeCard.Models.DataTransferObjects.v2.Purchase; using CoffeeCard.Models.Entities; -using Serilog; +using Microsoft.Extensions.Logging; namespace CoffeeCard.MobilePay.Service.v2 { @@ -14,11 +14,13 @@ public class MobilePayPaymentsService : IMobilePayPaymentsService { private readonly MobilePaySettingsV2 _mobilePaySettings; private readonly PaymentsApi _paymentsApi; + private readonly ILogger _logger; - public MobilePayPaymentsService(PaymentsApi paymentsApi, MobilePaySettingsV2 mobilePaySettings) + public MobilePayPaymentsService(PaymentsApi paymentsApi, MobilePaySettingsV2 mobilePaySettings, ILogger logger) { _paymentsApi = paymentsApi; _mobilePaySettings = mobilePaySettings; + _logger = logger; } public async Task InitiatePayment(MobilePayPaymentRequest paymentRequest) @@ -35,7 +37,7 @@ public async Task InitiatePayment(MobilePayPaymentReque Description = paymentRequest.Description }, null); - Log.Information("Initiated Payment with MobilePay PaymentId {TransactionId} of {OrerAmount} Oerer kr.", response.PaymentId.ToString(), paymentRequest.Amount); + _logger.LogInformation("Initiated Payment with MobilePay PaymentId {TransactionId} of {OrerAmount} Oerer kr.", response.PaymentId.ToString(), paymentRequest.Amount); return new MobilePayPaymentDetails(paymentRequest.OrderId.ToString(), response.MobilePayAppRedirectUri, response.PaymentId.ToString()); @@ -43,7 +45,7 @@ public async Task InitiatePayment(MobilePayPaymentReque catch (ApiException e) { var errorResponse = e.Result; - Log.Error(e, + _logger.LogError(e, "MobilePay InitiatePayment failed with HTTP {StatusCode}. ErrorCode: {ErrorCode} Message: {Message} CorrelationId: {CorrelationId}", e.StatusCode, errorResponse.Code, errorResponse.Message, errorResponse.CorrelationId); @@ -70,7 +72,7 @@ public async Task GetPayment(Guid paymentId) catch (ApiException e) { var errorResponse = e.Result; - Log.Error(e, + _logger.LogError(e, "MobilePay GetPayment failed with HTTP {StatusCode}. ErrorCode: {ErrorCode} Message: {Message} CorrelationId: {CorrelationId}", e.StatusCode, errorResponse.Code, errorResponse.Message, errorResponse.CorrelationId); @@ -105,15 +107,14 @@ public async Task RefundPayment(Purchase purchase, int amount) } catch (ApiException e) { - Log.Error(e, "MobilePay RefundPayment failed with HTTP {StatusCode}. Message: {Message}", e.StatusCode, e.Message); + _logger.LogError(e, "MobilePay RefundPayment failed with HTTP {StatusCode}. Message: {Message}", e.StatusCode, e.Message); return false; } - } catch (ApiException e) { var errorResponse = e.Result; - Log.Error(e, + _logger.LogError(e, "MobilePay RefundPayment failed with HTTP {StatusCode}. ErrorCode: {ErrorCode} Message: {Message} CorrelationId: {CorrelationId}", e.StatusCode, errorResponse.Code, errorResponse.Message, errorResponse.CorrelationId); throw new MobilePayApiException(e.StatusCode, errorResponse.Message, errorResponse.Code); @@ -132,7 +133,7 @@ public async Task CapturePayment(Guid paymentId, int amountInDanishKroner) catch (ApiException e) { var errorResponse = e.Result; - Log.Error(e, + _logger.LogError(e, "MobilePay CapturePayment failed with HTTP {StatusCode}. ErrorCode: {ErrorCode} Message: {Message} CorrelationId: {CorrelationId}", e.StatusCode, errorResponse.Code, errorResponse.Message, errorResponse.CorrelationId); @@ -156,7 +157,7 @@ public async Task CancelPayment(Guid paymentId) catch (ApiException e) { var errorResponse = e.Result; - Log.Error(e, + _logger.LogError(e, "MobilePay CancelPayment failed with HTTP {StatusCode}. ErrorCode: {ErrorCode} Message: {Message} CorrelationId: {CorrelationId}", e.StatusCode, errorResponse.Code, errorResponse.Message, errorResponse.CorrelationId); @@ -180,7 +181,7 @@ public async Task GetPaymentPoints() catch (ApiException e) { var errorResponse = e.Result; - Log.Error(e, + _logger.LogError(e, "MobilePay GetPaymentPoints failed with HTTP {StatusCode}. ErrorCode: {ErrorCode} Message: {Message} CorrelationId: {CorrelationId}", e.StatusCode, errorResponse.Code, errorResponse.Message, errorResponse.CorrelationId); @@ -202,7 +203,7 @@ public async Task GetPaymentPoints() private void LogMobilePayException(ApiException apiException) { - Log.Error(apiException, + _logger.LogError(apiException, "MobilePay InitiatePayment failed with HTTP {StatusCode}. Message: {Message}", apiException.StatusCode, apiException.Message); } diff --git a/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayWebhooksService.cs b/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayWebhooksService.cs index 749f169a..6aeef4fa 100644 --- a/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayWebhooksService.cs +++ b/coffeecard/CoffeeCard.MobilePay/Service/v2/MobilePayWebhooksService.cs @@ -5,7 +5,7 @@ using CoffeeCard.Common.Errors; using CoffeeCard.MobilePay.Exception.v2; using CoffeeCard.MobilePay.Generated.Api.WebhooksApi; -using Serilog; +using Microsoft.Extensions.Logging; using ApiException = CoffeeCard.MobilePay.Generated.Api.PaymentsApi.ApiException; namespace CoffeeCard.MobilePay.Service.v2 @@ -13,17 +13,19 @@ namespace CoffeeCard.MobilePay.Service.v2 public class MobilePayWebhooksService : IMobilePayWebhooksService { private readonly WebhooksApi _webhooksApi; + private readonly ILogger _logger; - public MobilePayWebhooksService(WebhooksApi webhooksApi) + public MobilePayWebhooksService(WebhooksApi webhooksApi, ILogger logger) { _webhooksApi = webhooksApi; + _logger = logger; } public async Task RegisterWebhook(string url, ICollection events) { try { - Log.Information("Register new webhook for Url: {url}, Events: {events}", url, events); + _logger.LogInformation("Register new webhook for Url: {url}, Events: {events}", url, events); return await _webhooksApi.CreateWebhookAsync(new CreateWebhookRequest { @@ -33,7 +35,7 @@ public async Task RegisterWebhook(string url, ICollection } catch (ApiException e) { - Log.Error(e, "Error calling Post Webhook with Url: {Url} and Events: {Events}. Http {StatusCode} {Message}", url, events, e.StatusCode, e.Message); + _logger.LogError(e, "Error calling Post Webhook with Url: {Url} and Events: {Events}. Http {StatusCode} {Message}", url, events, e.StatusCode, e.Message); throw new MobilePayApiException(e.StatusCode, e.Message); } } @@ -49,10 +51,10 @@ public async Task GetWebhook(Guid webhookId) switch (e.StatusCode) { case 404: - Log.Error("Webhook with Id: {Id} does not exist", webhookId); + _logger.LogError("Webhook with Id: {Id} does not exist", webhookId); throw new EntityNotFoundException(e.Message); default: - Log.Error(e, "Error calling Get Webhook with Id: {Id}. Http {StatusCode} {Message}", webhookId, e.StatusCode, e.Message); + _logger.LogError(e, "Error calling Get Webhook with Id: {Id}. Http {StatusCode} {Message}", webhookId, e.StatusCode, e.Message); throw new MobilePayApiException(e.StatusCode, e.Message); } } @@ -66,7 +68,7 @@ public async Task DeregisterWebhook(Guid webhookId) } catch (ApiException e) { - Log.Error(e, "Error calling Delete Webhook with Id: {Id}. Http {StatusCode} {Message}", webhookId, e.StatusCode, e.Message); + _logger.LogError(e, "Error calling Delete Webhook with Id: {Id}. Http {StatusCode} {Message}", webhookId, e.StatusCode, e.Message); throw new MobilePayApiException(e.StatusCode, e.Message); } } @@ -79,7 +81,7 @@ public async Task GetAllWebhooks() } catch (ApiException e) { - Log.Error("Error calling GetAllWebhooks. Http {StatusCode} {Message}", e.StatusCode, e.Message); + _logger.LogError("Error calling GetAllWebhooks. Http {StatusCode} {Message}", e.StatusCode, e.Message); throw new MobilePayApiException(e.StatusCode, e.Message); } } @@ -88,7 +90,7 @@ public async Task UpdateWebhook(Guid webhookId, string ur { var events3 = events.Select(MapEventsToEvents3).ToHashSet(); - Log.Information("Sync webhook subscription. Webhook: {webhookId}, Url: {url}, subscribed webhook events: {events}", webhookId, url, events3); + _logger.LogInformation("Sync webhook subscription. Webhook: {webhookId}, Url: {url}, subscribed webhook events: {events}", webhookId, url, events3); try { @@ -100,7 +102,7 @@ public async Task UpdateWebhook(Guid webhookId, string ur } catch (ApiException e) { - Log.Error(e, "Error calling Update Webhook with Id: {Id}. Http {StatusCode} {Message}", webhookId, e.StatusCode, e.Message); + _logger.LogError(e, "Error calling Update Webhook with Id: {Id}. Http {StatusCode} {Message}", webhookId, e.StatusCode, e.Message); throw new MobilePayApiException(e.StatusCode, e.Message); } diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs index 1c9d50de..6371aaa1 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs @@ -13,6 +13,7 @@ using CoffeeCard.Tests.Common.Builders; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.IdentityModel.Tokens; using Moq; using Xunit; @@ -43,7 +44,7 @@ public async Task RecoverUserGivenMalformedTokenReturnsFalse() // Act var accountService = new AccountService(AssertionContext, _environmentSettings, new Mock().Object, new Mock().Object, new Mock().Object, - new Mock().Object, new Mock().Object, _loginLimiterSettings); + new Mock().Object, new Mock().Object, _loginLimiterSettings, NullLogger.Instance); var result = await accountService.RecoverUserAsync("bogus", "3433"); // Assert @@ -73,7 +74,7 @@ public async Task RecoverUserGivenValidTokenReturnsTrue() var accountService = new AccountService(AssertionContext, _environmentSettings, tokenService.Object, new Mock().Object, new Mock().Object, - new Mock().Object, new Mock().Object, _loginLimiterSettings); + new Mock().Object, new Mock().Object, _loginLimiterSettings, NullLogger.Instance); var result = await accountService.RecoverUserAsync("valid", "3433"); @@ -108,7 +109,7 @@ public async Task RecoverUserGivenValidTokenUpdatesPasswordAndResetsUsersTokens( // Act var accountService = new AccountService(AssertionContext, _environmentSettings, tokenService.Object, new Mock().Object, new Mock().Object, - new Mock().Object, new Mock().Object, _loginLimiterSettings); + new Mock().Object, new Mock().Object, _loginLimiterSettings, NullLogger.Instance); await accountService.RecoverUserAsync("valid", "3433"); @@ -146,7 +147,7 @@ public async Task LoginGivenValidCredentialsReturnsToken() var accountService = new AccountService(AssertionContext, _environmentSettings, tokenService.Object, new Mock().Object, hasher.Object, - new Mock().Object, loginLimiter.Object, _loginLimiterSettings); + new Mock().Object, loginLimiter.Object, _loginLimiterSettings, NullLogger.Instance); var actualToken = accountService.Login(user.Email, user.Password, "2.1.0"); @@ -173,7 +174,7 @@ public async Task LoginRejectsAfterFiveFailedLogins() var accountService = new AccountService(AssertionContext, _environmentSettings, new Mock().Object, new Mock().Object, new HashService(), httpContextAccessor.Object, - loginLimiter.Object, _loginLimiterSettings); + loginLimiter.Object, _loginLimiterSettings, NullLogger.Instance); //Attempts to login Assert.Throws(() => accountService.Login(user.Email, wrongPass, "2.1.0")); @@ -199,7 +200,7 @@ public async Task LoginLimiterNotCalledWhenDisabled() // Act var accountService = new AccountService(AssertionContext, _environmentSettings, new Mock().Object, new Mock().Object, new HashService(), httpContextAccessor.Object, - loginLimiter.Object, _loginLimiterSettings); + loginLimiter.Object, _loginLimiterSettings, NullLogger.Instance); //Attempts to login Assert.Throws(() => accountService.Login(user.Email, wrongPass, "2.1.0")); @@ -226,7 +227,7 @@ public async Task LoginThrowsExceptionWhenLimitIsReached() _loginLimiterSettings.MaximumLoginAttemptsWithinTimeOut = 1; var accountService = new AccountService(AssertionContext, _environmentSettings, new Mock().Object, new Mock().Object, new HashService(), httpContextAccessor.Object, - new LoginLimiter(_loginLimiterSettings), _loginLimiterSettings); + new LoginLimiter(_loginLimiterSettings, NullLogger.Instance), _loginLimiterSettings, NullLogger.Instance); //Attempts to login with the wrong credentials Assert.Throws(() => accountService.Login(user.Email, wrongPass, "2.1.0")); @@ -259,7 +260,7 @@ public async Task LoginFailsIfEmailIsNotVerified() // Act var accountService = new AccountService(AssertionContext, _environmentSettings, new Mock().Object, new Mock().Object, new HashService(), httpContextAccessor.Object, - new LoginLimiter(_loginLimiterSettings), _loginLimiterSettings); + new LoginLimiter(_loginLimiterSettings, NullLogger.Instance), _loginLimiterSettings, NullLogger.Instance); // Login var exception = (ApiException)Record.Exception(() => accountService.Login(user.Email, somePass, "2.1.0")); @@ -288,7 +289,7 @@ public async Task LoginSucceedsIfEmailIsVerified() // Act var accountService = new AccountService(AssertionContext, _environmentSettings, new Mock().Object, new Mock().Object, hashService.Object, httpContextAccessor.Object, - new LoginLimiter(_loginLimiterSettings), _loginLimiterSettings); + new LoginLimiter(_loginLimiterSettings, NullLogger.Instance), _loginLimiterSettings, NullLogger.Instance); // Login var result = accountService.Login(user.Email, user.Password, "2.1.0"); @@ -307,7 +308,7 @@ public async Task LoginWithUnknownUserThrowsApiException() // Act var accountService = new AccountService(AssertionContext, _environmentSettings, new Mock().Object, new Mock().Object, new Mock().Object, httpContextAccessor.Object, - new LoginLimiter(_loginLimiterSettings), _loginLimiterSettings); + new LoginLimiter(_loginLimiterSettings, NullLogger.Instance), _loginLimiterSettings, NullLogger.Instance); // Login var exception = (ApiException)Record.Exception(() => accountService.Login("unknown email", "somePass", "2.1.0")); @@ -329,12 +330,12 @@ public async Task VerifyRegistrationReturnsFalseOnInvalidToken(string token) { TokenKey = "This is a long test token key" }; - var tokenService = new TokenService(identitySettings, new ClaimsUtilities(AssertionContext)); + var tokenService = new TokenService(identitySettings, new ClaimsUtilities(AssertionContext), NullLogger.Instance); httpContextAccessor.Setup(h => h.HttpContext).Returns(new DefaultHttpContext().HttpContext); var accountService = new AccountService(AssertionContext, _environmentSettings, tokenService, new Mock().Object, new Mock().Object, httpContextAccessor.Object, - new LoginLimiter(_loginLimiterSettings), _loginLimiterSettings); + new LoginLimiter(_loginLimiterSettings, NullLogger.Instance), _loginLimiterSettings, NullLogger.Instance); //Act & Assert await Assert.ThrowsAsync(() => accountService.VerifyRegistration(token)); @@ -350,12 +351,12 @@ public async Task VerifyRegistrationReturnsTrueGivenValidToken() { TokenKey = "SuperLongSigningKeySuperLongSigningKey" }; - var tokenService = new TokenService(identitySettings, new ClaimsUtilities(AssertionContext)); + var tokenService = new TokenService(identitySettings, new ClaimsUtilities(AssertionContext), NullLogger.Instance); httpContextAccessor.Setup(h => h.HttpContext).Returns(new DefaultHttpContext().HttpContext); var accountService = new AccountService(AssertionContext, _environmentSettings, tokenService, new Mock().Object, new Mock().Object, httpContextAccessor.Object, - new LoginLimiter(_loginLimiterSettings), _loginLimiterSettings); + new LoginLimiter(_loginLimiterSettings, NullLogger.Instance), _loginLimiterSettings, NullLogger.Instance); var user = UserBuilder.DefaultCustomer().WithIsVerified(false).Build(); var token = WriteTokenString(new List diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/LoginLimiterTests.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/LoginLimiterTests.cs index ba20c54b..4508d396 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/LoginLimiterTests.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/LoginLimiterTests.cs @@ -4,6 +4,7 @@ using CoffeeCard.Library.Services; using CoffeeCard.Models.Entities; using CoffeeCard.Tests.Common.Builders; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace CoffeeCard.Tests.Unit.Services @@ -23,7 +24,7 @@ public async Task LoginAllowsLoginsAfterTimeout() }; var user = UserBuilder.DefaultCustomer().Build(); - var loginLimiter = new LoginLimiter(loginLimiterSettings); + var loginLimiter = new LoginLimiter(loginLimiterSettings, NullLogger.Instance); const bool lockedOutExpected = false; const bool loginAllowedAgainExpected = true; @@ -56,7 +57,7 @@ public async Task LoginLockoutsTwice() }; var user = UserBuilder.DefaultCustomer().Build(); - var loginLimiter = new LoginLimiter(loginLimiterSettings); + var loginLimiter = new LoginLimiter(loginLimiterSettings, NullLogger.Instance); // Act var allowedLoginResults = new List(); diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs index 3c9ddb31..167f2327 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs @@ -10,6 +10,7 @@ using CoffeeCard.Library.Utils; using CoffeeCard.Models.Entities; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.IdentityModel.Tokens; using Xunit; @@ -49,7 +50,7 @@ public async Task ValidateTokenGivenInvalidTokenReturnsFalse() await using (context) { var claimsUtility = new ClaimsUtilities(context); - var tokenService = new TokenService(_identity, claimsUtility); + var tokenService = new TokenService(_identity, claimsUtility, NullLogger.Instance); // Act result = await tokenService.ValidateTokenIsUnusedAsync("Bogus token"); @@ -72,7 +73,7 @@ public async Task ValidateTokenGivenValidTokenReturnsTrue() await using (context) { var claimsUtility = new ClaimsUtilities(context); - var tokenService = new TokenService(_identity, claimsUtility); + var tokenService = new TokenService(_identity, claimsUtility, NullLogger.Instance); var token = tokenService.GenerateToken(claims); var userTokens = new List { new Token(token) }; @@ -111,7 +112,7 @@ public async Task ValidateTokenGivenInvalidSignedTokenReturnsFalse() var token = new JwtSecurityTokenHandler().WriteToken(jwt); var claimsUtility = new ClaimsUtilities(context); - var tokenService = new TokenService(_identity, claimsUtility); + var tokenService = new TokenService(_identity, claimsUtility, NullLogger.Instance); // Act var result = tokenService.ValidateToken(token); @@ -135,7 +136,7 @@ public async Task ValidateTokenGivenWelformedExpiredTokenReturnsFalse() await using (context) { var claimsUtility = new ClaimsUtilities(context); - var tokenService = new TokenService(_identity, claimsUtility); + var tokenService = new TokenService(_identity, claimsUtility, NullLogger.Instance); var key = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(_identity.TokenKey)); @@ -178,7 +179,7 @@ public async Task ValidateTokenGivenWelformedUsedTokenReturnsFalse() await using (context) { var claimsUtility = new ClaimsUtilities(context); - var tokenService = new TokenService(_identity, claimsUtility); + var tokenService = new TokenService(_identity, claimsUtility, NullLogger.Instance); var token = tokenService.GenerateToken(claims); diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/AccountServiceTest.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/AccountServiceTest.cs index 1201f4bd..50d0e2ba 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/AccountServiceTest.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/AccountServiceTest.cs @@ -16,9 +16,12 @@ using CoffeeCard.Models.Entities; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.IdentityModel.Tokens; using Moq; using Xunit; +using AccountService = CoffeeCard.Library.Services.v2.AccountService; namespace CoffeeCard.Tests.Unit.Services.v2 { @@ -54,7 +57,7 @@ public async Task GetAccountByClaimsReturnsUserClaimWithEmail() await context.SaveChangesAsync(); // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - new Mock().Object, new Mock().Object); + new Mock().Object, new Mock().Object, NullLogger.Instance); result = await accountService.GetAccountByClaimsAsync(claims); // Assert @@ -74,7 +77,7 @@ public async Task GetAccountByClaimsThrowsApiExceptionGivenInvalidClaim(IEnumera await context.SaveChangesAsync(); // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - new Mock().Object, new Mock().Object); + new Mock().Object, new Mock().Object, NullLogger.Instance); // Assert await Assert.ThrowsAsync(async () => await accountService.GetAccountByClaimsAsync(claims)); @@ -121,7 +124,7 @@ public async Task RegisterAccountReturnsUserOnValidInput(String name, String ema await context.SaveChangesAsync(); // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - emailService, hashService); + emailService, hashService, NullLogger.Instance); result = await accountService.RegisterAccountAsync(name, email, password, programmeId); // Assert @@ -149,8 +152,7 @@ public async Task RegisterAccountThrowsApiExceptionWithStatus409OnExistingEmail( // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - new Mock().Object, hashservice.Object); - + new Mock().Object, hashservice.Object, NullLogger.Instance); // Assert // Register the first user await accountService.RegisterAccountAsync("name", email, "pass", 1); @@ -167,7 +169,7 @@ public async Task RegisterAccountThrowsApiExceptionWithStatus400WhenGivenInvalid using var context = CreateTestCoffeeCardContextWithName(nameof(RegisterAccountThrowsApiExceptionWithStatus400WhenGivenInvalidProgrammeId)); // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - new Mock().Object, new Mock().Object); + new Mock().Object, new Mock().Object, NullLogger.Instance); // Assert var exception = await Assert.ThrowsAsync( @@ -210,7 +212,7 @@ public async Task RegisterAccountSendsVerificationEmailOnlyValidInput() await context.SaveChangesAsync(); // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - emailService, hashService); + emailService, hashService, NullLogger.Instance); await accountService.RegisterAccountAsync("name", "email", "password", 1); // Assert @@ -276,7 +278,7 @@ public async Task UpdateAccountUpdatesAllNonNullProperties(String name, String e // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - new Mock().Object, hashService); + new Mock().Object, hashService, NullLogger.Instance); var result = await accountService.UpdateAccountAsync(user, updateUserRequest); // Assert @@ -323,7 +325,7 @@ public async Task UpdateAccountThrowsApiExceptionOnInvalidProgrammeId() // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - new Mock().Object, new Mock().Object); + new Mock().Object, new Mock().Object, NullLogger.Instance); // Assert var exception = await Assert.ThrowsAsync(async () => await accountService.UpdateAccountAsync(user, updateUserRequest)); @@ -352,7 +354,7 @@ public async Task RequestAnonymizationSendsEmail() // Act var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, - emailService, new Mock().Object); + emailService, new Mock().Object, NullLogger.Instance); await accountService.RequestAnonymizationAsync(user); // Assert @@ -394,7 +396,7 @@ public async Task AnonymizeAccountRemovesIdentifyableInformationFromUser() // Act var accountService = new Library.Services.v2.AccountService(context, tokenServiceMock.Object, - new Mock().Object, new Mock().Object); + new Mock().Object, new Mock().Object, NullLogger.Instance); await accountService.AnonymizeAccountAsync("test"); var result = await context.Users.Where(u => u.Id == user.Id).FirstAsync(); @@ -432,7 +434,7 @@ public async Task ResendVerificationEmailWhenAccountIsNotVerified() // Act var emailService = new Mock(); - var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, emailService.Object, new Mock().Object); + var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, emailService.Object, new Mock().Object, NullLogger.Instance); await accountService.ResendAccountVerificationEmail(new ResendAccountVerificationEmailRequest { @@ -465,7 +467,7 @@ public async Task ResendVerificationEmailThrowsConflictExceptionWhenAccountIsAlr await context.SaveChangesAsync(); // Act - var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, new Mock().Object, new Mock().Object); + var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, new Mock().Object, new Mock().Object, NullLogger.Instance); await Assert.ThrowsAsync(async () => await accountService.ResendAccountVerificationEmail(new ResendAccountVerificationEmailRequest { @@ -480,7 +482,7 @@ public async Task ResendVerificationEmailThrowsEntityNotFoundExceptionWhenEmailD await using var context = CreateTestCoffeeCardContextWithName(nameof(ResendVerificationEmailThrowsEntityNotFoundExceptionWhenEmailDoesnotExist)); // Act - var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, new Mock().Object, new Mock().Object); + var accountService = new Library.Services.v2.AccountService(context, new Mock().Object, new Mock().Object, new Mock().Object, NullLogger.Instance); await Assert.ThrowsAsync(async () => await accountService.ResendAccountVerificationEmail(new ResendAccountVerificationEmailRequest { diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/ProductServiceTest.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/ProductServiceTest.cs index f44c5e98..a89d32e0 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/ProductServiceTest.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/ProductServiceTest.cs @@ -9,6 +9,7 @@ using CoffeeCard.Models.DataTransferObjects.v2.Products; using CoffeeCard.Models.Entities; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging.Abstractions; using Xunit; namespace CoffeeCard.Tests.Unit.Services.v2 @@ -58,7 +59,7 @@ await context.AddAsync(new ProductUserGroup await context.SaveChangesAsync(); - using var productService = new ProductService(context); + using var productService = new ProductService(context, NullLogger.Instance); await productService.UpdateProduct(1, new UpdateProductRequest() { @@ -98,7 +99,7 @@ public async Task AddProduct_Sets_Correct_UserGroups() await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings); - using var productService = new ProductService(context); + using var productService = new ProductService(context, NullLogger.Instance); var p = new AddProductRequest { @@ -136,7 +137,7 @@ public async Task GetAllProducts_Returns_Non_Visible_Products() await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings); - using var productService = new ProductService(context); + using var productService = new ProductService(context, NullLogger.Instance); var p1 = new AddProductRequest { @@ -184,7 +185,7 @@ public async Task GetAllProducts_Returns_Products_For_All_UserGroups() await using var context = new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings); - using var productService = new ProductService(context); + using var productService = new ProductService(context, NullLogger.Instance); var p1 = new AddProductRequest { diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs index 4071ec94..7234e2e3 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/v2/PurchaseServiceTests.cs @@ -11,6 +11,7 @@ using CoffeeCard.Models.DataTransferObjects.v2.Purchase; using CoffeeCard.Models.Entities; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; using PurchaseService = CoffeeCard.Library.Services.v2.PurchaseService; @@ -95,10 +96,10 @@ public async Task InitiatePurchaseCheckUserIsAllowedToPurchaseProductThrowsExcep var mobilePayService = new Mock(); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); var request = new InitiatePurchaseRequest { @@ -159,10 +160,10 @@ public async Task InitiatePurchasePaymentTypeMobilePay() var mobilePayService = new Mock(); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); var request = new InitiatePurchaseRequest { @@ -241,10 +242,10 @@ public async Task InitiatePurchaseAddsTicketsToUserWhenFree(Product product) var mobilePayService = new Mock(); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); var request = new InitiatePurchaseRequest { @@ -325,10 +326,10 @@ public async Task RefundPurchaseRefundsAPurchase(Product product) mobilePayService.Setup(mps => mps.RefundPayment(It.IsAny(), It.IsAny())) .ReturnsAsync(true); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); // Act var refund = await purchaseService.RefundPurchase(purchase.Id); @@ -391,10 +392,10 @@ public async Task RefundPurchaseThrowsExceptionWhenNotAllowed(Product product) mobilePayService.Setup(mps => mps.RefundPayment(It.IsAny(), It.IsAny())) .ReturnsAsync(true); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); // Act, Assert await Assert.ThrowsAsync(() => purchaseService.RefundPurchase(2)); @@ -455,10 +456,10 @@ public async Task RefundPurchaseThrowsExceptionWhenAlreadyRefunded(Product produ mobilePayService.Setup(mps => mps.RefundPayment(It.IsAny(), It.IsAny())) .ReturnsAsync(true); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); // Act, Assert await Assert.ThrowsAsync(() => purchaseService.RefundPurchase(product.Id)); @@ -516,10 +517,10 @@ public async Task GetPurchasesReturnsAllPurchasesForAUser(Product product) var mobilePayService = new Mock(); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); // act var result = await purchaseService.GetPurchases(user); @@ -580,10 +581,10 @@ public async Task GetPurchasesGivenAFaultyIdThrowsNotFoundException(Product prod var mobilePayService = new Mock(); var mailService = new Mock(); - var productService = new ProductService(context); - var ticketService = new TicketService(context, new Mock().Object); + var productService = new ProductService(context, NullLogger.Instance); + var ticketService = new TicketService(context, new Mock().Object, NullLogger.Instance); var purchaseService = new PurchaseService(context, mobilePayService.Object, ticketService, - mailService.Object, productService); + mailService.Object, productService, NullLogger.Instance); // Act & Assert await Assert.ThrowsAsync(() => purchaseService.GetPurchases(10)); diff --git a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj index cfa5c6fe..fae6e33f 100644 --- a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj +++ b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj @@ -39,6 +39,7 @@ +