feature: RBAC + Clinical Audit Logging

This commit is contained in:
voltsrage
2026-06-21 15:46:55 +08:00
parent a43db52813
commit 5af6ab490e
83 changed files with 4281 additions and 70 deletions
@@ -5,11 +5,16 @@ public class AlertThresholdService : IAlertThresholdService
{
private readonly AppDbContext _db;
private readonly IConnectionMultiplexer _redis;
private readonly IAuditService _audit;
public AlertThresholdService(AppDbContext db, IConnectionMultiplexer redis)
public AlertThresholdService(
AppDbContext db,
IConnectionMultiplexer redis,
IAuditService audit)
{
_db = db;
_redis = redis;
_audit = audit;
}
public async Task<AlertThreshold> CreateAsync(AlertThresholdRequest req)
@@ -35,6 +40,19 @@ public class AlertThresholdService : IAlertThresholdService
_db.AlertThresholds.Add(threshold);
await _db.SaveChangesAsync();
await _audit.WriteAsync(
AuditAction.ThresholdCreated,
"AlertThreshold",
threshold.Id,
newValue: new
{
threshold.ObservationCode,
threshold.CriticalLow,
threshold.WarningLow,
threshold.WarningHigh,
threshold.CriticalHigh
});
await InvalidateCacheAsync(threshold.ObservationCode);
return threshold;
}
@@ -56,6 +74,16 @@ public class AlertThresholdService : IAlertThresholdService
if (threshold is null)
throw new NotFoundException("Threshold not found.", "THRESHOLD_NOT_FOUND");
var previous = new
{
threshold.ObservationCode,
threshold.CriticalLow,
threshold.WarningLow,
threshold.WarningHigh,
threshold.CriticalHigh,
threshold.SuppressionWindowMinutes
};
threshold.DisplayName = req.DisplayName;
threshold.Unit = req.Unit;
threshold.CriticalLow = req.CriticalLow;
@@ -64,6 +92,22 @@ public class AlertThresholdService : IAlertThresholdService
threshold.CriticalHigh = req.CriticalHigh;
await _db.SaveChangesAsync();
await _audit.WriteAsync(
AuditAction.ThresholdUpdated,
"AlertThreshold",
threshold.Id,
previousValue: previous,
newValue: new
{
threshold.ObservationCode,
threshold.CriticalLow,
threshold.WarningLow,
threshold.WarningHigh,
threshold.CriticalHigh,
threshold.SuppressionWindowMinutes
});
await InvalidateCacheAsync(threshold.ObservationCode);
return threshold;
}