From 6ab01830f332c0460f75e54b33bfea378e8b3e35 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 27 Sep 2026 10:11:56 +0200 Subject: [PATCH] Added audit log endpoint --- .../Governance/GetAuditLogsEndpoint.cs | 35 +++++++++++++++++++ .../Services/Shared/AuditService.cs | 35 ++++++++++++++++++- .../PostFundManagement.Domain.csproj | 4 +-- 3 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 PostFundManagement.Api/Endpoints/Governance/GetAuditLogsEndpoint.cs diff --git a/PostFundManagement.Api/Endpoints/Governance/GetAuditLogsEndpoint.cs b/PostFundManagement.Api/Endpoints/Governance/GetAuditLogsEndpoint.cs new file mode 100644 index 0000000..3421316 --- /dev/null +++ b/PostFundManagement.Api/Endpoints/Governance/GetAuditLogsEndpoint.cs @@ -0,0 +1,35 @@ +using PostFundManagement.Application.Extensions; +using PostFundManagement.Application.Services.Shared; +using PostFundManagement.Domain; +using PostFundManagement.Domain.Abstractions; +using PostFundManagement.Domain.Extensions; +using PostFundManagement.Domain.Models; +using PostFundManagement.Domain.Security; +using Problems = Microsoft.AspNetCore.Mvc.ProblemDetails; + +namespace PostFundManagement.Api.Endpoints.Governance; + +[ApiVersionTarget(1)] +public sealed class GetAuditLogsEndpoint : IEndpoint +{ + public void Map(IEndpointRouteBuilder builder) + { + builder.MapPost("api/governance/auditlog", async (Pagination pagination, AuditService service, + CancellationToken cancellationToken = default) => + await service.GetAuditLogsAsync(pagination, cancellationToken) switch + { + { IsSuccess: true, Value: var logs } => Results.Ok(logs), + var r => Results.InternalServerError(r.Errors.ToProblems()) + }) + .WithDescription("Retrieves audit logs based on pagination parameters") + .RequireAuthorization(Constants.MainScope) + .WithName(typeof(GetAuditLogsEndpoint).ToEndpointName()) + .MapToApiVersion(new ApiVersion(1)) + .Produces(StatusCodes.Status200OK) + .Produces(StatusCodes.Status401Unauthorized) + .Produces(StatusCodes.Status400BadRequest) + .Produces(StatusCodes.Status500InternalServerError) + .WithTags(EndpointTags.Governance) + .CacheOutput(); + } +} diff --git a/PostFundManagement.Application/Services/Shared/AuditService.cs b/PostFundManagement.Application/Services/Shared/AuditService.cs index 25ce543..41d6641 100644 --- a/PostFundManagement.Application/Services/Shared/AuditService.cs +++ b/PostFundManagement.Application/Services/Shared/AuditService.cs @@ -1,11 +1,44 @@ -using PostFundManagement.Domain.Abstractions; +using PostFundManagement.Domain; +using PostFundManagement.Domain.Abstractions; using PostFundManagement.Domain.Errors; +using PostFundManagement.Domain.Extensions; +using PostFundManagement.Domain.Models; using PostFundManagement.Infrastructure.Database; namespace PostFundManagement.Application.Services.Shared; public sealed class AuditService(IDbContextFactory contextFactory, ITenantContextService tenantContextService) : IService { + public async Task> GetAuditLogsAsync(CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(async () => + { + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + + var pagination = new Pagination { Page = 1, PageSize = 500, Index = 1 }; + + var logs = await context.AuditLogs + .OrderByDescending(o => o.Id) + .Skip((pagination.Page - 1) * pagination.PageSize) + .Take(pagination.PageSize) + .ToListAsync(cancellationToken); + + return Result.Ok(logs.Select(p => p.Map()).ToArray()); + })); + + public async Task> GetAuditLogsAsync(Pagination pagination, CancellationToken cancellationToken = default) => + await Result.Try((Func>>)(async () => + { + await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); + + var logs = await context.AuditLogs + .OrderByDescending(o => o.Id) + .Skip((pagination.Page - 1) * pagination.PageSize) + .Take(pagination.PageSize) + .ToListAsync(cancellationToken); + + return Result.Ok(logs.Select(p => p.Map()).ToArray()); + })); + public async Task LogActionAsync(string entityId, string entityName, string action, string[] changes, Guid performedBy, CancellationToken cancellationToken = default) => await Result.Try((Func>)(async () => { diff --git a/PostFundManagement.Domain/PostFundManagement.Domain.csproj b/PostFundManagement.Domain/PostFundManagement.Domain.csproj index 7222148..e1690af 100644 --- a/PostFundManagement.Domain/PostFundManagement.Domain.csproj +++ b/PostFundManagement.Domain/PostFundManagement.Domain.csproj @@ -10,11 +10,11 @@ - 1701;1702;MA0048 + 1701;1702;MA0048;MA0051 - 1701;1702;MA0048 + 1701;1702;MA0048;MA0051