62 lines
2.1 KiB
C#
62 lines
2.1 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
/// <summary>
|
|
/// Clinical audit log query (Admin only).
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/v1/audit-logs")]
|
|
[Produces("application/json")]
|
|
[AuthorizePermission(ClinicalPermissions.AuditRead)]
|
|
public class AuditLogsController : ControllerBase
|
|
{
|
|
private readonly AppDbContext _db;
|
|
|
|
public AuditLogsController(AppDbContext db) => _db = db;
|
|
|
|
/// <summary>Query clinical audit logs with optional filters.</summary>
|
|
[HttpGet]
|
|
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
|
public async Task<IActionResult> List(
|
|
[FromQuery] string? entityType,
|
|
[FromQuery] Guid? entityId,
|
|
[FromQuery] Guid? userId,
|
|
[FromQuery] string? action,
|
|
[FromQuery] DateTimeOffset? from,
|
|
[FromQuery] DateTimeOffset? to,
|
|
[FromQuery] int page = 1,
|
|
[FromQuery] int pageSize = 50)
|
|
{
|
|
pageSize = Math.Clamp(pageSize, 1, 100);
|
|
var query = _db.ClinicalAuditLogs.AsNoTracking().AsQueryable();
|
|
|
|
if (!string.IsNullOrEmpty(entityType))
|
|
query = query.Where(a => a.EntityType == entityType);
|
|
if (entityId.HasValue)
|
|
query = query.Where(a => a.EntityId == entityId);
|
|
if (userId.HasValue)
|
|
query = query.Where(a => a.UserId == userId);
|
|
if (!string.IsNullOrEmpty(action))
|
|
query = query.Where(a => a.Action.ToDbString() == action);
|
|
if (from.HasValue)
|
|
query = query.Where(a => a.CreatedAt >= from);
|
|
if (to.HasValue)
|
|
query = query.Where(a => a.CreatedAt <= to);
|
|
|
|
var total = await query.CountAsync();
|
|
var items = await query
|
|
.OrderByDescending(a => a.CreatedAt)
|
|
.Skip((page - 1) * pageSize)
|
|
.Take(pageSize)
|
|
.ToListAsync();
|
|
|
|
return Ok(ApiResponse<object>.Ok(new
|
|
{
|
|
items,
|
|
page,
|
|
pageSize,
|
|
totalCount = total,
|
|
totalPages = (int)Math.Ceiling(total / (double)pageSize)
|
|
}));
|
|
}
|
|
} |