Skip to content

Commit

Permalink
finish password reset API
Browse files Browse the repository at this point in the history
  • Loading branch information
GNUGradyn committed Nov 1, 2023
1 parent c72fec9 commit 7bdc88e
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 12 deletions.
20 changes: 20 additions & 0 deletions JournalyApiV2/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,26 @@ public async Task<IActionResult> ResetPassword([FromBody] string email)
{
// Ignore argumentException - this means the email was not found but we don't want the user to know that
}
catch (TooEarlyException ex)
{
throw new HttpBadRequestException(ex.Message);
}
return StatusCode(204);
}

[Route("submit-password-reset")]
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> SubmitPasswordReset([FromBody] ResetPasswordRequest request)
{
try
{
await _authService.SubmitPasswordResetAsync(request.Code, request.NewPassword);
}
catch (ArgumentException ex)
{
throw new HttpBadRequestException(ex.Message);
}
return StatusCode(204);
}
}
7 changes: 7 additions & 0 deletions JournalyApiV2/Models/Requests/ResetPasswordRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace JournalyApiV2.Models.Requests;

public class ResetPasswordRequest
{
public string Code { get; set; }
public string NewPassword { get; set; }
}
28 changes: 20 additions & 8 deletions JournalyApiV2/Services/BLL/AuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,15 +245,27 @@ public async Task ResetPasswordAsync(string email)
}
else
{
try
{
await _authDbService.ResetPasswordResetTimerAsync(Guid.Parse(user.Id));
}
catch (TooEarlyException ex)
{
throw new HttpBadRequestException(ex.Message);
}
await _authDbService.ResetPasswordResetTimerAsync(Guid.Parse(user.Id));
}
await _emailService.SendPasswordResetEmailAsync(user.Email, user.FirstName, user.LastName, code);
}

public async Task SubmitPasswordResetAsync(string code, string password)
{
var userGuid = await _authDbService.LookupPasswordResetAsync(code);
if (userGuid == null) throw new ArgumentException("Invalid password reset code");
var user = await _userManager.FindByIdAsync(userGuid.Value.ToString());
if (user == null) throw new Exception("User not found");
await _userManager.RemovePasswordAsync(user);
var result = await _userManager.AddPasswordAsync(user, password);
if (result.Succeeded)
{
await _authDbService.ResetPassword(userGuid.Value);
}
else
{
throw new Exception(string.Join(", ", result.Errors.Select(x => x.Description).ToArray()));
}
}

}
1 change: 1 addition & 0 deletions JournalyApiV2/Services/BLL/IAuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public interface IAuthService
Task VerifyEmailWithShortCode(Guid userId, string shortCode);
Task ResendVerificationEmailAsync(Guid userId);
Task ResetPasswordAsync(string email);
Task SubmitPasswordResetAsync(string code, string password);
}
16 changes: 16 additions & 0 deletions JournalyApiV2/Services/DAL/AuthDbService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,20 @@ public async Task ResetPasswordResetTimerAsync(Guid userId)
code.LastSent = DateTime.UtcNow;
await db.SaveChangesAsync();
}

public async Task<Guid?> LookupPasswordResetAsync(string code)
{
await using var db = _db.Journaly();
var codeObj = await db.PasswordResetCodes.SingleOrDefaultAsync(x => x.Code == code);

return codeObj?.User;
}

public async Task ResetPassword(Guid userId)
{
await using var db = _db.Journaly();
var toRemove = db.PasswordResetCodes.Where(x => x.User == userId);
db.RemoveRange(toRemove);
await db.SaveChangesAsync();
}
}
10 changes: 6 additions & 4 deletions JournalyApiV2/Services/DAL/IAuthDbService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ namespace JournalyApiV2.Services.DAL;

public interface IAuthDbService
{
Task<RefreshToken?> ExchangeRefreshTokenAsync(string token);
Task<Models.RefreshToken?> ExchangeRefreshTokenAsync(string token);
Task<Models.RefreshToken> NewRefreshTokenAsync(Guid user);
Task<Guid?> LookupRefreshTokenAsync(string token);
Task<RefreshToken> NewRefreshTokenAsync(Guid user);
Task VoidRefreshTokensAsync(params int[] tokenIds);
Task<RefreshToken[]> GetRefreshTokensAsync(Guid userId);
Task<Models.RefreshToken[]> GetRefreshTokensAsync(Guid userId);
Task<EmailVerification> GetOrCreateEmailVerificationCode(Guid userId);
Task ResetEmailVerificationTimerAsync(Guid userId);
Task<Guid?> GetUserByLongCode(string longCode);
Task VerifyUser(Guid user);
Task<bool> CheckShortCode(Guid userId, string shortCode);
Task ResetEmailVerificationTimerAsync(Guid userId);
Task<string?> GetPasswordResetCode(Guid userId);
Task<string> GeneratePasswordResetCode(Guid userId);
Task ResetPasswordResetTimerAsync(Guid userId);
Task<Guid?> LookupPasswordResetAsync(string code);
Task ResetPassword(Guid userId);
}

0 comments on commit 7bdc88e

Please sign in to comment.