using System.Text.Json; using line_gestao_api.Data; using line_gestao_api.Dtos; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace line_gestao_api.Controllers; [ApiController] [Route("api/historico")] [Authorize(Roles = "admin")] public class HistoricoController : ControllerBase { private readonly AppDbContext _db; public HistoricoController(AppDbContext db) { _db = db; } [HttpGet] public async Task>> GetAll( [FromQuery] string? pageName, [FromQuery] string? action, [FromQuery] string? entity, [FromQuery] Guid? userId, [FromQuery] string? search, [FromQuery] DateTime? dateFrom, [FromQuery] DateTime? dateTo, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { page = page < 1 ? 1 : page; pageSize = pageSize < 1 ? 20 : pageSize; var q = _db.AuditLogs.AsNoTracking(); if (!string.IsNullOrWhiteSpace(pageName)) { var p = pageName.Trim(); q = q.Where(x => EF.Functions.ILike(x.Page, $"%{p}%")); } if (!string.IsNullOrWhiteSpace(action)) { var a = action.Trim().ToUpperInvariant(); q = q.Where(x => x.Action == a); } if (!string.IsNullOrWhiteSpace(entity)) { var e = entity.Trim(); q = q.Where(x => EF.Functions.ILike(x.EntityName, $"%{e}%")); } if (userId.HasValue) { q = q.Where(x => x.UserId == userId.Value); } if (!string.IsNullOrWhiteSpace(search)) { var s = search.Trim(); q = q.Where(x => EF.Functions.ILike(x.UserName ?? "", $"%{s}%") || EF.Functions.ILike(x.UserEmail ?? "", $"%{s}%") || EF.Functions.ILike(x.EntityName ?? "", $"%{s}%") || EF.Functions.ILike(x.EntityLabel ?? "", $"%{s}%") || EF.Functions.ILike(x.EntityId ?? "", $"%{s}%") || EF.Functions.ILike(x.Page ?? "", $"%{s}%")); } if (dateFrom.HasValue) { var fromUtc = ToUtc(dateFrom.Value); q = q.Where(x => x.OccurredAtUtc >= fromUtc); } if (dateTo.HasValue) { var toUtc = ToUtc(dateTo.Value); if (dateTo.Value.TimeOfDay == TimeSpan.Zero) { toUtc = toUtc.Date.AddDays(1).AddTicks(-1); } q = q.Where(x => x.OccurredAtUtc <= toUtc); } var total = await q.CountAsync(); var items = await q .OrderByDescending(x => x.OccurredAtUtc) .ThenByDescending(x => x.Id) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); return Ok(new PagedResult { Page = page, PageSize = pageSize, Total = total, Items = items.Select(ToDto).ToList() }); } private static AuditLogDto ToDto(Models.AuditLog log) { return new AuditLogDto { Id = log.Id, OccurredAtUtc = log.OccurredAtUtc, Action = log.Action, Page = log.Page, EntityName = log.EntityName, EntityId = log.EntityId, EntityLabel = log.EntityLabel, UserId = log.UserId, UserName = log.UserName, UserEmail = log.UserEmail, RequestPath = log.RequestPath, RequestMethod = log.RequestMethod, IpAddress = log.IpAddress, Changes = ParseChanges(log.ChangesJson) }; } private static List ParseChanges(string? json) { if (string.IsNullOrWhiteSpace(json)) { return new List(); } try { return JsonSerializer.Deserialize>(json) ?? new List(); } catch { return new List(); } } private static DateTime ToUtc(DateTime value) { if (value.Kind == DateTimeKind.Utc) return value; if (value.Kind == DateTimeKind.Local) return value.ToUniversalTime(); return DateTime.SpecifyKind(value, DateTimeKind.Utc); } }