From c39591a2533894d1f128338dc2776b724738d046 Mon Sep 17 00:00:00 2001 From: thepirat000 Date: Tue, 3 Sep 2024 21:18:35 -0600 Subject: [PATCH] Updating WebApi template --- .../Audit.NET.PostgreSql.csproj | 2 +- .../Audit.NET.SqlServer.csproj | 4 +- templates/WebApi/Audit.WebApi.Template.nuspec | 2 +- .../Audit.WebApi.Template/AuditSetup.cs | 58 +++++++++++-------- .../MyAuditScopeFactory.cs | 27 +++++++++ .../content/Audit.WebApi.Template/Program.cs | 20 +++---- .../Services/IValuesService.cs | 2 +- .../Services/ValuesService.cs | 4 +- 8 files changed, 79 insertions(+), 40 deletions(-) create mode 100644 templates/WebApi/content/Audit.WebApi.Template/MyAuditScopeFactory.cs diff --git a/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj b/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj index 0967d8df..870ea593 100644 --- a/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj +++ b/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj @@ -35,7 +35,7 @@ - + diff --git a/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj b/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj index 16e48a18..7b8b8d46 100644 --- a/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj +++ b/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj @@ -37,12 +37,12 @@ - + - + diff --git a/templates/WebApi/Audit.WebApi.Template.nuspec b/templates/WebApi/Audit.WebApi.Template.nuspec index 52112681..295c91d8 100644 --- a/templates/WebApi/Audit.WebApi.Template.nuspec +++ b/templates/WebApi/Audit.WebApi.Template.nuspec @@ -2,7 +2,7 @@ Audit.WebApi.Template - 7.0.0 + 8.0.0 Audited AspNetCore Web API Federico Colombo false diff --git a/templates/WebApi/content/Audit.WebApi.Template/AuditSetup.cs b/templates/WebApi/content/Audit.WebApi.Template/AuditSetup.cs index ad74b88f..fc6b559a 100644 --- a/templates/WebApi/content/Audit.WebApi.Template/AuditSetup.cs +++ b/templates/WebApi/content/Audit.WebApi.Template/AuditSetup.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc; +using Audit.Core.Providers; +using Microsoft.AspNetCore.Mvc; namespace Audit.WebApi.Template { @@ -9,8 +10,10 @@ public static class AuditSetup { /// Event type to identify the MVC audit logs private const string EventTypeMvc = "MVC"; + /// Event type to identify the HTTP audit logs from the middleware private const string EventTypeHttp = "HTTP"; + #if EnableEntityFramework /// Event type to identify the Entity Framework audit logs private const string EventTypeEntityFramework = "EF"; @@ -22,19 +25,26 @@ public static class AuditSetup #if ServiceInterception /// - /// Adds an audited service to the service collection + /// Adds an audited service to the service collection. The service will be intercepted to log the calls to its methods. /// - public static IServiceCollection AddAuditedTransient(this IServiceCollection services) + public static IServiceCollection AddScopedAuditedService(this IServiceCollection services) where TService : class where TImplementation : class, TService { - return services.AddTransient(s => + return services.AddScoped(s => { - var svc = (TService)ActivatorUtilities.CreateInstance(s); - return AuditProxy.Create(svc, new InterceptionSettings() + // AuditProxy lacks awareness of the service provider, defaulting to the globally configured ScopeFactory and DataProvider. + // To prevent this, we retrieve the ScopeFactory and DataProvider from the service provider and set them in the InterceptionSettings. + var interceptionSettings = new InterceptionSettings() { - EventType = EventTypeServiceInterception - }); + EventType = EventTypeServiceInterception, + AuditScopeFactory = s.GetRequiredService(), + AuditDataProvider = s.GetRequiredService() + }; + + var service = (TService)ActivatorUtilities.CreateInstance(s); + + return AuditProxy.Create(service, interceptionSettings); }); } #endif @@ -42,7 +52,7 @@ public static IServiceCollection AddAuditedTransient( /// /// Add the global audit filter to the MVC pipeline /// - public static MvcOptions AuditSetupFilter(this MvcOptions mvcOptions) + public static MvcOptions AuditSetupMvcFilter(this MvcOptions mvcOptions) { // Add the global MVC Action Filter to the filter chain mvcOptions.AddAuditFilter(a => a @@ -85,25 +95,27 @@ public static void AuditSetupDbContext(this IApplicationBuilder app) #endif /// - /// Setups the audit output + /// Setups the audit scope creation /// - public static void AuditSetupOutput(this WebApplication app) + public static IServiceCollection AddAuditScopeFactory(this IServiceCollection services) { - // TODO: Configure the audit output. - // For more info, see https://github.com/thepirat000/Audit.NET#data-providers. - Audit.Core.Configuration.Setup() - .UseFileLogProvider(_ => _ - .Directory(@"C:\Logs") - .FilenameBuilder(ev => $"{ev.StartDate:yyyyMMddHHmmssffff}_{ev.EventType}.json")); + services.AddScoped(); + + return services; + } + /// + /// Setups the audit output + /// + public static IServiceCollection AddAuditDataProvider(this IServiceCollection services) + { Audit.Core.Configuration.JsonSettings.WriteIndented = true; - // Include the trace identifier in the audit events - var httpContextAccessor = app.Services.GetRequiredService(); - Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope => - { - scope.SetCustomField("TraceId", httpContextAccessor.HttpContext?.TraceIdentifier); - }); + services.AddSingleton(new FileDataProvider(cfg => cfg + .Directory(@"C:\Logs") + .FilenameBuilder(ev => $"{ev.StartDate:yyyyMMddHHmmssffff}_{ev.EventType}.json"))); + + return services; } } } diff --git a/templates/WebApi/content/Audit.WebApi.Template/MyAuditScopeFactory.cs b/templates/WebApi/content/Audit.WebApi.Template/MyAuditScopeFactory.cs new file mode 100644 index 00000000..91881668 --- /dev/null +++ b/templates/WebApi/content/Audit.WebApi.Template/MyAuditScopeFactory.cs @@ -0,0 +1,27 @@ +namespace Audit.WebApi.Template +{ + /// + /// Custom Audit Scope Factory that includes information to the audit events from the HttpContext + /// + public class MyAuditScopeFactory : AuditScopeFactory + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public MyAuditScopeFactory(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + /// + public override void OnConfiguring(AuditScopeOptions options) + { + } + + /// + public override void OnScopeCreated(AuditScope auditScope) + { + auditScope.SetCustomField("TraceId", _httpContextAccessor.HttpContext?.TraceIdentifier); + auditScope.SetCustomField("UserName", _httpContextAccessor.HttpContext?.User.Identity?.Name); + } + } +} diff --git a/templates/WebApi/content/Audit.WebApi.Template/Program.cs b/templates/WebApi/content/Audit.WebApi.Template/Program.cs index f99135d5..1d8785d0 100644 --- a/templates/WebApi/content/Audit.WebApi.Template/Program.cs +++ b/templates/WebApi/content/Audit.WebApi.Template/Program.cs @@ -1,10 +1,9 @@ - -var builder = WebApplication.CreateBuilder(args); +var builder = WebApplication.CreateBuilder(args); // Add services to the container and configure the audit global filter builder.Services.AddControllers(mvc => { - mvc.AuditSetupFilter(); + mvc.AuditSetupMvcFilter(); }); // Swagger @@ -14,16 +13,20 @@ // HTTP context accessor builder.Services.AddHttpContextAccessor(); +// Configure a custom scope factory and data provider +builder.Services.AddAuditScopeFactory(); +builder.Services.AddAuditDataProvider(); + // TODO: Configure your services #if ServiceInterception -builder.Services.AddAuditedTransient(); +builder.Services.AddScopedAuditedService(); #else -builder.Services.AddTransient(); +builder.Services.AddScoped(); #endif #if EnableEntityFramework // TODO: Configure your context connection -builder.Services.AddDbContext(_ => _.UseInMemoryDatabase("default")); +builder.Services.AddDbContextFactory(_ => _.UseInMemoryDatabase("default"), ServiceLifetime.Scoped); #endif var app = builder.Build(); @@ -53,7 +56,4 @@ app.AuditSetupDbContext(); #endif -// Configure the audit output. -app.AuditSetupOutput(); - -app.Run(); \ No newline at end of file +await app.RunAsync(); \ No newline at end of file diff --git a/templates/WebApi/content/Audit.WebApi.Template/Services/IValuesService.cs b/templates/WebApi/content/Audit.WebApi.Template/Services/IValuesService.cs index 33496d7b..8a85fd62 100644 --- a/templates/WebApi/content/Audit.WebApi.Template/Services/IValuesService.cs +++ b/templates/WebApi/content/Audit.WebApi.Template/Services/IValuesService.cs @@ -6,7 +6,7 @@ namespace Audit.WebApi.Template.Services { public interface IValuesService { - IEnumerable GetValues(); + List GetValues(); Task GetAsync(int id); Task InsertAsync(string value); Task ReplaceAsync(int id, string value); diff --git a/templates/WebApi/content/Audit.WebApi.Template/Services/ValuesService.cs b/templates/WebApi/content/Audit.WebApi.Template/Services/ValuesService.cs index bb1faa96..6821aded 100644 --- a/templates/WebApi/content/Audit.WebApi.Template/Services/ValuesService.cs +++ b/templates/WebApi/content/Audit.WebApi.Template/Services/ValuesService.cs @@ -23,9 +23,9 @@ public ValuesService(MyContext dbContext) _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); } - public IEnumerable GetValues() + public List GetValues() { - return _dbContext.Values.Select(x => x.Value); + return _dbContext.Values.Select(x => x.Value).ToList(); } public async Task GetAsync(int id)