using Domain.Exceptions; using Infrastructure.Repository.Auth; using Service.Emails; namespace Service.Auth; /// /// Handles confirmation of newly registered user accounts and resending of confirmation emails. /// /// Repository used to look up and confirm user accounts. /// Service used to generate and validate confirmation tokens. /// Service used to send confirmation-related emails. public class ConfirmationService( IAuthRepository authRepository, ITokenService tokenService, IEmailService emailService ) : IConfirmationService { /// /// Validates a confirmation token and marks the corresponding user account as confirmed. /// /// The confirmation token issued to the user, typically delivered via email. /// /// A containing the UTC timestamp of confirmation and the confirmed user's ID. /// /// /// Thrown when the confirmation token is invalid or expired, or when the associated user account cannot be found. /// public async Task ConfirmUserAsync( string confirmationToken ) { var validatedToken = await tokenService.ValidateConfirmationTokenAsync( confirmationToken ); var user = await authRepository.ConfirmUserAccountAsync( validatedToken.UserId ); if (user == null) { throw new UnauthorizedException("User account not found"); } return new ConfirmationServiceReturn( DateTime.UtcNow, user.UserAccountId ); } /// /// Resends the account confirmation email to a user, generating a fresh confirmation token. /// /// The unique identifier of the user requesting the resend. /// A task that completes once the operation has finished. /// /// Returns silently without sending an email if the user does not exist (to prevent user enumeration) /// or if the user's account is already verified. /// public async Task ResendConfirmationEmailAsync(Guid userId) { var user = await authRepository.GetUserByIdAsync(userId); if (user == null) { return; // Silent return to prevent user enumeration } if (await authRepository.IsUserVerifiedAsync(userId)) { return; // Already confirmed, no-op } var confirmationToken = tokenService.GenerateConfirmationToken(user); await emailService.SendResendConfirmationEmailAsync(user, confirmationToken); } }