Files
2026-09-20 16:21:15 +07:00

49 lines
1.7 KiB
C#

using MediatR;
using mws.backend.dotnet.application.Common;
using mws.backend.dotnet.domain.Audit;
namespace mws.backend.dotnet.application.Audit;
public class AuditLogBehavior<TRequest, TResponse>(
IUnitOfWork uow,
ICurrentUser currentUser,
IAuditContext auditContext)
: IPipelineBehavior<TRequest, TResponse> where TRequest : notnull
{
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken ct)
{
if (request is not IAuditableRequest auditable)
{
return await next();
}
auditContext.EntityId = null;
auditContext.EntityName = null;
var response = await next();
uow.ActionLogs.Add(new ActionLog
{
Id = Guid.NewGuid(),
ActorUserId = currentUser.UserId ?? Guid.Empty,
ActorUsername = TruncateRequired(currentUser.Username ?? "unknown", 100),
Action = auditable.Action,
EntityType = auditable.EntityType,
EntityId = auditable.EntityId ?? auditContext.EntityId ?? (response as IHasEntityId)?.EntityId,
EntityName = Truncate(auditable.EntityName ?? auditContext.EntityName, 255),
IpAddress = currentUser.IpAddress,
UserAgent = currentUser.UserAgent,
CreatedAt = DateTimeOffset.UtcNow,
});
await uow.SaveChangesAsync(ct);
return response;
}
private static string TruncateRequired(string value, int max) =>
value.Length <= max ? value : value[..max];
private static string? Truncate(string? value, int max) =>
value is null || value.Length <= max ? value : value[..max];
}