feat(udt-011): T400.10 — inject TimeProvider into all Application handlers
All command handlers that call domain mutators now inject TimeProvider via constructor and use _timeProvider.GetUtcNow().UtcDateTime as the explicit 'now' argument. Replaces previous direct DateTime.UtcNow usage.
This commit is contained in:
@@ -22,6 +22,7 @@ public sealed class LoginCommandHandler : ICommandHandler<LoginCommand, LoginRes
|
||||
private readonly IRolPermisoRepository _rolPermisoRepository;
|
||||
private readonly ISecurityEventLogger _security;
|
||||
private readonly ILogger<LoginCommandHandler> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public LoginCommandHandler(
|
||||
IUsuarioRepository repository,
|
||||
@@ -33,7 +34,8 @@ public sealed class LoginCommandHandler : ICommandHandler<LoginCommand, LoginRes
|
||||
AuthOptions authOptions,
|
||||
IRolPermisoRepository rolPermisoRepository,
|
||||
ISecurityEventLogger security,
|
||||
ILogger<LoginCommandHandler> logger)
|
||||
ILogger<LoginCommandHandler> logger,
|
||||
TimeProvider timeProvider)
|
||||
{
|
||||
_repository = repository;
|
||||
_hasher = hasher;
|
||||
@@ -45,6 +47,7 @@ public sealed class LoginCommandHandler : ICommandHandler<LoginCommand, LoginRes
|
||||
_rolPermisoRepository = rolPermisoRepository;
|
||||
_security = security;
|
||||
_logger = logger;
|
||||
_timeProvider = timeProvider;
|
||||
}
|
||||
|
||||
public async Task<LoginResponseDto> Handle(LoginCommand command)
|
||||
@@ -81,7 +84,7 @@ public sealed class LoginCommandHandler : ICommandHandler<LoginCommand, LoginRes
|
||||
// Generate and persist refresh token — only the hash hits the DB
|
||||
var rawRefresh = _refreshGenerator.Generate();
|
||||
var hash = TokenHasher.Sha256Base64Url(rawRefresh);
|
||||
var now = DateTime.UtcNow;
|
||||
var now = _timeProvider.GetUtcNow().UtcDateTime;
|
||||
var ttl = TimeSpan.FromDays(_authOptions.RefreshTokenDays);
|
||||
var entity = RefreshToken.IssueForNewFamily(
|
||||
usuario.Id, hash, now, ttl,
|
||||
|
||||
@@ -8,18 +8,24 @@ public sealed class LogoutCommandHandler : ICommandHandler<LogoutCommand, Logout
|
||||
{
|
||||
private readonly IRefreshTokenRepository _refreshRepo;
|
||||
private readonly ISecurityEventLogger _security;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public LogoutCommandHandler(IRefreshTokenRepository refreshRepo, ISecurityEventLogger security)
|
||||
public LogoutCommandHandler(
|
||||
IRefreshTokenRepository refreshRepo,
|
||||
ISecurityEventLogger security,
|
||||
TimeProvider timeProvider)
|
||||
{
|
||||
_refreshRepo = refreshRepo;
|
||||
_security = security;
|
||||
_timeProvider = timeProvider;
|
||||
}
|
||||
|
||||
public async Task<LogoutResponseDto> Handle(LogoutCommand command)
|
||||
{
|
||||
// Revoke all active tokens for the user across all families.
|
||||
// Idempotent: 0 rows affected is not an error.
|
||||
await _refreshRepo.RevokeAllActiveForUserAsync(command.UsuarioId, DateTime.UtcNow);
|
||||
var now = _timeProvider.GetUtcNow().UtcDateTime;
|
||||
await _refreshRepo.RevokeAllActiveForUserAsync(command.UsuarioId, now);
|
||||
await _security.LogAsync("logout", "success", actorUserId: command.UsuarioId);
|
||||
return new LogoutResponseDto(true, "Sesión cerrada correctamente");
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ public sealed class RefreshCommandHandler : ICommandHandler<RefreshCommand, Refr
|
||||
private readonly IClientContext _clientCtx;
|
||||
private readonly AuthOptions _authOptions;
|
||||
private readonly ISecurityEventLogger _security;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public RefreshCommandHandler(
|
||||
IRefreshTokenRepository refreshRepo,
|
||||
@@ -25,7 +26,8 @@ public sealed class RefreshCommandHandler : ICommandHandler<RefreshCommand, Refr
|
||||
IRefreshTokenGenerator refreshGenerator,
|
||||
IClientContext clientCtx,
|
||||
AuthOptions authOptions,
|
||||
ISecurityEventLogger security)
|
||||
ISecurityEventLogger security,
|
||||
TimeProvider timeProvider)
|
||||
{
|
||||
_refreshRepo = refreshRepo;
|
||||
_usuarioRepo = usuarioRepo;
|
||||
@@ -34,6 +36,7 @@ public sealed class RefreshCommandHandler : ICommandHandler<RefreshCommand, Refr
|
||||
_clientCtx = clientCtx;
|
||||
_authOptions = authOptions;
|
||||
_security = security;
|
||||
_timeProvider = timeProvider;
|
||||
}
|
||||
|
||||
public async Task<RefreshResponseDto> Handle(RefreshCommand command)
|
||||
@@ -60,7 +63,7 @@ public sealed class RefreshCommandHandler : ICommandHandler<RefreshCommand, Refr
|
||||
if (stored is null)
|
||||
throw new InvalidRefreshTokenException();
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var now = _timeProvider.GetUtcNow().UtcDateTime;
|
||||
|
||||
// 4. Reuse detection: already revoked → chain revocation and throw
|
||||
if (stored.IsRevoked)
|
||||
|
||||
Reference in New Issue
Block a user