59 lines
1.8 KiB
C#
59 lines
1.8 KiB
C#
|
|
using Dapper;
|
||
|
|
using SIGCM2.Application.Audit;
|
||
|
|
using SIGCM2.Infrastructure.Persistence;
|
||
|
|
|
||
|
|
namespace SIGCM2.Infrastructure.Audit;
|
||
|
|
|
||
|
|
public sealed class SecurityEventRepository : ISecurityEventRepository
|
||
|
|
{
|
||
|
|
private readonly SqlConnectionFactory _factory;
|
||
|
|
|
||
|
|
public SecurityEventRepository(SqlConnectionFactory factory)
|
||
|
|
{
|
||
|
|
_factory = factory;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<long> InsertAsync(
|
||
|
|
DateTime occurredAt,
|
||
|
|
int? actorUserId,
|
||
|
|
string? attemptedUsername,
|
||
|
|
Guid? sessionId,
|
||
|
|
string action,
|
||
|
|
string result,
|
||
|
|
string? failureReason,
|
||
|
|
string? ipAddress,
|
||
|
|
string? userAgent,
|
||
|
|
string? metadata,
|
||
|
|
CancellationToken ct = default)
|
||
|
|
{
|
||
|
|
const string sql = """
|
||
|
|
INSERT INTO dbo.SecurityEvent
|
||
|
|
(OccurredAt, ActorUserId, AttemptedUsername, SessionId, Action, Result,
|
||
|
|
FailureReason, IpAddress, UserAgent, Metadata)
|
||
|
|
OUTPUT INSERTED.Id
|
||
|
|
VALUES
|
||
|
|
(@OccurredAt, @ActorUserId, @AttemptedUsername, @SessionId, @Action, @Result,
|
||
|
|
@FailureReason, @IpAddress, @UserAgent, @Metadata);
|
||
|
|
""";
|
||
|
|
|
||
|
|
await using var conn = _factory.CreateConnection();
|
||
|
|
await conn.OpenAsync(ct);
|
||
|
|
|
||
|
|
var cmd = new CommandDefinition(sql, new
|
||
|
|
{
|
||
|
|
OccurredAt = occurredAt,
|
||
|
|
ActorUserId = actorUserId,
|
||
|
|
AttemptedUsername = attemptedUsername,
|
||
|
|
SessionId = sessionId,
|
||
|
|
Action = action,
|
||
|
|
Result = result,
|
||
|
|
FailureReason = failureReason,
|
||
|
|
IpAddress = ipAddress,
|
||
|
|
UserAgent = userAgent,
|
||
|
|
Metadata = metadata,
|
||
|
|
}, cancellationToken: ct);
|
||
|
|
|
||
|
|
return await conn.ExecuteScalarAsync<long>(cmd);
|
||
|
|
}
|
||
|
|
}
|