Add signup/signin with backend-issued JWT (Argon2 passwords in SurrealDB), role-based authorization policies, per-user data access levels, consent register and read audit log. Protect user endpoints and record sensitive reads.
48 lines
1.3 KiB
C#
48 lines
1.3 KiB
C#
using SurrealDb.Net;
|
|
using TarninaHub.Application.Abstractions;
|
|
|
|
namespace TarninaHub.Infrastructure.Persistence;
|
|
|
|
public sealed class AuditLogService : IAuditLogService
|
|
{
|
|
private readonly ISurrealDbClient _client;
|
|
|
|
public AuditLogService(ISurrealDbClient client)
|
|
{
|
|
_client = client;
|
|
}
|
|
|
|
public async Task RecordAsync(
|
|
string? actorId,
|
|
string action,
|
|
string target,
|
|
IReadOnlyDictionary<string, object?> context,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var (actorTable, actorIdPart) = actorId is null
|
|
? ("user", (string?)null)
|
|
: SurrealRecordId.Split(actorId);
|
|
|
|
var actorExpression = actorId is null
|
|
? "NONE"
|
|
: "type::record($actorTable, $actorId)";
|
|
|
|
var parameters = new Dictionary<string, object?>
|
|
{
|
|
["action"] = action,
|
|
["target"] = target,
|
|
["context"] = context,
|
|
["actorTable"] = actorTable,
|
|
["actorId"] = actorIdPart,
|
|
};
|
|
|
|
var response = await _client.RawQuery(
|
|
$"CREATE audit_log SET actor = {actorExpression}, action = $action, " +
|
|
"target = $target, context = $context, at = time::now();",
|
|
parameters,
|
|
cancellationToken);
|
|
|
|
response.EnsureAllOks();
|
|
}
|
|
}
|