Merge branch 'feature/change-password'

This commit is contained in:
Chris Chen
2026-06-23 20:36:26 -07:00
21 changed files with 579 additions and 13 deletions
+44
View File
@@ -159,6 +159,50 @@ public class AuthService : IAuthService
}
}
// -------------------------------------------------------------------------
// Change password
// -------------------------------------------------------------------------
public async Task<IdentityResult> ChangePasswordAsync(
string userId, string currentPassword, string newPassword, string? currentRawRefreshToken)
{
var user = await _userManager.FindByIdAsync(userId);
if (user is null)
return IdentityResult.Failed(new IdentityError
{
Code = "UserNotFound",
Description = "User not found.",
});
var result = await _userManager.ChangePasswordAsync(user, currentPassword, newPassword);
if (!result.Succeeded)
return result;
// Revoke the user's other active sessions; keep the current one alive.
var currentHash = currentRawRefreshToken is null
? null
: _tokenService.HashToken(currentRawRefreshToken);
var otherTokens = await _db.RefreshTokens
.Where(rt => rt.UserId == userId
&& rt.RevokedAt == null
&& (currentHash == null || rt.TokenHash != currentHash))
.ToListAsync();
foreach (var token in otherTokens)
token.RevokedAt = DateTime.UtcNow;
await _db.SaveChangesAsync();
_audit.Write(
AuditActions.PasswordChanged, AuditCategories.Security, LogLevelEnum.Information,
entityName: nameof(AppUser), entityId: user.Id,
summary: $"Password changed: {user.Email}",
userId: user.Id, userEmail: user.Email);
return result;
}
// -------------------------------------------------------------------------
// Private helpers
// -------------------------------------------------------------------------