begin: PHI Column Encryption
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
public class PhiAccessLogService : IPhiAccessLogService
|
||||
{
|
||||
private readonly AppDbContext _db;
|
||||
private readonly ICurrentUserService _currentUser;
|
||||
private readonly IHttpContextAccessor _http;
|
||||
private readonly PhiEncryptionOptions _options;
|
||||
|
||||
public PhiAccessLogService(
|
||||
AppDbContext db,
|
||||
ICurrentUserService currentUser,
|
||||
IHttpContextAccessor http,
|
||||
IOptions<PhiEncryptionOptions> options)
|
||||
{
|
||||
_db = db;
|
||||
_currentUser = currentUser;
|
||||
_http = http;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
public async Task LogViewAsync(Guid patientId, string resourcePath) =>
|
||||
await WriteAsync(PhiAccessType.View, patientId, resourcePath);
|
||||
|
||||
public async Task LogCreateAsync(Guid patientId, string resourcePath) =>
|
||||
await WriteAsync(PhiAccessType.Create, patientId, resourcePath);
|
||||
|
||||
public async Task LogUpdateAsync(Guid patientId, string resourcePath) =>
|
||||
await WriteAsync(PhiAccessType.Update, patientId, resourcePath);
|
||||
|
||||
public async Task LogListAsync(string resourcePath, int resultCount, string? searchQuery = null)
|
||||
{
|
||||
if (!_options.LogListAccess)
|
||||
return;
|
||||
|
||||
var accessType = string.IsNullOrWhiteSpace(searchQuery)
|
||||
? PhiAccessType.List
|
||||
: PhiAccessType.Search;
|
||||
|
||||
await WriteAsync(accessType, null, resourcePath, resultCount, searchQuery);
|
||||
}
|
||||
|
||||
private async Task WriteAsync(
|
||||
PhiAccessType accessType,
|
||||
Guid? patientId,
|
||||
string resourcePath,
|
||||
int? resultCount = null,
|
||||
string? searchQuery = null)
|
||||
{
|
||||
if (!_currentUser.IsAuthenticated || _currentUser.UserId is null)
|
||||
return; // machine/integration paths may skip — Phase 31 Integration role should still auth
|
||||
|
||||
_db.PhiAccessLogs.Add(new PhiAccessLog
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
AccessType = accessType,
|
||||
PatientId = patientId,
|
||||
UserId = _currentUser.UserId.Value,
|
||||
UserDisplayName = _currentUser.DisplayName ?? _currentUser.Username ?? "Unknown",
|
||||
ResourcePath = resourcePath,
|
||||
SearchQueryHash = searchQuery is null ? null : HashQuery(searchQuery),
|
||||
ResultCount = resultCount,
|
||||
IpAddress = _currentUser.IpAddress,
|
||||
CorrelationId = _http.HttpContext?.Items["CorrelationId"]?.ToString(),
|
||||
AccessedAt = DateTimeOffset.UtcNow
|
||||
});
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static string HashQuery(string query)
|
||||
{
|
||||
var hash = SHA256.HashData(Encoding.UTF8.GetBytes(query.Trim().ToLowerInvariant()));
|
||||
return Convert.ToHexString(hash).ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user