Files
ROLAC/API/ROLAC.API/Entities/Logging/AuditLog.cs

73 lines
3.3 KiB
C#

namespace ROLAC.API.Entities.Logging;
/// <summary>
/// An append-only audit row recording a meaningful action: a data change (Create/Update/
/// Delete with before→after values), a security event (login, role/permission change), or a
/// key business action (check issued, expense approved, ...). Does NOT inherit AuditableEntity.
/// </summary>
public class AuditLog
{
public long Id { get; set; }
public DateTimeOffset Timestamp { get; set; }
public LogLevelEnum Level { get; set; } = LogLevelEnum.Information;
/// <summary>One of <see cref="AuditActions"/>.</summary>
public string Action { get; set; } = null!;
/// <summary>One of <see cref="AuditCategories"/> — drives the UI grouping.</summary>
public string Category { get; set; } = null!;
public string? EntityName { get; set; }
/// <summary>String to cover int, Guid and string primary keys uniformly.</summary>
public string? EntityId { get; set; }
/// <summary>JSON <c>{ "before": {...}, "after": {...} }</c> (jsonb column); sensitive fields masked.</summary>
public string? Changes { get; set; }
/// <summary>Human-readable one-liner, e.g. "Check #1042 issued to Acme — $1,200.00".</summary>
public string? Summary { get; set; }
public string? UserId { get; set; }
/// <summary>Denormalized actor email — survives user deletion and avoids a join in the grid.</summary>
public string? UserEmail { get; set; }
public string? IpAddress { get; set; }
public string? CorrelationId { get; set; }
}
/// <summary>Canonical audit action names (stored verbatim in <see cref="AuditLog.Action"/>).</summary>
public static class AuditActions
{
public const string Create = "Create";
public const string Update = "Update";
public const string Delete = "Delete";
public const string Login = "Login";
public const string Logout = "Logout";
public const string LoginFailed = "LoginFailed";
public const string RoleChanged = "RoleChanged";
public const string PasswordChanged = "PasswordChanged";
public const string UserDeactivated = "UserDeactivated";
public const string PermissionChanged = "PermissionChanged";
public const string CheckIssued = "CheckIssued";
public const string CheckVoided = "CheckVoided";
public const string ExpenseApproved = "ExpenseApproved";
public const string StatementFinalized = "StatementFinalized";
public static readonly IReadOnlyList<string> All =
[
Create, Update, Delete, Login, Logout, LoginFailed, RoleChanged,
PasswordChanged, UserDeactivated, PermissionChanged, CheckIssued,
CheckVoided, ExpenseApproved, StatementFinalized,
];
}
/// <summary>Top-level audit grouping (stored verbatim in <see cref="AuditLog.Category"/>).</summary>
public static class AuditCategories
{
public const string DataChange = "DataChange";
public const string Security = "Security";
public const string Business = "Business";
public static readonly IReadOnlyList<string> All = [DataChange, Security, Business];
}