Remove repository tests, usages of registration dto used in repo

This commit is contained in:
Aaron Po
2026-08-20 20:55:47 -04:00
parent 1855041910
commit e60683a415
29 changed files with 341 additions and 1351 deletions

View File

@@ -0,0 +1,10 @@
using Features.Auth.Dtos;
using MediatR;
namespace Features.Auth.Commands.Login;
/// <summary>
/// Authenticates a user using their username and password and issues new tokens. Bound directly
/// from the request body of <c>POST /api/auth/login</c>.
/// </summary>
public record LoginCommand(string Username, string Password) : IRequest<LoginPayload>;

View File

@@ -0,0 +1,43 @@
using Domain.Entities;
using Domain.Exceptions;
using Features.Auth.Dtos;
using Features.Auth.Repository;
using Features.Auth.Services;
using Infrastructure.PasswordHashing;
using MediatR;
namespace Features.Auth.Commands.Login;
/// <summary>
/// Handles <see cref="LoginCommand" /> by verifying credentials and issuing access/refresh tokens.
/// </summary>
public class LoginHandler(
IAuthRepository authRepo,
IPasswordInfrastructure passwordInfrastructure,
ITokenService tokenService
) : IRequestHandler<LoginCommand, LoginPayload>
{
/// <exception cref="UnauthorizedException">
/// Thrown when the username does not match any account, the account has no active credential,
/// or the supplied password does not match the stored hash.
/// </exception>
public async Task<LoginPayload> Handle(LoginCommand request, CancellationToken cancellationToken)
{
UserAccount user =
await authRepo.GetUserByUsernameAsync(request.Username)
?? throw new UnauthorizedException("Invalid username or password.");
// @todo handle expired passwords
UserCredential activeCred =
await authRepo.GetActiveCredentialByUserAccountIdAsync(user.UserAccountId)
?? throw new UnauthorizedException("Invalid username or password.");
if (!passwordInfrastructure.Verify(request.Password, activeCred.Hash))
throw new UnauthorizedException("Invalid username or password.");
string accessToken = tokenService.GenerateAccessToken(user);
string refreshToken = tokenService.GenerateRefreshToken(user);
return new LoginPayload(user.UserAccountId, user.Username, refreshToken, accessToken);
}
}

View File

@@ -0,0 +1,14 @@
using FluentValidation;
namespace Features.Auth.Commands.Login;
/// <summary>Validates that <see cref="LoginCommand.Username" /> and <see cref="LoginCommand.Password" /> are present.</summary>
public class LoginValidator : AbstractValidator<LoginCommand>
{
public LoginValidator()
{
RuleFor(x => x.Username).NotEmpty().WithMessage("Username is required");
RuleFor(x => x.Password).NotEmpty().WithMessage("Password is required");
}
}

View File

@@ -34,14 +34,18 @@ public class RegisterUserHandler(
string hashed = passwordInfrastructure.Hash(request.Password);
UserAccount createdUser = await authRepo.RegisterUserAsync(
new UserRegistrationDto(
request.Username,
request.FirstName,
request.LastName,
request.Email,
request.DateOfBirth,
hashed
)
new UserAccount
{
Username = request.Username,
FirstName = request.FirstName,
LastName = request.LastName,
DateOfBirth = request.DateOfBirth,
Email = request.Email,
UserCredential = new UserCredential
{
Hash = hashed,
}
}
);
string accessToken = tokenService.GenerateAccessToken(createdUser);