88 lines
3.0 KiB
C#
88 lines
3.0 KiB
C#
using BCrypt.Net;
|
|
using Knot.Contracts.Auth.Application.Abstractions;
|
|
using Knot.Contracts.Auth.Application.Auth.DTOs;
|
|
using Knot.Contracts.Settings.Application.Abstractions;
|
|
using Knot.Contracts.Settings.Application.DTOs;
|
|
using Knot.Modules.Auth.Domain;
|
|
using Knot.Shared.Kernel;
|
|
|
|
namespace Knot.Modules.Auth.Application.Users.Register;
|
|
|
|
public sealed record RegisterUserCommand(
|
|
string Username,
|
|
string Password,
|
|
string DisplayName,
|
|
string? Email,
|
|
string? Bio) : ICommand<AuthResponseDto>;
|
|
|
|
internal sealed class RegisterUserCommandHandler : ICommandHandler<RegisterUserCommand, AuthResponseDto>
|
|
{
|
|
private readonly IUserRepository _userRepository;
|
|
private readonly IAuthUnitOfWork _unitOfWork;
|
|
private readonly ISystemSettings _settings;
|
|
private readonly IJwtTokenProvider _tokenProvider;
|
|
|
|
public RegisterUserCommandHandler(
|
|
IUserRepository userRepository,
|
|
IAuthUnitOfWork unitOfWork,
|
|
ISystemSettings settings,
|
|
IJwtTokenProvider tokenProvider)
|
|
{
|
|
_userRepository = userRepository;
|
|
_unitOfWork = unitOfWork;
|
|
_settings = settings;
|
|
_tokenProvider = tokenProvider;
|
|
}
|
|
|
|
public async Task<Result<AuthResponseDto>> Handle(RegisterUserCommand request, CancellationToken cancellationToken)
|
|
{
|
|
if (!_settings.Current.EnableRegistration)
|
|
{
|
|
return Result.Failure<AuthResponseDto>(AuthErrors.IdentityRegistrationDisabled);
|
|
}
|
|
|
|
if (!await _userRepository.IsUsernameUniqueAsync(request.Username, cancellationToken))
|
|
{
|
|
return Result.Failure<AuthResponseDto>(AuthErrors.IdentityUsernameNotUnique);
|
|
}
|
|
|
|
string passwordHash = BCrypt.Net.BCrypt.HashPassword(request.Password);
|
|
|
|
var user = User.Create(
|
|
request.Username,
|
|
passwordHash,
|
|
request.DisplayName,
|
|
request.Email,
|
|
request.Bio);
|
|
|
|
var repoImpl = _userRepository as Infrastructure.Persistence.UserRepository;
|
|
repoImpl?.Add(user);
|
|
|
|
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
|
|
|
// Get the saved user as contract
|
|
var userContract = await _userRepository.GetByUsernameAsync(request.Username, cancellationToken);
|
|
if (userContract == null)
|
|
{
|
|
return Result.Failure<AuthResponseDto>(AuthErrors.IdentityRegistrationFailed);
|
|
}
|
|
|
|
string token = _tokenProvider.Generate(userContract.Id, userContract.Username, userContract.DisplayName, userContract.Avatar);
|
|
string refreshToken = _tokenProvider.GenerateRefreshToken();
|
|
DateTime refreshExpiry = _tokenProvider.GetRefreshTokenExpiry();
|
|
|
|
userContract.SetRefreshToken(refreshToken, refreshExpiry);
|
|
await _userRepository.UpdateAsync(userContract, cancellationToken);
|
|
|
|
return Result.Success(new AuthResponseDto
|
|
{
|
|
AccessToken = token,
|
|
RefreshToken = refreshToken,
|
|
UserId = userContract.Id,
|
|
Username = userContract.Username,
|
|
DisplayName = userContract.DisplayName
|
|
});
|
|
}
|
|
}
|
|
|