From 86fa272c842e69910f28fea444b21965806bcdcb Mon Sep 17 00:00:00 2001 From: Aaron Po Date: Mon, 16 Feb 2026 00:02:07 -0500 Subject: [PATCH] Refactor authentication payloads and services for registration and login processes --- .../API/API.Core/Contracts/Auth/AuthDTO.cs | 10 +++++- .../API.Core/Controllers/AuthController.cs | 17 ++++------ .../Service.Auth.Tests/LoginService.test.cs | 1 + .../Service/Service.Auth/ILoginService.cs | 2 +- .../Service/Service.Auth/IRegisterService.cs | 32 +++++++++++++---- src/Core/Service/Service.Auth/LoginService.cs | 10 ++++-- .../Service/Service.Auth/RegisterService.cs | 34 ++++++++++++++----- 7 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/Core/API/API.Core/Contracts/Auth/AuthDTO.cs b/src/Core/API/API.Core/Contracts/Auth/AuthDTO.cs index 5b9b19d..0d74d16 100644 --- a/src/Core/API/API.Core/Contracts/Auth/AuthDTO.cs +++ b/src/Core/API/API.Core/Contracts/Auth/AuthDTO.cs @@ -3,9 +3,17 @@ using Org.BouncyCastle.Asn1.Cms; namespace API.Core.Contracts.Auth; -public record AuthPayload( +public record LoginPayload( Guid UserAccountId, string Username, string RefreshToken, string AccessToken ); + +public record RegistrationPayload( + Guid UserAccountId, + string Username, + string RefreshToken, + string AccessToken, + bool ConfirmationEmailSent +); \ No newline at end of file diff --git a/src/Core/API/API.Core/Controllers/AuthController.cs b/src/Core/API/API.Core/Controllers/AuthController.cs index 2715896..34e44cd 100644 --- a/src/Core/API/API.Core/Controllers/AuthController.cs +++ b/src/Core/API/API.Core/Controllers/AuthController.cs @@ -16,7 +16,7 @@ namespace API.Core.Controllers [FromBody] RegisterRequest req ) { - AuthServiceReturn rtn = await register.RegisterAsync( + var rtn = await register.RegisterAsync( new UserAccount { UserAccountId = Guid.Empty, @@ -29,15 +29,12 @@ namespace API.Core.Controllers req.Password ); - var response = new ResponseBody + var response = new ResponseBody { Message = "User registered successfully.", - Payload = new AuthPayload( - rtn.UserAccount.UserAccountId, - rtn.UserAccount.Username, + Payload = new RegistrationPayload(rtn.UserAccount.UserAccountId, rtn.UserAccount.Username, rtn.RefreshToken, - rtn.AccessToken - ), + rtn.AccessToken, rtn.EmailSent), }; return Created("/", response); } @@ -48,10 +45,10 @@ namespace API.Core.Controllers var rtn = await login.LoginAsync(req.Username, req.Password); return Ok( - new ResponseBody + new ResponseBody { Message = "Logged in successfully.", - Payload = new AuthPayload( + Payload = new LoginPayload( rtn.UserAccount.UserAccountId, rtn.UserAccount.Username, rtn.RefreshToken, @@ -61,4 +58,4 @@ namespace API.Core.Controllers ); } } -} +} \ No newline at end of file diff --git a/src/Core/Service/Service.Auth.Tests/LoginService.test.cs b/src/Core/Service/Service.Auth.Tests/LoginService.test.cs index 12f2e20..3d5cffb 100644 --- a/src/Core/Service/Service.Auth.Tests/LoginService.test.cs +++ b/src/Core/Service/Service.Auth.Tests/LoginService.test.cs @@ -7,6 +7,7 @@ using Moq; namespace Service.Auth.Tests; + public class LoginServiceTest { private readonly Mock _authRepoMock; diff --git a/src/Core/Service/Service.Auth/ILoginService.cs b/src/Core/Service/Service.Auth/ILoginService.cs index 0e0fa33..9554a36 100644 --- a/src/Core/Service/Service.Auth/ILoginService.cs +++ b/src/Core/Service/Service.Auth/ILoginService.cs @@ -4,5 +4,5 @@ namespace Service.Auth; public interface ILoginService { - Task LoginAsync(string username, string password); + Task LoginAsync(string username, string password); } diff --git a/src/Core/Service/Service.Auth/IRegisterService.cs b/src/Core/Service/Service.Auth/IRegisterService.cs index 1cda5dc..a126c09 100644 --- a/src/Core/Service/Service.Auth/IRegisterService.cs +++ b/src/Core/Service/Service.Auth/IRegisterService.cs @@ -2,16 +2,34 @@ using Domain.Entities; namespace Service.Auth; -public record AuthServiceReturn( - UserAccount UserAccount, - string RefreshToken, - string AccessToken -); +public record RegisterServiceReturn +{ + public bool IsAuthenticated { get; init; } + public bool EmailSent { get; init; } + public UserAccount UserAccount { get; init; } + public string AccessToken { get; init; } = string.Empty; + public string RefreshToken { get; init; } = string.Empty; + + public RegisterServiceReturn(UserAccount userAccount, string accessToken, string refreshToken, bool emailSent) + { + IsAuthenticated = true; + UserAccount = userAccount; + AccessToken = accessToken; + RefreshToken = refreshToken; + EmailSent = true; + } + + public RegisterServiceReturn(UserAccount userAccount) + { + IsAuthenticated = false; + UserAccount = userAccount; + } +} public interface IRegisterService { - Task RegisterAsync( + Task RegisterAsync( UserAccount userAccount, string password ); -} +} \ No newline at end of file diff --git a/src/Core/Service/Service.Auth/LoginService.cs b/src/Core/Service/Service.Auth/LoginService.cs index 1e0115b..4cd0bb3 100644 --- a/src/Core/Service/Service.Auth/LoginService.cs +++ b/src/Core/Service/Service.Auth/LoginService.cs @@ -5,13 +5,19 @@ using Infrastructure.Repository.Auth; namespace Service.Auth; +public record LoginServiceReturn( + UserAccount UserAccount, + string RefreshToken, + string AccessToken +); + public class LoginService( IAuthRepository authRepo, IPasswordInfrastructure passwordInfrastructure, ITokenService tokenService ) : ILoginService { - public async Task LoginAsync( + public async Task LoginAsync( string username, string password ) @@ -35,6 +41,6 @@ public class LoginService( string accessToken = tokenService.GenerateAccessToken(user); string refreshToken = tokenService.GenerateRefreshToken(user); - return new AuthServiceReturn(user, refreshToken, accessToken); + return new LoginServiceReturn(user, refreshToken, accessToken); } } diff --git a/src/Core/Service/Service.Auth/RegisterService.cs b/src/Core/Service/Service.Auth/RegisterService.cs index ee3fa1a..c51135a 100644 --- a/src/Core/Service/Service.Auth/RegisterService.cs +++ b/src/Core/Service/Service.Auth/RegisterService.cs @@ -4,6 +4,7 @@ using Infrastructure.Email; using Infrastructure.Email.Templates.Rendering; using Infrastructure.PasswordHashing; using Infrastructure.Repository.Auth; +using Microsoft.Extensions.Logging; using Service.Emails; namespace Service.Auth; @@ -31,7 +32,7 @@ public class RegisterService( } } - public async Task RegisterAsync( + public async Task RegisterAsync( UserAccount userAccount, string password ) @@ -53,12 +54,29 @@ public class RegisterService( var accessToken = tokenService.GenerateAccessToken(createdUser); var refreshToken = tokenService.GenerateRefreshToken(createdUser); - // send confirmation email - await emailService.SendRegistrationEmailAsync( - createdUser, - "some-confirmation-token" - ); + if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(refreshToken)) + { + return new RegisterServiceReturn(createdUser); + } - return new AuthServiceReturn(createdUser, refreshToken, accessToken); + + bool emailSent = false; + try + { + // send confirmation email + await emailService.SendRegistrationEmailAsync( + createdUser, + "some-confirmation-token" + ); + + emailSent = true; + } + catch + { + // ignored + } + + + return new RegisterServiceReturn(createdUser, accessToken, refreshToken, emailSent); } -} +} \ No newline at end of file