feat: 添加管理员密码修改功能

This commit is contained in:
2026-04-27 23:16:31 +08:00
parent c161660b51
commit 9c4f22ff97
8 changed files with 135 additions and 0 deletions
@@ -9,4 +9,6 @@ public interface IAuthService
Task LogoutAsync(string token, CancellationToken cancellationToken = default);
Task<AuthenticatedUser?> ValidateTokenAsync(string token, CancellationToken cancellationToken = default);
Task ChangePasswordAsync(Guid userId, ChangePasswordRequest request, CancellationToken cancellationToken = default);
}
@@ -109,6 +109,8 @@ public interface IUserAccountRepository
Task<UserAccount?> GetByUsernameAsync(string username, CancellationToken cancellationToken = default);
Task AddAsync(UserAccount userAccount, CancellationToken cancellationToken = default);
void Update(UserAccount userAccount);
}
public interface IUserSessionRepository
@@ -28,3 +28,10 @@ public sealed class LoginResponse
public required AuthenticatedUser User { get; init; }
}
public sealed class ChangePasswordRequest
{
public string CurrentPassword { get; set; } = string.Empty;
public string NewPassword { get; set; } = string.Empty;
}
@@ -112,4 +112,31 @@ public sealed class AuthService : IAuthService
ExpiresAt = session.ExpiresAt
};
}
public async Task ChangePasswordAsync(Guid userId, ChangePasswordRequest request, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(request);
if (string.IsNullOrWhiteSpace(request.CurrentPassword) || string.IsNullOrWhiteSpace(request.NewPassword))
{
throw new InvalidOperationException("当前密码和新密码不能为空。");
}
if (request.NewPassword.Length < 6)
{
throw new InvalidOperationException("新密码长度不能少于 6 位。");
}
var user = await _userAccountRepository.GetByIdAsync(userId, cancellationToken)
?? throw new InvalidOperationException("用户不存在。");
if (!PasswordHasher.Verify(request.CurrentPassword, user.PasswordHash))
{
throw new InvalidOperationException("当前密码不正确。");
}
user.UpdatePassword(PasswordHasher.Hash(request.NewPassword));
_userAccountRepository.Update(user);
await _unitOfWork.SaveChangesAsync(cancellationToken);
}
}