diff --git a/JournalyApiV2/Services/BLL/AuthService.cs b/JournalyApiV2/Services/BLL/AuthService.cs index 8bea73e..d0aba36 100644 --- a/JournalyApiV2/Services/BLL/AuthService.cs +++ b/JournalyApiV2/Services/BLL/AuthService.cs @@ -10,6 +10,7 @@ using JournalyApiV2.Data.Models; using JournalyApiV2.Models; using JournalyApiV2.Models.Responses; +using JournalyApiV2.Pipeline; using JournalyApiV2.Services.DAL; using Microsoft.AspNetCore.Identity; using Microsoft.IdentityModel.Tokens; @@ -237,7 +238,22 @@ public async Task ResetPasswordAsync(string email) { var user = await _userManager.FindByEmailAsync(email); if (user == null) throw new ArgumentException("User not found"); - var code = await _authDbService.GetOrGeneratePasswordResetCode(Guid.Parse(user.Id)); + var code = await _authDbService.GetPasswordResetCode(Guid.Parse(user.Id)); + if (code == null) + { + code = await _authDbService.GeneratePasswordResetCode(Guid.Parse(user.Id)); + } + else + { + try + { + await _authDbService.ResetPasswordResetTimerAsync(Guid.Parse(user.Id)); + } + catch (TooEarlyException ex) + { + throw new HttpBadRequestException(ex.Message); + } + } await _emailService.SendPasswordResetEmailAsync(user.Email, user.FirstName, user.LastName, code); } } \ No newline at end of file diff --git a/JournalyApiV2/Services/DAL/AuthDbService.cs b/JournalyApiV2/Services/DAL/AuthDbService.cs index 89fbe70..fafe868 100644 --- a/JournalyApiV2/Services/DAL/AuthDbService.cs +++ b/JournalyApiV2/Services/DAL/AuthDbService.cs @@ -136,12 +136,13 @@ public async Task ResetEmailVerificationTimerAsync(Guid userId) var code = await db.EmailVerificationCodes.SingleOrDefaultAsync(x => x.User == userId); if (code == null) throw new ArgumentException("No user verification found for given ID"); if (code.LastSent.AddSeconds(60) >= DateTime.UtcNow) - throw new TooEarlyException($"Too early to resend: Please wait an additional {Convert.ToInt16((code.LastSent.AddSeconds(60) - DateTime.UtcNow).TotalSeconds)} seconds"); + throw new TooEarlyException( + $"Too early to resend: Please wait an additional {Convert.ToInt16((code.LastSent.AddSeconds(60) - DateTime.UtcNow).TotalSeconds)} seconds"); code.LastSent = DateTime.UtcNow; await db.SaveChangesAsync(); } -public async Task GetUserByLongCode(string longCode) + public async Task GetUserByLongCode(string longCode) { await using var db = _db.Journaly(); return (await db.EmailVerificationCodes.SingleOrDefaultAsync(x => x.LongCode == longCode))?.User; @@ -158,27 +159,47 @@ public async Task VerifyUser(Guid user) public async Task CheckShortCode(Guid userId, string shortCode) { await using var db = _db.Journaly(); - var code = await db.EmailVerificationCodes.SingleOrDefaultAsync(x => x.User == userId && x.ShortCode == shortCode); + var code = await db.EmailVerificationCodes.SingleOrDefaultAsync(x => + x.User == userId && x.ShortCode == shortCode); return code != null; } - public async Task GetOrGeneratePasswordResetCode(Guid userId) + public async Task GetPasswordResetCode(Guid userId) { await using var db = _db.Journaly(); var code = await db.PasswordResetCodes.SingleOrDefaultAsync(x => x.User == userId); - if (code == null) + return code?.Code; + } + + public async Task GeneratePasswordResetCode(Guid userId) + { + await using var db = _db.Journaly(); + var code = await db.PasswordResetCodes.SingleOrDefaultAsync(x => x.User == userId); + if (code != null) return code.Code; + + code = new PasswordResetCode { - code = new PasswordResetCode - { - User = userId, - Code = GenerateSecureOpaqueToken(), - LastSent = DateTime.UtcNow - }; - await db.PasswordResetCodes.AddAsync(code); - await db.SaveChangesAsync(); - } + Code = GenerateSecureOpaqueToken(), + LastSent = DateTime.UtcNow, + User = userId + }; + + await db.PasswordResetCodes.AddAsync(code); + await db.SaveChangesAsync(); return code.Code; } + + public async Task ResetPasswordResetTimerAsync(Guid userId) + { + await using var db = _db.Journaly(); + var code = await db.PasswordResetCodes.SingleOrDefaultAsync(x => x.User == userId); + if (code == null) throw new ArgumentException("User not found"); + if (code.LastSent.AddSeconds(60) >= DateTime.UtcNow) + throw new TooEarlyException( + $"Too early to send another reset, please try again in {Convert.ToInt16((code.LastSent.AddSeconds(60) - DateTime.UtcNow).TotalSeconds)} seconds"); + code.LastSent = DateTime.UtcNow; + await db.SaveChangesAsync(); + } } \ No newline at end of file diff --git a/JournalyApiV2/Services/DAL/IAuthDbService.cs b/JournalyApiV2/Services/DAL/IAuthDbService.cs index a1c64dc..fa8d488 100644 --- a/JournalyApiV2/Services/DAL/IAuthDbService.cs +++ b/JournalyApiV2/Services/DAL/IAuthDbService.cs @@ -14,5 +14,7 @@ public interface IAuthDbService Task VerifyUser(Guid user); Task CheckShortCode(Guid userId, string shortCode); Task ResetEmailVerificationTimerAsync(Guid userId); - Task GetOrGeneratePasswordResetCode(Guid userId); + Task GetPasswordResetCode(Guid userId); + Task GeneratePasswordResetCode(Guid userId); + Task ResetPasswordResetTimerAsync(Guid userId); } \ No newline at end of file