93 lines
2.9 KiB
C#
93 lines
2.9 KiB
C#
using System.Security.Cryptography;
|
|
using Application.Auth.DTOs;
|
|
using Domain.Entities;
|
|
using Domain.Ports.Repositories;
|
|
using Domain.ValueObjects;
|
|
using MediatR;
|
|
|
|
namespace Application.Auth.Commands;
|
|
|
|
public record RegisterCommand(
|
|
string Username,
|
|
string Password,
|
|
string? Name = null,
|
|
string? Email = null
|
|
) : IRequest<AuthResponse>;
|
|
|
|
public class RegisterCommandHandler(
|
|
IUserRepository userRepository,
|
|
IStudentRepository studentRepository,
|
|
IPasswordService passwordService,
|
|
IJwtService jwtService,
|
|
IUnitOfWork unitOfWork
|
|
) : IRequestHandler<RegisterCommand, AuthResponse>
|
|
{
|
|
public async Task<AuthResponse> Handle(RegisterCommand request, CancellationToken ct)
|
|
{
|
|
// Check if username already exists
|
|
if (await userRepository.ExistsAsync(request.Username, ct))
|
|
return new AuthResponse(false, Error: "El nombre de usuario ya existe");
|
|
|
|
// Validate password strength
|
|
if (request.Password.Length < 6)
|
|
return new AuthResponse(false, Error: "La contrasena debe tener al menos 6 caracteres");
|
|
|
|
// Create student if name and email are provided
|
|
Student? student = null;
|
|
if (!string.IsNullOrWhiteSpace(request.Name) && !string.IsNullOrWhiteSpace(request.Email))
|
|
{
|
|
try
|
|
{
|
|
var email = Email.Create(request.Email);
|
|
student = new Student(request.Name, email);
|
|
studentRepository.Add(student);
|
|
await unitOfWork.SaveChangesAsync(ct);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return new AuthResponse(false, Error: ex.Message);
|
|
}
|
|
}
|
|
|
|
// Generate recovery code (12 chars alphanumeric)
|
|
var recoveryCode = GenerateRecoveryCode();
|
|
var recoveryCodeHash = passwordService.HashPassword(recoveryCode);
|
|
|
|
// Create user with recovery code
|
|
var passwordHash = passwordService.HashPassword(request.Password);
|
|
var user = User.Create(
|
|
request.Username,
|
|
passwordHash,
|
|
recoveryCodeHash,
|
|
UserRoles.Student,
|
|
student?.Id
|
|
);
|
|
|
|
await userRepository.AddAsync(user, ct);
|
|
await unitOfWork.SaveChangesAsync(ct);
|
|
|
|
// Generate token
|
|
var token = jwtService.GenerateToken(user);
|
|
|
|
return new AuthResponse(
|
|
Success: true,
|
|
Token: token,
|
|
User: new UserInfo(
|
|
user.Id,
|
|
user.Username,
|
|
user.Role,
|
|
user.StudentId,
|
|
student?.Name
|
|
),
|
|
RecoveryCode: recoveryCode // Show only once!
|
|
);
|
|
}
|
|
|
|
private static string GenerateRecoveryCode()
|
|
{
|
|
const string chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
var bytes = RandomNumberGenerator.GetBytes(12);
|
|
return new string(bytes.Select(b => chars[b % chars.Length]).ToArray());
|
|
}
|
|
}
|