Audit Handling - pengdows/pengdows.crud GitHub Wiki
The pengdows.crud library can automatically populate audit columns such as
CreatedBy
, CreatedOn
, LastUpdatedBy
, and
LastUpdatedOn
. These values come from an object implementing the
IAuditValueResolver
interface.
The interface exposes a single method:
<syntaxhighlight lang="csharp">
IAuditValues Resolve();
</syntaxhighlight>
The returned IAuditValues
contains the user identifier and the
current UTC timestamp.
Below is the testbed implementation. It provides a fixed user name for demonstration purposes.
<syntaxhighlight lang="csharp"> using pengdows.crud; namespace testbed; public class StringAuditContextProvider : IAuditValueResolver { public string GetCurrentUserIdentifier() { return "testuser"; } public IAuditValues Resolve() { var x = new AuditValues { UserId = GetCurrentUserIdentifier() }; return x; } } </syntaxhighlight>Register your resolver with the dependency injection container and pass it to
EntityHelper
when creating instances. In the testbed project this is
achieved with:
<syntaxhighlight lang="csharp">
builder.Services.AddScoped<IAuditValueResolver, StringAuditContextProvider>();
</syntaxhighlight>
For a real application you typically want the user identifier from the HTTP context after authentication has occurred. The resolver can obtain it from the current claims principal when using OpenID Connect or OAuth.
<syntaxhighlight lang="csharp"> using System.Security.Claims; using Microsoft.AspNetCore.Http; using pengdows.crud; public class OidcAuditContextProvider : IAuditValueResolver { private readonly IHttpContextAccessor _accessor; public OidcAuditContextProvider(IHttpContextAccessor accessor) { _accessor = accessor; } public IAuditValues Resolve() { var user = _accessor.HttpContext?.User; var id = user?.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "anonymous"; return new AuditValues { UserId = id }; } } </syntaxhighlight>And register it alongside the authentication configuration: <syntaxhighlight lang="csharp"> builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped<IAuditValueResolver, OidcAuditContextProvider>(); builder.Services.AddAuthentication().AddOpenIdConnect(...); // or AddJwtBearer </syntaxhighlight>
Implementations can obtain audit information from any source—HTTP context,
thread principal, a custom service, etc. The library only requires an
IAuditValues
object, letting you adapt it to the needs of your
application.