feat(udt-011): T400.30 — inject TimeProvider into Infrastructure critical services

AuditLogger, SecurityEventLogger: inject TimeProvider and use
_timeProvider.GetUtcNow().UtcDateTime for occurredAt timestamps.
JwtService: inject TimeProvider; use GetUtcNow() for token IssuedAt/Expires.
DI: update JwtService factory to pass sp.GetRequiredService<TimeProvider>().
Repositories: remove ?? DateTime.UtcNow fallback in UpdateAsync since callers
always provide FechaModificacion via domain mutators.
This commit is contained in:
2026-04-18 10:12:24 -03:00
parent d69da5ff4c
commit a9838427a4
7 changed files with 21 additions and 10 deletions

View File

@@ -12,15 +12,18 @@ public sealed class AuditLogger : IAuditLogger
private readonly IAuditContext _context;
private readonly IAuditEventRepository _repo;
private readonly IOptions<AuditOptions> _options;
private readonly TimeProvider _timeProvider;
public AuditLogger(
IAuditContext context,
IAuditEventRepository repo,
IOptions<AuditOptions> options)
IOptions<AuditOptions> options,
TimeProvider timeProvider)
{
_context = context;
_repo = repo;
_options = options;
_timeProvider = timeProvider;
}
public async Task LogAsync(
@@ -42,7 +45,7 @@ public sealed class AuditLogger : IAuditLogger
: _context.CorrelationId;
await _repo.InsertAsync(
occurredAt: DateTime.UtcNow,
occurredAt: _timeProvider.GetUtcNow().UtcDateTime,
actorUserId: _context.ActorUserId,
actorRoleId: _context.ActorRoleId,
action: action,

View File

@@ -11,15 +11,18 @@ public sealed class SecurityEventLogger : ISecurityEventLogger
private readonly ISecurityEventRepository _repo;
private readonly IAuditContext _context;
private readonly IOptions<AuditOptions> _options;
private readonly TimeProvider _timeProvider;
public SecurityEventLogger(
ISecurityEventRepository repo,
IAuditContext context,
IOptions<AuditOptions> options)
IOptions<AuditOptions> options,
TimeProvider timeProvider)
{
_repo = repo;
_context = context;
_options = options;
_timeProvider = timeProvider;
}
public async Task LogAsync(
@@ -37,7 +40,7 @@ public sealed class SecurityEventLogger : ISecurityEventLogger
: JsonSanitizer.Sanitize(metadata, _options.Value.SanitizedKeys);
await _repo.InsertAsync(
occurredAt: DateTime.UtcNow,
occurredAt: _timeProvider.GetUtcNow().UtcDateTime,
actorUserId: actorUserId,
attemptedUsername: attemptedUsername,
sessionId: sessionId,

View File

@@ -68,7 +68,10 @@ public static class DependencyInjection
});
services.AddScoped<IJwtService>(sp =>
new JwtService(sp.GetRequiredService<RSA>(), sp.GetRequiredService<JwtOptions>()));
new JwtService(
sp.GetRequiredService<RSA>(),
sp.GetRequiredService<JwtOptions>(),
sp.GetRequiredService<TimeProvider>()));
services.AddScoped<IPasswordHasher, BcryptPasswordHasher>();
services.AddSingleton<IRefreshTokenGenerator, RefreshTokenGenerator>();
services.AddHttpContextAccessor();

View File

@@ -85,7 +85,7 @@ public sealed class MedioRepository : IMedioRepository
Tipo = (int)m.Tipo,
m.PlataformaEmpresaId,
m.Activo,
FechaModificacion = m.FechaModificacion ?? DateTime.UtcNow,
FechaModificacion = m.FechaModificacion,
m.Id,
});
}

View File

@@ -96,7 +96,7 @@ public sealed class PuntoDeVentaRepository : IPuntoDeVentaRepository
pdv.Nombre,
pdv.Descripcion,
pdv.Activo,
FechaModificacion = pdv.FechaModificacion ?? DateTime.UtcNow,
FechaModificacion = pdv.FechaModificacion,
pdv.Id,
});
}

View File

@@ -84,7 +84,7 @@ public sealed class SeccionRepository : ISeccionRepository
s.Nombre,
s.Tipo,
s.Activo,
FechaModificacion = s.FechaModificacion ?? DateTime.UtcNow,
FechaModificacion = s.FechaModificacion,
s.Id,
});
}

View File

@@ -11,11 +11,13 @@ public sealed class JwtService : IJwtService
{
private readonly RSA _rsa;
private readonly JwtOptions _options;
private readonly TimeProvider _timeProvider;
public JwtService(RSA rsa, JwtOptions options)
public JwtService(RSA rsa, JwtOptions options, TimeProvider timeProvider)
{
_rsa = rsa;
_options = options;
_timeProvider = timeProvider;
}
/// <inheritdoc/>
@@ -62,7 +64,7 @@ public sealed class JwtService : IJwtService
new("rol", usuario.Rol),
};
var now = DateTime.UtcNow;
var now = _timeProvider.GetUtcNow().UtcDateTime;
var descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),