diff --git a/CHANGELOG.md b/CHANGELOG.md index b88a0929..66714151 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to Audit.NET and its extensions will be documented in this f The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +## [16.0.0] - 2020-08-06 +### Modified +- Audit.NET: Moving the AuditScope creation to an `AuditScopeFactory` implementing an interface `IAuditScopeFactory`. +Also added `IAuditScope` interface for unit testing + ## [15.2.4] - 2020-07-22 ### Modified - Audit.EntityFramework.Core: Changing version for Microsoft.EntityFrameworkCore reference when targeting .NET Standard 2.0 or 2.1 (now referencing Microsoft.EntityFrameworkCore 3.1.0) (#310) diff --git a/README.md b/README.md index b8684532..44307a2f 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,17 @@ The **Audit Scope** is the central object of this framework. It encapsulates an The **Audit Event** is an extensible information container of an audited operation. See the [audit scope statechart](#auditscope-statechart). -Create an Audit Scope by calling the static `AuditScope.Create` method. - +To create a new Audit Scope, call the `Create`/`CreateAsync` method on `AuditScopeFactory`. + +```c# +var scope = new AuditScopeFactory().Create(new AuditScopeOptions(...))); +``` + +Or use the static shortcuts `AuditScope.Create`/`AuditScope.CreateAsync`: +```c# +var scope = AuditScope.Create(new AuditScopeOptions(...))); +``` + Suppose you have the following code to _cancel an order_ that you want to audit: ```c# @@ -62,25 +71,24 @@ using (AuditScope.Create("Order:Update", () => order)) > It is not mandatory to use a `using` block, but it simplifies the syntax when the code to audit is on a single block, allowing the detection of exceptions and calculating the duration by implicitly saving the event on disposal. -The first parameter of the `Create` method is an _event type name_ intended to identify and group the events. The second is the delegate to obtain the object to track (target object). This object is passed as a `Func` to allow the library to inspect the value at the beginning and at the disposal of the scope. It is not mandatory to supply a target object, pass `null` when you don't want to track a specific object. +The first parameter of the `AuditScope.Create` method is an _event type name_ intended to identify and group the events. The second is the delegate to obtain the object to track (target object). This object is passed as a `Func` to allow the library to inspect the value at the beginning and at the disposal of the scope. It is not mandatory to supply a target object, pass `null` when you don't want to track a specific object. -There is also a unified overload of the `Create` method that accepts an instance of [`AuditScopeOptions`](https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.NET/AuditScopeOptions.cs). Use this class to configure any of the available options for the scope: +> When using the [extensions](#extensions) that logs interactions with different systems, like [Audit.EntityFramework](https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.EntityFramework/README.md), [Audit.WebApi](https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.WebApi/README.md), etc. you don't need to explicitly create the `AuditScope` or `AuditEvent`, they are created internally by the extension. -```c# -var options = new AuditScopeOptions() -{ - EventType = "MyEvent", - CreationPolicy = EventCreationPolicy.Manual, - ExtraFields = new { Action = this.Action }, - AuditEvent = new MyCustomAuditEvent() -}; -using (var scope = AuditScope.Create(options)) -{ - // ... -} -``` +#### AuditScopeOptions fields + +Option field | Type | Description +------------ | ---------------- | ---------------- +EventType | `string` | A string representing the type of the event +TargetGetter | `Func` | Target object getter (a func that returns the object to track) +ExtraFields | `obejct` | Anonymous object that contains additional fields to be merged into the audit event +DataProvider | `AuditDataProvider` | The [data provider](#data-providers) to use. Defaults to the DataProvider configured on `Audit.Core.Configuration.DataProvider` +CreationPolicy | `EventCreationPolicy` | The [creation policy](#creation-policy) to use. Default is `InsertOnEnd` +IsCreateAndSave | `bool` | Value indicating whether this scope should be immediately ended and saved after creation. Default is false +AuditEvent | `AuditEvent` | Custom initial audit event to use. By default it will create a new instance of basic `AuditEvent` +SkipExtraFrames | `int` | Value used to indicate how many frames in the stack should be skipped to determine the calling method. Default is 0 +CallingMethod | `MethodBase` | Specific calling method to store on the event. Default is to use the calling stack to determine the calling method. -> When using the [extensions](#extensions) that logs interactions with different systems, like [Audit.EntityFramework](https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.EntityFramework/README.md), [Audit.WebApi](https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.WebApi/README.md), etc. you don't need to explicitly create the `AuditScope` or `AuditEvent`, they are created internally by the extension. ### Simple logging @@ -104,7 +112,12 @@ public class SomethingThatStartsAndEnds public void Start() { // Create a manual scope - auditScope = AuditScope.Create("MyEvent", () => Status, EventCreationPolicy.Manual); + auditScope = AuditScope.Create(new AuditScopeOptions() + { + EventType = "MyEvent", + TargetGetter = () => this.Status, + CreationPolicy = EventCreationPolicy.Manual + }); } public void End() @@ -130,7 +143,7 @@ public async Task SaveOrderAsync(Order order) try { // async scope creation - auditScope = await AuditScope.CreateAsync("order", () => order); + auditScope = await AuditScope.CreateAsync(new AuditScopeOptions("order", () => order)); } finally { @@ -230,7 +243,7 @@ For example: ```c# Order order = Db.GetOrder(orderId); -using (var audit = AuditScope.Create("Order:Update", () => order)) +using (var audit = AuditScope.Create(new AuditScopeOptions("Order:Update", () => order))) { audit.SetCustomField("ReferenceId", orderId); order.Status = -1; @@ -242,7 +255,7 @@ using (var audit = AuditScope.Create("Order:Update", () => order)) You can also set Custom Fields when creating the `AuditScope`, by passing an anonymous object with the properties you want as extra fields. For example: ```c# -using (var audit = AuditScope.Create("Order:Update", () => order, new { ReferenceId = orderId })) +using (var audit = AuditScope.Create(new AuditScopeOptions("Order:Update", () => order, new { ReferenceId = orderId }))) { order.Status = -1; order = Db.OrderUpdate(order); @@ -252,7 +265,7 @@ using (var audit = AuditScope.Create("Order:Update", () => order, new { Referenc You can also access the Custom Fields directly from `Event.CustomFields` property of the scope. For example: ```c# -using (var audit = AuditScope.Create("Order:Update", () => order, new { ReferenceId = orderId })) +using (var audit = AuditScope.Create(new AuditScopeOptions("Order:Update", () => order, new { ReferenceId = orderId }))) { audit.Event.CustomFields["ReferenceId"] = orderId; } @@ -317,7 +330,7 @@ The `AuditScope` object has a `Discard()` method to allow the user to discard an For example, if you want to avoid saving the audit event under certain condition: ```c# -using (var scope = AuditScope.Create("SomeEvent", () => someTarget)) +using (var scope = AuditScope.Create(new AuditScopeOptions("SomeEvent", () => someTarget))) { try { @@ -409,15 +422,9 @@ Audit.Core.Configuration.Setup() See [Configuration section](#configuration) for more information. -You can also set the data provider per-scope, by using an appropriate overload of the `AuditScope.Create` method. For example: -```c# -AuditScope.Create("Order:Update", () => order, EventCreationPolicy.Manual, new MyCustomDataProvider()); -``` - -Or: - +You can also set the data provider per-scope. For example: ```c# -AuditScope.Create(new AuditScopeOptions { DataProvider = new MyCustomDataProvider() }); +AuditScope.Create(new AuditScopeOptions { DataProvider = new MyCustomDataProvider(), ... }); ``` diff --git a/src/Audit.DynamicProxy/Audit.DynamicProxy.csproj b/src/Audit.DynamicProxy/Audit.DynamicProxy.csproj index d03111c1..c666a8c6 100644 --- a/src/Audit.DynamicProxy/Audit.DynamicProxy.csproj +++ b/src/Audit.DynamicProxy/Audit.DynamicProxy.csproj @@ -4,7 +4,7 @@ Generate Audit Logs by intercepting operation calls on any class without changing its code. Copyright 2019 Audit.DynamicProxy - 15.3.0 + 16.0.0 Federico Colombo netstandard1.5;net45 $(DefineConstants);STRONG_NAME @@ -31,7 +31,7 @@ - + diff --git a/src/Audit.DynamicProxy/AuditInterceptor.cs b/src/Audit.DynamicProxy/AuditInterceptor.cs index bda08a02..6971621b 100644 --- a/src/Audit.DynamicProxy/AuditInterceptor.cs +++ b/src/Audit.DynamicProxy/AuditInterceptor.cs @@ -36,7 +36,7 @@ public class AuditInterceptor : IInterceptor /// /// Intercept an asynchronous operation that returns a Task. /// - private static async Task InterceptAsync(Task task, IInvocation invocation, InterceptEvent intEvent, AuditScope scope) + private static async Task InterceptAsync(Task task, IInvocation invocation, InterceptEvent intEvent, IAuditScope scope) { try { @@ -53,7 +53,7 @@ private static async Task InterceptAsync(Task task, IInvocation invocation, Inte /// /// Intercept an asynchronous operation that returns a Task Of[T]. /// - private static async Task InterceptAsync(Task task, IInvocation invocation, InterceptEvent intEvent, AuditScope scope) + private static async Task InterceptAsync(Task task, IInvocation invocation, InterceptEvent intEvent, IAuditScope scope) { T result; try @@ -72,7 +72,7 @@ private static async Task InterceptAsync(Task task, IInvocation invocat /// /// Ends the event for asynchronous interceptions. /// - private static void EndAsyncAuditInterceptEvent(Task task, IInvocation invocation, InterceptEvent intEvent, AuditScope scope, object result) + private static void EndAsyncAuditInterceptEvent(Task task, IInvocation invocation, InterceptEvent intEvent, IAuditScope scope, object result) { intEvent.AsyncStatus = task.Status.ToString(); if (task.Status == TaskStatus.Faulted) @@ -220,7 +220,8 @@ public void Intercept(IInvocation invocation) DataProvider = Settings.AuditDataProvider, AuditEvent = auditEventIntercept }; - var scope = AuditScope.Create(scopeOptions); + var auditScopeFactory = Settings.AuditScopeFactory ?? Configuration.AuditScopeFactory; + var scope = auditScopeFactory.Create(scopeOptions); AuditProxy.CurrentScope = scope; // Call the intercepted method (sync part) try @@ -239,7 +240,7 @@ public void Intercept(IInvocation invocation) { if (typeof(Task).IsAssignableFrom(returnType)) { - invocation.ReturnValue = InterceptAsync((dynamic) invocation.ReturnValue, invocation, intEvent, scope); + invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation, intEvent, scope); return; } } diff --git a/src/Audit.DynamicProxy/AuditProxy.cs b/src/Audit.DynamicProxy/AuditProxy.cs index 7d4e66fe..bb725e8e 100644 --- a/src/Audit.DynamicProxy/AuditProxy.cs +++ b/src/Audit.DynamicProxy/AuditProxy.cs @@ -14,7 +14,7 @@ public class AuditProxy { private static readonly ProxyGenerator Generator = new ProxyGenerator(); [ThreadStatic] - private static AuditScope _currentScope; + private static IAuditScope _currentScope; /// /// Gets the scope for the current running thread. Get this property value from the audited methods to customize the Audit. @@ -22,7 +22,7 @@ public class AuditProxy /// Calling this property from a different thread will return NULL or an unexpected value. /// /// The current scope related to the running thread, or NULL. - public static AuditScope CurrentScope + public static IAuditScope CurrentScope { get => _currentScope; internal set => _currentScope = value; diff --git a/src/Audit.DynamicProxy/InterceptionSettings.cs b/src/Audit.DynamicProxy/InterceptionSettings.cs index e73f9837..4711ad43 100644 --- a/src/Audit.DynamicProxy/InterceptionSettings.cs +++ b/src/Audit.DynamicProxy/InterceptionSettings.cs @@ -40,5 +40,9 @@ public class InterceptionSettings /// Gets or sets the event creation policy to use for this interception. Default is NULL to use the globally configured creation policy. /// public EventCreationPolicy? EventCreationPolicy { get; set; } + /// + /// Gets or sets the custom audit scope factory. Default is NULL to use the general AuditScopeFactory. + /// + public IAuditScopeFactory AuditScopeFactory { get; set; } } } \ No newline at end of file diff --git a/src/Audit.EntityFramework.Core/Audit.EntityFramework.Core.csproj b/src/Audit.EntityFramework.Core/Audit.EntityFramework.Core.csproj index f721c250..b1261906 100644 --- a/src/Audit.EntityFramework.Core/Audit.EntityFramework.Core.csproj +++ b/src/Audit.EntityFramework.Core/Audit.EntityFramework.Core.csproj @@ -4,7 +4,7 @@ Generate Audit Logs from EntityFramework context changes Copyright 2016 Audit.EntityFramework.Core - 15.3.0 + 16.0.0 Federico Colombo netstandard1.5;netstandard2.0;net461;netstandard2.1;net472 $(DefineConstants);STRONG_NAME;EF_CORE diff --git a/src/Audit.EntityFramework.Identity.Core/Audit.EntityFramework.Identity.Core.csproj b/src/Audit.EntityFramework.Identity.Core/Audit.EntityFramework.Identity.Core.csproj index 0789360a..0e31db17 100644 --- a/src/Audit.EntityFramework.Identity.Core/Audit.EntityFramework.Identity.Core.csproj +++ b/src/Audit.EntityFramework.Identity.Core/Audit.EntityFramework.Identity.Core.csproj @@ -4,7 +4,7 @@ Generate Audit Logs from EntityFramework identity context changes Copyright 2018 Audit.EntityFramework.Identity.Core - 15.3.0 + 16.0.0 Federico Colombo netstandard1.5;netstandard2.1;net461 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.EntityFramework.Identity/Audit.EntityFramework.Identity.csproj b/src/Audit.EntityFramework.Identity/Audit.EntityFramework.Identity.csproj index 020a8754..5840eb21 100644 --- a/src/Audit.EntityFramework.Identity/Audit.EntityFramework.Identity.csproj +++ b/src/Audit.EntityFramework.Identity/Audit.EntityFramework.Identity.csproj @@ -1,10 +1,10 @@ - + Generate Audit Logs from EntityFramework identity context changes Copyright 2018 Audit.EntityFramework.Identity - 15.3.0 + 16.0.0 Federico Colombo netstandard1.5;netstandard2.0;net45;netstandard2.1 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.Net45.cs b/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.Net45.cs index 1ec5ec64..a6aa925d 100644 --- a/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.Net45.cs +++ b/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.Net45.cs @@ -131,6 +131,11 @@ public AuditIdentityDbContext(DbConnection existingConnection, DbCompiledModel m /// public AuditDataProvider AuditDataProvider { get; set; } + /// + /// To indicate a custom audit scope factory. (Default is NULL to use the Audit.Core.Configuration.DefaultAuditScopeFactory). + /// + public IAuditScopeFactory AuditScopeFactory { get; set; } + /// /// Indicates if the Audit is disabled. /// Default is false. @@ -192,7 +197,7 @@ public AuditIdentityDbContext(DbConnection existingConnection, DbCompiledModel m /// Override to specify custom logic. /// /// The audit scope. - public virtual void OnScopeCreated(AuditScope auditScope) + public virtual void OnScopeCreated(IAuditScope auditScope) { } @@ -201,7 +206,7 @@ public virtual void OnScopeCreated(AuditScope auditScope) /// Override to specify custom logic. /// /// The audit scope. - public virtual void OnScopeSaving(AuditScope auditScope) + public virtual void OnScopeSaving(IAuditScope auditScope) { } diff --git a/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.cs b/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.cs index 105c75cf..03c2fe51 100644 --- a/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.cs +++ b/src/Audit.EntityFramework.Identity/AuditIdentityDbContext.cs @@ -118,6 +118,11 @@ public AuditIdentityDbContext(DbConnection existingConnection, DbCompiledModel m /// public AuditDataProvider AuditDataProvider { get; set; } + /// + /// To indicate a custom audit scope factory. (Default is NULL to use the Audit.Core.Configuration.DefaultAuditScopeFactory). + /// + public IAuditScopeFactory AuditScopeFactory { get; set; } + /// /// Indicates if the Audit is disabled. /// Default is false. @@ -180,7 +185,7 @@ public AuditIdentityDbContext(DbConnection existingConnection, DbCompiledModel m /// Override to specify custom logic. /// /// The audit scope. - public virtual void OnScopeCreated(AuditScope auditScope) + public virtual void OnScopeCreated(IAuditScope auditScope) { } @@ -189,7 +194,7 @@ public virtual void OnScopeCreated(AuditScope auditScope) /// Override to specify custom logic. /// /// The audit scope. - public virtual void OnScopeSaving(AuditScope auditScope) + public virtual void OnScopeSaving(IAuditScope auditScope) { } diff --git a/src/Audit.EntityFramework/Audit.EntityFramework.csproj b/src/Audit.EntityFramework/Audit.EntityFramework.csproj index 905b7cdc..b03db4ce 100644 --- a/src/Audit.EntityFramework/Audit.EntityFramework.csproj +++ b/src/Audit.EntityFramework/Audit.EntityFramework.csproj @@ -4,7 +4,7 @@ Generate Audit Logs from EntityFramework context changes Copyright 2016 Audit.EntityFramework - 15.3.0 + 16.0.0 Federico Colombo netstandard1.5;netstandard2.0;net45;netstandard2.1;net472 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.EntityFramework/AuditDbContext.cs b/src/Audit.EntityFramework/AuditDbContext.cs index fb219586..5a295838 100644 --- a/src/Audit.EntityFramework/AuditDbContext.cs +++ b/src/Audit.EntityFramework/AuditDbContext.cs @@ -120,6 +120,11 @@ protected AuditDbContext() : base() /// public virtual AuditDataProvider AuditDataProvider { get; set; } + /// + /// To indicate a custom audit scope factory. (Default is NULL to use the Audit.Core.Configuration.DefaultAuditScopeFactory). + /// + public virtual IAuditScopeFactory AuditScopeFactory { get; set; } + /// /// Optional custom fields added to the audit event /// @@ -149,7 +154,7 @@ protected AuditDbContext() : base() /// Override to specify custom logic. /// /// The audit scope. - public virtual void OnScopeCreated(AuditScope auditScope) + public virtual void OnScopeCreated(IAuditScope auditScope) { } /// @@ -157,7 +162,7 @@ public virtual void OnScopeCreated(AuditScope auditScope) /// Override to specify custom logic. /// /// The audit scope. - public virtual void OnScopeSaving(AuditScope auditScope) + public virtual void OnScopeSaving(IAuditScope auditScope) { } diff --git a/src/Audit.EntityFramework/AuditEventExtensions.cs b/src/Audit.EntityFramework/AuditEventExtensions.cs index 2ea2a6ed..34db7b05 100644 --- a/src/Audit.EntityFramework/AuditEventExtensions.cs +++ b/src/Audit.EntityFramework/AuditEventExtensions.cs @@ -8,7 +8,7 @@ public static class AuditEventExtensions /// Gets the Entity Framework Event portion of the Audit Event on the given scope. /// /// The audit scope. - public static EntityFrameworkEvent GetEntityFrameworkEvent(this AuditScope auditScope) + public static EntityFrameworkEvent GetEntityFrameworkEvent(this IAuditScope auditScope) { return auditScope?.Event.GetEntityFrameworkEvent(); } diff --git a/src/Audit.EntityFramework/DbContextHelper.cs b/src/Audit.EntityFramework/DbContextHelper.cs index 5d9cb7a0..a33902ea 100644 --- a/src/Audit.EntityFramework/DbContextHelper.cs +++ b/src/Audit.EntityFramework/DbContextHelper.cs @@ -133,7 +133,7 @@ public static string GetStateName(EntityState state) /// /// Saves the scope. /// - public void SaveScope(IAuditDbContext context, AuditScope scope, EntityFrameworkEvent @event) + public void SaveScope(IAuditDbContext context, IAuditScope scope, EntityFrameworkEvent @event) { UpdateAuditEvent(@event, context); (scope.Event as AuditEventEntityFramework).EntityFrameworkEvent = @event; @@ -144,7 +144,7 @@ public void SaveScope(IAuditDbContext context, AuditScope scope, EntityFramework /// /// Saves the scope asynchronously. /// - public async Task SaveScopeAsync(IAuditDbContext context, AuditScope scope, EntityFrameworkEvent @event) + public async Task SaveScopeAsync(IAuditDbContext context, IAuditScope scope, EntityFrameworkEvent @event) { UpdateAuditEvent(@event, context); (scope.Event as AuditEventEntityFramework).EntityFrameworkEvent = @event; @@ -339,7 +339,7 @@ private bool EvalIgnoreFilter(Type type, EfSettings localConfig, EfSettings glob /// /// Creates the Audit scope. /// - public AuditScope CreateAuditScope(IAuditDbContext context, EntityFrameworkEvent efEvent) + public IAuditScope CreateAuditScope(IAuditDbContext context, EntityFrameworkEvent efEvent) { var typeName = context.GetType().Name; var eventType = context.AuditEventType?.Replace("{context}", typeName).Replace("{database}", efEvent.Database) ?? typeName; @@ -347,7 +347,16 @@ public AuditScope CreateAuditScope(IAuditDbContext context, EntityFrameworkEvent { EntityFrameworkEvent = efEvent }; - var scope = AuditScope.Create(eventType, null, null, EventCreationPolicy.Manual, context.AuditDataProvider, auditEfEvent, 3); + var factory = context.AuditScopeFactory ?? Core.Configuration.AuditScopeFactory; + var options = new AuditScopeOptions() + { + EventType = eventType, + CreationPolicy = EventCreationPolicy.Manual, + DataProvider = context.AuditDataProvider, + AuditEvent = auditEfEvent, + SkipExtraFrames = 3 + }; + var scope = factory.Create(options); if (context.ExtraFields != null) { foreach (var field in context.ExtraFields) @@ -362,7 +371,7 @@ public AuditScope CreateAuditScope(IAuditDbContext context, EntityFrameworkEvent /// /// Creates the Audit scope asynchronously. /// - public async Task CreateAuditScopeAsync(IAuditDbContext context, EntityFrameworkEvent efEvent) + public async Task CreateAuditScopeAsync(IAuditDbContext context, EntityFrameworkEvent efEvent) { var typeName = context.GetType().Name; var eventType = context.AuditEventType?.Replace("{context}", typeName).Replace("{database}", efEvent.Database) ?? typeName; @@ -370,7 +379,16 @@ public async Task CreateAuditScopeAsync(IAuditDbContext context, Ent { EntityFrameworkEvent = efEvent }; - var scope = await AuditScope.CreateAsync(eventType, null, null, EventCreationPolicy.Manual, context.AuditDataProvider, auditEfEvent, 3); + var factory = context.AuditScopeFactory ?? Core.Configuration.AuditScopeFactory; + var options = new AuditScopeOptions() + { + EventType = eventType, + CreationPolicy = EventCreationPolicy.Manual, + DataProvider = context.AuditDataProvider, + AuditEvent = auditEfEvent, + SkipExtraFrames = 3 + }; + var scope = await factory.CreateAsync(options); if (context.ExtraFields != null) { foreach (var field in context.ExtraFields) diff --git a/src/Audit.EntityFramework/DefaultAuditContext.cs b/src/Audit.EntityFramework/DefaultAuditContext.cs index 6daf0aae..7ee650df 100644 --- a/src/Audit.EntityFramework/DefaultAuditContext.cs +++ b/src/Audit.EntityFramework/DefaultAuditContext.cs @@ -26,8 +26,9 @@ public class DefaultAuditContext : IAuditDbContext public virtual Dictionary ExtraFields { get; set; } public virtual Dictionary EntitySettings { get; set; } public virtual AuditDataProvider AuditDataProvider { get; set; } - public virtual void OnScopeCreated(AuditScope auditScope) { } - public virtual void OnScopeSaving(AuditScope auditScope) { } + public virtual IAuditScopeFactory AuditScopeFactory { get; set; } + public virtual void OnScopeCreated(IAuditScope auditScope) { } + public virtual void OnScopeSaving(IAuditScope auditScope) { } public bool ExcludeTransactionId { get; set; } #if EF_FULL public virtual bool IncludeIndependantAssociations { get; set; } diff --git a/src/Audit.EntityFramework/IAuditDbContext.cs b/src/Audit.EntityFramework/IAuditDbContext.cs index f720251d..5a4b5aaf 100644 --- a/src/Audit.EntityFramework/IAuditDbContext.cs +++ b/src/Audit.EntityFramework/IAuditDbContext.cs @@ -22,11 +22,12 @@ public interface IAuditDbContext bool ExcludeValidationResults { get; set; } AuditOptionMode Mode { get; set; } AuditDataProvider AuditDataProvider { get; set; } + IAuditScopeFactory AuditScopeFactory { get; set; } Dictionary ExtraFields { get; } DbContext DbContext { get; } Dictionary EntitySettings { get; set; } - void OnScopeSaving(AuditScope auditScope); - void OnScopeCreated(AuditScope auditScope); + void OnScopeSaving(IAuditScope auditScope); + void OnScopeCreated(IAuditScope auditScope); bool ExcludeTransactionId { get; set; } #if EF_FULL bool IncludeIndependantAssociations { get; set; } diff --git a/src/Audit.FileSystem/Audit.FileSystem.csproj b/src/Audit.FileSystem/Audit.FileSystem.csproj index bd1b9860..15dd6051 100644 --- a/src/Audit.FileSystem/Audit.FileSystem.csproj +++ b/src/Audit.FileSystem/Audit.FileSystem.csproj @@ -4,7 +4,7 @@ Generate Audit Logs from file system events using a FileSystemWatcher Copyright 2018 Audit.FileSystem - 15.3.0 + 16.0.0 Federico Colombo netstandard1.3;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.FileSystem/FileSystemMonitor.cs b/src/Audit.FileSystem/FileSystemMonitor.cs index 49ab09a0..a443bd61 100644 --- a/src/Audit.FileSystem/FileSystemMonitor.cs +++ b/src/Audit.FileSystem/FileSystemMonitor.cs @@ -141,8 +141,8 @@ private void ProcessEvent(FileSystemEventArgs e, FileSystemEventType type) FileSystemEvent = fsEvent }; var eventType = (_options.EventTypeName ?? "[{type}] {name}").Replace("{name}", fsEvent.Name).Replace("{path}", fsEvent.FullPath).Replace("{type}", e.ChangeType.ToString()); - - using (var auditScope = AuditScope.Create(new AuditScopeOptions() { EventType = eventType, AuditEvent = fsAuditEvent, DataProvider = _options.AuditDataProvider, CreationPolicy = _options.CreationPolicy })) + var factory = _options.AuditScopeFactory ?? Configuration.AuditScopeFactory; + using (var auditScope = factory.Create(new AuditScopeOptions() { EventType = eventType, AuditEvent = fsAuditEvent, DataProvider = _options.AuditDataProvider, CreationPolicy = _options.CreationPolicy })) { if (type != FileSystemEventType.Delete) { diff --git a/src/Audit.FileSystem/FileSystemMonitorOptions.cs b/src/Audit.FileSystem/FileSystemMonitorOptions.cs index 476540d1..d96636a8 100644 --- a/src/Audit.FileSystem/FileSystemMonitorOptions.cs +++ b/src/Audit.FileSystem/FileSystemMonitorOptions.cs @@ -77,5 +77,9 @@ public FileSystemMonitorOptions(string path) /// Gets or sets the event creation policy to use. By default it will use the global Configuration.CreationPolicy. /// public EventCreationPolicy? CreationPolicy { get; set; } + /// + /// Gets or sets a custom audit scope factory. By default it will use the general `AuditScopeFactory`. + /// + public IAuditScopeFactory AuditScopeFactory { get; set; } } } diff --git a/src/Audit.FileSystem/README.md b/src/Audit.FileSystem/README.md index 9be0df84..87a10e75 100644 --- a/src/Audit.FileSystem/README.md +++ b/src/Audit.FileSystem/README.md @@ -68,6 +68,7 @@ By default content is not included. - **InternalBufferSize**: Gets or sets the size (in bytes) of the [internal buffer](https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.internalbuffersize?view=netstandard-2.0#System_IO_FileSystemWatcher_InternalBufferSize). - **AuditDataProvider**: To indicate the Audit Data Provider to use. Default is NULL to use the [globally configured data provider](https://github.com/thepirat000/Audit.NET#data-provider). - **CreationPolicy**: To indicate the event creation policy to use. Default is NULL to use the [globally configured creation policy](https://github.com/thepirat000/Audit.NET#creation-policy). +- **AuditScopeFactory**: Allows to set a specific audit scope factory. By default the general [`AuditScopeFactory`](https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.NET/AuditScopeFactory.cs) is used. ## Output diff --git a/src/Audit.HttpClient/Audit.HttpClient.csproj b/src/Audit.HttpClient/Audit.HttpClient.csproj index f878a651..a430f2c1 100644 --- a/src/Audit.HttpClient/Audit.HttpClient.csproj +++ b/src/Audit.HttpClient/Audit.HttpClient.csproj @@ -3,7 +3,7 @@ Generate detailed Audit Logs for HttpClient instances. Copyright 2019 Audit.HttpClient - 15.3.0 + 16.0.0 Federico Colombo netstandard1.3;netstandard2.0;netstandard2.1;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.HttpClient/AuditHttpClientHandler.cs b/src/Audit.HttpClient/AuditHttpClientHandler.cs index f59cd9d3..6240ef62 100644 --- a/src/Audit.HttpClient/AuditHttpClientHandler.cs +++ b/src/Audit.HttpClient/AuditHttpClientHandler.cs @@ -60,6 +60,10 @@ public class AuditHttpClientHandler : HttpClientHandler /// Specifies the audit data provider to use. Default is NULL to use the globally configured data provider. /// public AuditDataProvider AuditDataProvider { set => _config._auditDataProvider = value; } + /// + /// Specifies the Audit Scope factory to use. Default is NULL to use the default AuditScopeFactory. + /// + public IAuditScopeFactory AuditScopeFactory { set => _config._auditScopeFactory = value; } public AuditHttpClientHandler() { @@ -101,7 +105,8 @@ protected async override Task SendAsync(HttpRequestMessage DataProvider = _config._auditDataProvider }; HttpResponseMessage response; - var scope = AuditScope.Create(options); + var auditScopeFactory = _config._auditScopeFactory ?? Configuration.AuditScopeFactory; + var scope = auditScopeFactory.Create(options); try { response = await base.SendAsync(request, cancellationToken); @@ -127,7 +132,7 @@ protected async override Task SendAsync(HttpRequestMessage return response; } - private async Task SaveDispose(AuditScope scope) + private async Task SaveDispose(IAuditScope scope) { if (scope.EventCreationPolicy == Core.EventCreationPolicy.Manual) { diff --git a/src/Audit.HttpClient/ConfigurationApi/AuditClientHandlerConfigurator.cs b/src/Audit.HttpClient/ConfigurationApi/AuditClientHandlerConfigurator.cs index 07bbff0a..6184d431 100644 --- a/src/Audit.HttpClient/ConfigurationApi/AuditClientHandlerConfigurator.cs +++ b/src/Audit.HttpClient/ConfigurationApi/AuditClientHandlerConfigurator.cs @@ -16,6 +16,13 @@ public class AuditClientHandlerConfigurator : IAuditClientHandlerConfigurator internal Func _eventTypeName; internal EventCreationPolicy? _eventCreationPolicy; internal AuditDataProvider _auditDataProvider; + internal IAuditScopeFactory _auditScopeFactory; + + public IAuditClientHandlerConfigurator AuditScopeFactory(IAuditScopeFactory auditScopeFactory) + { + _auditScopeFactory = auditScopeFactory; + return this; + } public IAuditClientHandlerConfigurator CreationPolicy(EventCreationPolicy eventCreationPolicy) { diff --git a/src/Audit.HttpClient/ConfigurationApi/IAuditClientHandlerConfigurator.cs b/src/Audit.HttpClient/ConfigurationApi/IAuditClientHandlerConfigurator.cs index e877244e..63c38501 100644 --- a/src/Audit.HttpClient/ConfigurationApi/IAuditClientHandlerConfigurator.cs +++ b/src/Audit.HttpClient/ConfigurationApi/IAuditClientHandlerConfigurator.cs @@ -91,5 +91,9 @@ public interface IAuditClientHandlerConfigurator /// Specifies the audit data provider to use. Default is NULL to use the globally configured data provider. /// IAuditClientHandlerConfigurator AuditDataProvider(AuditDataProvider auditDataProvider); + /// + /// Specifies the Audit Scope factory to use. Default is NULL to use the default AuditScopeFactory. + /// + IAuditClientHandlerConfigurator AuditScopeFactory(IAuditScopeFactory auditScopeFactory); } } diff --git a/src/Audit.HttpClient/README.md b/src/Audit.HttpClient/README.md index 82fcf08f..8ac48129 100644 --- a/src/Audit.HttpClient/README.md +++ b/src/Audit.HttpClient/README.md @@ -85,6 +85,7 @@ The `AuditHttpClientHandler` class allows to configure the following settings: - **IncludeResponseBody**: Specifies whether the HTTP Response body should be included on the audit output. Default is false. - **CreationPolicy**: Allows to set a specific event creation policy. By default the globally configured creation policy is used. See [Audit.NET Event Creation Policy](https://github.com/thepirat000/Audit.NET#event-creation-policy) section for more information. - **AuditDataProvider**: Allows to set a specific audit data provider. By default the globally configured data provider is used. See [Audit.NET Data Providers](https://github.com/thepirat000/Audit.NET/blob/master/README.md#data-providers) section for more information. +- **AuditScopeFactory**: Allows to set a specific audit scope factory. By default the general [`AuditScopeFactory`](https://github.com/thepirat000/Audit.NET/blob/master/src/Audit.NET/AuditScopeFactory.cs) is used. ## Output Details diff --git a/src/Audit.Mvc.Core/Audit.Mvc.Core.csproj b/src/Audit.Mvc.Core/Audit.Mvc.Core.csproj index 78eec9cd..b23de35e 100644 --- a/src/Audit.Mvc.Core/Audit.Mvc.Core.csproj +++ b/src/Audit.Mvc.Core/Audit.Mvc.Core.csproj @@ -4,7 +4,7 @@ Generate detailed Audit Logs for AspNet Core MVC Controller actions. Copyright 2016 Audit.Mvc.Core - 15.3.0 + 16.0.0 Federico Colombo netstandard1.6;netstandard2.0;net451;netstandard2.1;netcoreapp3.0 TRACE;DEBUG;STRONG_NAME diff --git a/src/Audit.Mvc/Audit.Mvc.csproj b/src/Audit.Mvc/Audit.Mvc.csproj index d02c8196..e6819ed4 100644 --- a/src/Audit.Mvc/Audit.Mvc.csproj +++ b/src/Audit.Mvc/Audit.Mvc.csproj @@ -4,7 +4,7 @@ Generate detailed Audit Logs for MVC Controller actions. Copyright 2016 Audit.Mvc - 15.3.0 + 16.0.0 Federico Colombo netstandard1.6;netstandard2.0;net45;netstandard2.1;netcoreapp3.0 TRACE;DEBUG;STRONG_NAME diff --git a/src/Audit.NET.AmazonQLDB/Audit.NET.AmazonQLDB.csproj b/src/Audit.NET.AmazonQLDB/Audit.NET.AmazonQLDB.csproj index 7b90f96c..d06b7b2c 100644 --- a/src/Audit.NET.AmazonQLDB/Audit.NET.AmazonQLDB.csproj +++ b/src/Audit.NET.AmazonQLDB/Audit.NET.AmazonQLDB.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs into Amazon QLDB Copyright 2020 Audit.AmazonQLDB - 15.3.0 + 16.0.0 Adrian Iftode;Federico Colombo netstandard2.0 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.AzureDocumentDB/Audit.NET.AzureDocumentDB.csproj b/src/Audit.NET.AzureDocumentDB/Audit.NET.AzureDocumentDB.csproj index 494d393d..e4e35434 100644 --- a/src/Audit.NET.AzureDocumentDB/Audit.NET.AzureDocumentDB.csproj +++ b/src/Audit.NET.AzureDocumentDB/Audit.NET.AzureDocumentDB.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs into an Azure Document DB database Copyright 2016 Audit.AzureDocumentDB - 15.3.0 + 16.0.0 Federico Colombo net45;netstandard1.6;netstandard2.0 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.AzureStorage/Audit.NET.AzureStorage.csproj b/src/Audit.NET.AzureStorage/Audit.NET.AzureStorage.csproj index c343434f..ad1f87c4 100644 --- a/src/Audit.NET.AzureStorage/Audit.NET.AzureStorage.csproj +++ b/src/Audit.NET.AzureStorage/Audit.NET.AzureStorage.csproj @@ -4,7 +4,7 @@ Store Audit.NET Logs into an Azure Blob Storage Copyright 2019 Audit.AzureStorage - 15.3.0 + 16.0.0 Federico Colombo netstandard1.4;net452 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.DynamoDB/Audit.NET.DynamoDB.csproj b/src/Audit.NET.DynamoDB/Audit.NET.DynamoDB.csproj index b7c6a48c..14d3f91d 100644 --- a/src/Audit.NET.DynamoDB/Audit.NET.DynamoDB.csproj +++ b/src/Audit.NET.DynamoDB/Audit.NET.DynamoDB.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs into Amazon DynamoDB Copyright 2018 Audit.DynamoDB - 15.3.0 + 16.0.0 Federico Colombo netstandard1.3;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.ElasticSearch/Audit.NET.Elasticsearch.csproj b/src/Audit.NET.ElasticSearch/Audit.NET.Elasticsearch.csproj index cf412b55..e1c143a4 100644 --- a/src/Audit.NET.ElasticSearch/Audit.NET.Elasticsearch.csproj +++ b/src/Audit.NET.ElasticSearch/Audit.NET.Elasticsearch.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs into Elasticsearch database Copyright 2018 Audit.Elasticsearch - 15.3.0 + 16.0.0 Federico Colombo net461;netstandard2.0 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.EventLog.Core/Audit.NET.EventLog.Core.csproj b/src/Audit.NET.EventLog.Core/Audit.NET.EventLog.Core.csproj index 5d30fa6a..a7203168 100644 --- a/src/Audit.NET.EventLog.Core/Audit.NET.EventLog.Core.csproj +++ b/src/Audit.NET.EventLog.Core/Audit.NET.EventLog.Core.csproj @@ -4,7 +4,7 @@ Log Audit.NET events to the Windows EventLog when targeting net standard 2.0 Copyright 2018 Audit.NET.EventLog.Core - 15.3.0 + 16.0.0 Federico Colombo netstandard2.0 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.MongoDB/Audit.NET.MongoDB.csproj b/src/Audit.NET.MongoDB/Audit.NET.MongoDB.csproj index b97af19c..9b511755 100644 --- a/src/Audit.NET.MongoDB/Audit.NET.MongoDB.csproj +++ b/src/Audit.NET.MongoDB/Audit.NET.MongoDB.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs into a MongoDB database Copyright 2016 Audit.MongoDB - 15.3.0 + 16.0.0 Federico Colombo netstandard1.5;net452 $(NoWarn);1591 diff --git a/src/Audit.NET.MySql/Audit.NET.MySql.csproj b/src/Audit.NET.MySql/Audit.NET.MySql.csproj index d6206407..9aafe66c 100644 --- a/src/Audit.NET.MySql/Audit.NET.MySql.csproj +++ b/src/Audit.NET.MySql/Audit.NET.MySql.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs into a MySQL database Copyright 2016 Audit.MySql - 15.3.0 + 16.0.0 Federico Colombo netstandard1.3;netstandard2.0;netcoreapp2.1;net45;net461 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.NLog/Audit.NET.NLog.csproj b/src/Audit.NET.NLog/Audit.NET.NLog.csproj index 0c1b3c0e..2a6ebae0 100644 --- a/src/Audit.NET.NLog/Audit.NET.NLog.csproj +++ b/src/Audit.NET.NLog/Audit.NET.NLog.csproj @@ -5,7 +5,7 @@ Log Audit.NET Audit Trail NLog™ Copyright 2019 Audit.NLog - 15.3.0 + 16.0.0 Dominick Marciano netstandard1.3;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj b/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj index abcf61ba..284d9aa6 100644 --- a/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj +++ b/src/Audit.NET.PostgreSql/Audit.NET.PostgreSql.csproj @@ -3,7 +3,7 @@ Store Audit.NET Trail Logs into a PostgreSQL database Copyright 2017 Audit.PostgreSql - 15.3.0 + 16.0.0 Federico Colombo netstandard2.0;netstandard1.3;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.Redis/Audit.NET.Redis.csproj b/src/Audit.NET.Redis/Audit.NET.Redis.csproj index 43a3b184..c63b5e58 100644 --- a/src/Audit.NET.Redis/Audit.NET.Redis.csproj +++ b/src/Audit.NET.Redis/Audit.NET.Redis.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs in a Redis database as a strings, lists, hashes, sortedsets or pubsub Copyright 2017 Audit.Redis - 15.3.0 + 16.0.0 Federico Colombo netstandard1.5;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj b/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj index 248d973d..572bd09e 100644 --- a/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj +++ b/src/Audit.NET.SqlServer/Audit.NET.SqlServer.csproj @@ -4,7 +4,7 @@ Store Audit.NET Trail Logs into a SQL Server database Copyright 2016 Audit.SqlServer - 15.3.0 + 16.0.0 Federico Colombo netstandard2.1;netstandard2.0;netstandard1.3;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.Udp/Audit.NET.Udp.csproj b/src/Audit.NET.Udp/Audit.NET.Udp.csproj index 5d0b7231..74bf3efa 100644 --- a/src/Audit.NET.Udp/Audit.NET.Udp.csproj +++ b/src/Audit.NET.Udp/Audit.NET.Udp.csproj @@ -4,7 +4,7 @@ Send Audit.NET Trail Logs as connectionless UDP datagrams to a remote host or a multicast group Copyright 2017 Audit.Udp - 15.3.0 + 16.0.0 Federico Colombo netstandard1.3;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET.log4net/Audit.NET.log4net.csproj b/src/Audit.NET.log4net/Audit.NET.log4net.csproj index 74607d17..5d74dcf0 100644 --- a/src/Audit.NET.log4net/Audit.NET.log4net.csproj +++ b/src/Audit.NET.log4net/Audit.NET.log4net.csproj @@ -4,7 +4,7 @@ Log Audit.NET Audit Trail using Apache log4net™ Copyright 2017 Audit.log4net - 15.3.0 + 16.0.0 Federico Colombo netstandard1.3;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET/Audit.NET.csproj b/src/Audit.NET/Audit.NET.csproj index aabd55b2..469646ca 100644 --- a/src/Audit.NET/Audit.NET.csproj +++ b/src/Audit.NET/Audit.NET.csproj @@ -3,7 +3,7 @@ An extensible framework to audit executing operations in .NET and .NET Core. Copyright 2016 Audit.NET - 15.3.0 + 16.0.0 Federico Colombo netstandard1.3;netstandard2.0;netstandard2.1;net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.NET/AuditScope.Helpers.cs b/src/Audit.NET/AuditScope.Helpers.cs new file mode 100644 index 00000000..aacdba6d --- /dev/null +++ b/src/Audit.NET/AuditScope.Helpers.cs @@ -0,0 +1,77 @@ +using System; +using System.Net.NetworkInformation; +using System.Threading.Tasks; + +namespace Audit.Core +{ + public partial class AuditScope + { + /// + /// Shortcut to create an audit scope + /// + public static AuditScope Create(AuditScopeOptions options) + { + return new AuditScope(options).Start(); + } + /// + /// Shortcut to create an audit scope + /// + public static async Task CreateAsync(AuditScopeOptions options) + { + return await new AuditScope(options).StartAsync(); + } + /// + /// Shortcut to create an audit scope with the given Event type and Target. + /// + /// A string representing the type of the event. + /// The target object getter. + /// An anonymous object that contains additional fields to be merged into the audit event. + public static AuditScope Create(string eventType, Func target, object extraFields = null) + { + var options = new AuditScopeOptions(eventType: eventType, targetGetter: target, extraFields: extraFields); + return new AuditScope(options).Start(); + } + /// + /// Shortcut to create an audit scope with the given Event type and Target. + /// + /// A string representing the type of the event. + /// The target object getter. + /// An anonymous object that contains additional fields to be merged into the audit event. + public static async Task CreateAsync(string eventType, Func target, object extraFields = null) + { + var options = new AuditScopeOptions(eventType: eventType, targetGetter: target, extraFields: extraFields); + return await new AuditScope(options).StartAsync(); + } + + /// + /// Creates an audit scope with the given extra fields, and saves it right away + /// + /// Type of the event. + /// An anonymous object that can contain additional fields to be merged into the audit event. + public static void Log(string eventType, object extraFields) + { + var options = new AuditScopeOptions() + { + EventType = eventType, + ExtraFields = extraFields, + IsCreateAndSave = true + }; + new AuditScope(options).Start(); + } + /// + /// Creates an audit scope with the given extra fields, and saves it right away + /// + /// Type of the event. + /// An anonymous object that can contain additional fields to be merged into the audit event. + public static async Task LogAsync(string eventType, object extraFields) + { + var options = new AuditScopeOptions() + { + EventType = eventType, + ExtraFields = extraFields, + IsCreateAndSave = true + }; + await new AuditScope(options).StartAsync(); + } + } +} diff --git a/src/Audit.NET/AuditScope.cs b/src/Audit.NET/AuditScope.cs index b6cb291f..d03fb54a 100644 --- a/src/Audit.NET/AuditScope.cs +++ b/src/Audit.NET/AuditScope.cs @@ -12,16 +12,13 @@ namespace Audit.Core /// /// Makes a code block auditable. /// - public partial class AuditScope : IDisposable -#if NETSTANDARD2_1 - , IAsyncDisposable -#endif + public partial class AuditScope : IAuditScope { private readonly AuditScopeOptions _options; -#region Constructors + #region Constructors [MethodImpl(MethodImplOptions.NoInlining)] - private AuditScope(AuditScopeOptions options) + internal AuditScope(AuditScopeOptions options) { _options = options; _creationPolicy = options.CreationPolicy ?? Configuration.CreationPolicy; @@ -32,7 +29,7 @@ private AuditScope(AuditScopeOptions options) Culture = System.Globalization.CultureInfo.CurrentCulture.ToString(), }; MethodBase callingMethod = options.CallingMethod; -#if NET45 || NETSTANDARD2_0 +#if NET45 || NETSTANDARD2_0 || NETSTANDARD2_1 environment.UserName = Environment.UserName; environment.MachineName = Environment.MachineName; environment.DomainName = Environment.UserDomainName; @@ -132,9 +129,9 @@ protected internal async Task StartAsync() } return this; } -#endregion + #endregion -#region Public Properties + #region Public Properties /// /// The current save mode. Useful on custom actions to determine the saving trigger. /// @@ -189,9 +186,9 @@ public EventCreationPolicy EventCreationPolicy return _creationPolicy; } } -#endregion + #endregion -#region Private fields + #region Private fields private SaveMode _saveMode; private readonly EventCreationPolicy _creationPolicy; private readonly AuditEvent _event; @@ -200,9 +197,9 @@ public EventCreationPolicy EventCreationPolicy private bool _ended; private readonly AuditDataProvider _dataProvider; private Func _targetGetter; -#endregion + #endregion -#region Public Methods + #region Public Methods /// /// Replaces the target object getter whose old/new value will be stored on the AuditEvent.Target property /// @@ -229,7 +226,7 @@ public void SetTargetGetter(Func targetGetter) /// public void Comment(string text) { - Comment(text, new object[0]); + Comment(text, new object[0]); } /// @@ -367,9 +364,9 @@ public async Task SaveAsync() EndEvent(); await SaveEventAsync(); } -#endregion + #endregion -#region Private Methods + #region Private Methods private bool IsEndedOrDisabled() { @@ -392,7 +389,7 @@ private void EndEvent() } } - private static Exception GetCurrentException() + private Exception GetCurrentException() { #pragma warning disable CS0618 // Type or member is obsolete if (PlatformHelper.IsRunningOnMono()) @@ -425,7 +422,7 @@ private void SaveEvent(bool forceInsert = false) { if (IsEndedOrDisabled()) { - return; + return; } // Execute custom on event saving actions Configuration.InvokeScopeCustomActions(ActionType.OnEventSaving, this); @@ -468,6 +465,6 @@ private async Task SaveEventAsync(bool forceInsert = false) // Execute custom after saving actions Configuration.InvokeScopeCustomActions(ActionType.OnEventSaved, this); } -#endregion + #endregion } } diff --git a/src/Audit.NET/AuditScope.Factory.cs b/src/Audit.NET/AuditScopeFactory.cs similarity index 51% rename from src/Audit.NET/AuditScope.Factory.cs rename to src/Audit.NET/AuditScopeFactory.cs index 4a3fd722..fcf876bb 100644 --- a/src/Audit.NET/AuditScope.Factory.cs +++ b/src/Audit.NET/AuditScopeFactory.cs @@ -1,4 +1,5 @@ -using System; +using Audit.Core.Providers; +using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -7,129 +8,72 @@ namespace Audit.Core /// /// A factory of scopes. /// - public partial class AuditScope + public class AuditScopeFactory : IAuditScopeFactory { + #region IAuditScopeFactory implementation /// - /// Creates an audit scope with the given extra fields, and saves it right away. - /// - /// Type of the event. - /// An anonymous object that can contain additional fields to be merged into the audit event. - /// The data provider to use. NULL to use the configured default data provider. - [MethodImpl(MethodImplOptions.NoInlining)] - public static void CreateAndSave(string eventType, object extraFields, AuditDataProvider dataProvider = null) - { - using (var scope = new AuditScope(new AuditScopeOptions(eventType, null, extraFields, dataProvider, null, true))) - { - scope.Start(); - } - } - - /// - /// Creates an audit scope with the given extra fields, and saves it right away using the globally configured data provider. Shortcut for CreateAndSave(). + /// Creates an audit scope with the given creation options. /// - /// Type of the event. - /// An anonymous object that can contain additional fields to be merged into the audit event. [MethodImpl(MethodImplOptions.NoInlining)] - public static void Log(string eventType, object extraFields) + public IAuditScope Create(AuditScopeOptions options) { - CreateAndSave(eventType, extraFields, null); - } - - /// - /// Creates an audit scope for a target object and an event type. - /// - /// Type of the event. - /// The reference object getter. - [MethodImpl(MethodImplOptions.NoInlining)] - public static AuditScope Create(string eventType, Func target) - { - return new AuditScope(new AuditScopeOptions(eventType, target, null, null, null)).Start(); + return new AuditScope(options).Start(); } /// - /// Creates an audit scope for a targer object and an event type, providing the creation policy and optionally the Data Provider. + /// Creates an audit scope with the given creation options. /// - /// Type of the event. - /// The reference object getter. - /// The event creation policy to use. - /// The data provider to use. NULL to use the configured default data provider. [MethodImpl(MethodImplOptions.NoInlining)] - public static AuditScope Create(string eventType, Func target, EventCreationPolicy creationPolicy, AuditDataProvider dataProvider = null) + public async Task CreateAsync(AuditScopeOptions options) { - return new AuditScope(new AuditScopeOptions(eventType, target, null, dataProvider, creationPolicy)).Start(); + return await new AuditScope(options).StartAsync(); } + #endregion /// - /// Creates an audit scope from a reference value, and an event type. + /// Creates an audit scope with the given extra fields, and saves it right away using the globally configured data provider. Shortcut for CreateAndSave(). /// /// Type of the event. - /// The reference object getter. /// An anonymous object that can contain additional fields to be merged into the audit event. [MethodImpl(MethodImplOptions.NoInlining)] - public static AuditScope Create(string eventType, Func target, object extraFields) + public void Log(string eventType, object extraFields) { - return new AuditScope(new AuditScopeOptions(eventType, target, extraFields, null, null)).Start(); - } - - /// - /// Creates an audit scope from a reference value, and an event type. - /// - /// Type of the event. - /// The reference object getter. - /// An anonymous object that can contain additional fields will be merged into the audit event. - /// The event creation policy to use. - /// The data provider to use. NULL to use the configured default data provider. - /// The initialized audit event to use, or NULL to create a new instance of AuditEvent. - /// Used to indicate how many frames in the stack should be skipped to determine the calling method. - [MethodImpl(MethodImplOptions.NoInlining)] - public static AuditScope Create(string eventType, Func target, object extraFields, EventCreationPolicy creationPolicy, AuditDataProvider dataProvider = null, AuditEvent auditEvent = null, int skipExtraFrames = 0) - { - return new AuditScope(new AuditScopeOptions(eventType, target, extraFields, dataProvider, creationPolicy, false, auditEvent, skipExtraFrames)).Start(); - } - - /// - /// Creates an audit scope with the given creation options. - /// - [MethodImpl(MethodImplOptions.NoInlining)] - public static AuditScope Create(AuditScopeOptions options) - { - return new AuditScope(options).Start(); + using (var scope = new AuditScope(new AuditScopeOptions(eventType, null, extraFields, null, null, true))) + { + scope.Start(); + } } - /// - /// Creates an audit scope with the given extra fields, and saves it right away. + /// Creates an audit scope with the given extra fields, and saves it right away using the globally configured data provider. Shortcut for CreateAndSaveAsync(). /// /// Type of the event. /// An anonymous object that can contain additional fields to be merged into the audit event. - /// The data provider to use. NULL to use the configured default data provider. [MethodImpl(MethodImplOptions.NoInlining)] - public static async Task CreateAndSaveAsync(string eventType, object extraFields, AuditDataProvider dataProvider = null) + public async Task LogAsync(string eventType, object extraFields) { - using (var scope = new AuditScope(new AuditScopeOptions(eventType, null, extraFields, dataProvider, null, true))) + using (var scope = new AuditScope(new AuditScopeOptions(eventType, null, extraFields, null, null, true))) { await scope.StartAsync(); } } /// - /// Creates an audit scope with the given extra fields, and saves it right away using the globally configured data provider. Shortcut for CreateAndSaveAsync(). + /// Creates an audit scope for a target object and an event type. /// /// Type of the event. - /// An anonymous object that can contain additional fields to be merged into the audit event. - /// The data provider to use. NULL to use the configured default data provider. + /// The reference object getter. [MethodImpl(MethodImplOptions.NoInlining)] - public static async Task LogAsync(string eventType, object extraFields, AuditDataProvider dataProvider = null) + public IAuditScope Create(string eventType, Func target) { - await CreateAndSaveAsync(eventType, extraFields, null); + return new AuditScope(new AuditScopeOptions(eventType, target, null, null, null)).Start(); } - /// /// Creates an audit scope for a target object and an event type. /// /// Type of the event. /// The reference object getter. [MethodImpl(MethodImplOptions.NoInlining)] - public static async Task CreateAsync(string eventType, Func target) + public async Task CreateAsync(string eventType, Func target) { return await new AuditScope(new AuditScopeOptions(eventType, target, null, null, null)).StartAsync(); } @@ -142,21 +86,21 @@ public static async Task CreateAsync(string eventType, Func /// The event creation policy to use. /// The data provider to use. NULL to use the configured default data provider. [MethodImpl(MethodImplOptions.NoInlining)] - public static async Task CreateAsync(string eventType, Func target, EventCreationPolicy creationPolicy, AuditDataProvider dataProvider = null) + public IAuditScope Create(string eventType, Func target, EventCreationPolicy creationPolicy, AuditDataProvider dataProvider) { - return await new AuditScope(new AuditScopeOptions(eventType, target, null, dataProvider, creationPolicy)).StartAsync(); + return new AuditScope(new AuditScopeOptions(eventType, target, null, dataProvider, creationPolicy)).Start(); } - /// - /// Creates an audit scope from a reference value, and an event type. + /// Creates an audit scope for a targer object and an event type, providing the creation policy and optionally the Data Provider. /// /// Type of the event. /// The reference object getter. - /// An anonymous object that can contain additional fields to be merged into the audit event. + /// The event creation policy to use. NULL to use the configured default policy. + /// The data provider to use. NULL to use the configured default data provider. [MethodImpl(MethodImplOptions.NoInlining)] - public static async Task CreateAsync(string eventType, Func target, object extraFields) + public async Task CreateAsync(string eventType, Func target, EventCreationPolicy? creationPolicy, AuditDataProvider dataProvider) { - return await new AuditScope(new AuditScopeOptions(eventType, target, extraFields, null, null)).StartAsync(); + return await new AuditScope(new AuditScopeOptions(eventType, target, null, dataProvider, creationPolicy)).StartAsync(); } /// @@ -164,24 +108,27 @@ public static async Task CreateAsync(string eventType, Func /// /// Type of the event. /// The reference object getter. - /// An anonymous object that can contain additional fields will be merged into the audit event. - /// The event creation policy to use. + /// An anonymous object that can contain additional fields to be merged into the audit event. + /// The event creation policy to use. NULL to use the configured default policy. /// The data provider to use. NULL to use the configured default data provider. - /// The initialized audit event to use, or NULL to create a new instance of AuditEvent. - /// Used to indicate how many frames in the stack should be skipped to determine the calling method. [MethodImpl(MethodImplOptions.NoInlining)] - public static async Task CreateAsync(string eventType, Func target, object extraFields, EventCreationPolicy creationPolicy, AuditDataProvider dataProvider = null, AuditEvent auditEvent = null, int skipExtraFrames = 0) + public IAuditScope Create(string eventType, Func target, object extraFields, EventCreationPolicy? creationPolicy, AuditDataProvider dataProvider) { - return await new AuditScope(new AuditScopeOptions(eventType, target, extraFields, dataProvider, creationPolicy, false, auditEvent, skipExtraFrames)).StartAsync(); + return new AuditScope(new AuditScopeOptions(eventType, target, extraFields, dataProvider, creationPolicy)).Start(); } - /// - /// Creates an audit scope with the given creation options. + /// Creates an audit scope from a reference value, and an event type. /// + /// Type of the event. + /// The reference object getter. + /// An anonymous object that can contain additional fields to be merged into the audit event. + /// The event creation policy to use. NULL to use the configured default policy. + /// The data provider to use. NULL to use the configured default data provider. [MethodImpl(MethodImplOptions.NoInlining)] - public static async Task CreateAsync(AuditScopeOptions options) + public async Task CreateAsync(string eventType, Func target, object extraFields, EventCreationPolicy? creationPolicy, AuditDataProvider dataProvider) { - return await new AuditScope(options).StartAsync(); + return await new AuditScope(new AuditScopeOptions(eventType, target, extraFields, dataProvider, creationPolicy)).StartAsync(); } + } } diff --git a/src/Audit.NET/Configuration.cs b/src/Audit.NET/Configuration.cs index 16154fde..4b8d5822 100644 --- a/src/Audit.NET/Configuration.cs +++ b/src/Audit.NET/Configuration.cs @@ -25,6 +25,20 @@ public static class Configuration /// public static AuditDataProvider DataProvider { get; set; } /// + /// Gets or Sets the Default audit scope factory. + /// + public static IAuditScopeFactory AuditScopeFactory + { + get + { + return _auditScopeFactory; + } + set + { + _auditScopeFactory = value ?? new AuditScopeFactory(); + } + } + /// /// Global switch to disable audit logging. Default is false. /// public static bool AuditDisabled { get; set; } @@ -37,6 +51,8 @@ public static class Configuration internal static object Locker = new object(); + private static IAuditScopeFactory _auditScopeFactory; + static Configuration() { AuditDisabled = false; @@ -49,6 +65,7 @@ static Configuration() }; SystemClock = new DefaultSystemClock(); ResetCustomActions(); + _auditScopeFactory = new AuditScopeFactory(); } /// diff --git a/src/Audit.NET/IAuditScope.cs b/src/Audit.NET/IAuditScope.cs new file mode 100644 index 00000000..affa4fb7 --- /dev/null +++ b/src/Audit.NET/IAuditScope.cs @@ -0,0 +1,28 @@ +using System; +using System.Threading.Tasks; + +namespace Audit.Core +{ + public interface IAuditScope : IDisposable +#if NETSTANDARD2_1 + , IAsyncDisposable +#endif + { + AuditDataProvider DataProvider { get; } + AuditEvent Event { get; } + EventCreationPolicy EventCreationPolicy { get; } + object EventId { get; } + string EventType { get; set; } + SaveMode SaveMode { get; } + void Comment(string text); + void Comment(string format, params object[] args); + void Discard(); +#if !NETSTANDARD2_1 + Task DisposeAsync(); +#endif + void Save(); + Task SaveAsync(); + void SetCustomField(string fieldName, TC value, bool serialize = false); + void SetTargetGetter(Func targetGetter); + } +} \ No newline at end of file diff --git a/src/Audit.NET/IAuditScopeFactory.cs b/src/Audit.NET/IAuditScopeFactory.cs new file mode 100644 index 00000000..da797961 --- /dev/null +++ b/src/Audit.NET/IAuditScopeFactory.cs @@ -0,0 +1,17 @@ +using System; +using System.Threading.Tasks; + +namespace Audit.Core +{ + public interface IAuditScopeFactory + { + /// + /// Creates an audit scope with the given creation options. + /// + IAuditScope Create(AuditScopeOptions options); + /// + /// Creates an audit scope with the given creation options. + /// + Task CreateAsync(AuditScopeOptions options); + } +} \ No newline at end of file diff --git a/src/Audit.SignalR/Audit.SignalR.csproj b/src/Audit.SignalR/Audit.SignalR.csproj index 861d884c..c35ce168 100644 --- a/src/Audit.SignalR/Audit.SignalR.csproj +++ b/src/Audit.SignalR/Audit.SignalR.csproj @@ -3,7 +3,7 @@ Generate Audit Logs for ASP.NET SignalR invokations Copyright 2016 Audit.SignalR - 15.3.0 + 16.0.0 Federico Colombo net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.SignalR/AuditPipelineModule.cs b/src/Audit.SignalR/AuditPipelineModule.cs index 3bf3af77..433778aa 100644 --- a/src/Audit.SignalR/AuditPipelineModule.cs +++ b/src/Audit.SignalR/AuditPipelineModule.cs @@ -24,6 +24,7 @@ public partial class AuditPipelineModule : HubPipelineModule public Func ErrorEventsFilter { get; set; } public AuditDataProvider AuditDataProvider { get; set; } + public IAuditScopeFactory AuditScopeFactory { get; set; } public EventCreationPolicy? CreationPolicy { get; set; } public string AuditEventType { get; set; } public bool AuditDisabled { get; set; } @@ -33,7 +34,7 @@ public partial class AuditPipelineModule : HubPipelineModule public AuditPipelineModule() { } public AuditPipelineModule(AuditDataProvider dataProvider = null, EventCreationPolicy? creationPolicy = null, - string auditEventType = null, bool includeHeaders = false, bool includeQueryString = false, bool auditDisabled = false) + string auditEventType = null, bool includeHeaders = false, bool includeQueryString = false, bool auditDisabled = false, IAuditScopeFactory auditScopeFactory = null) { AuditDataProvider = dataProvider; CreationPolicy = creationPolicy; @@ -41,6 +42,7 @@ public AuditPipelineModule(AuditDataProvider dataProvider = null, EventCreationP AuditDisabled = auditDisabled; IncludeHeaders = includeHeaders; IncludeQueryString = includeQueryString; + AuditScopeFactory = auditScopeFactory; } private bool AuditEventEnabled(SignalrEventBase @event) @@ -286,13 +288,14 @@ protected override void OnIncomingError(ExceptionContext exceptionContext, IHubI } } - private AuditScope CreateAuditScope(SignalrEventBase signalrEvent) + private IAuditScope CreateAuditScope(SignalrEventBase signalrEvent) { var auditEvent = new AuditEventSignalr() { Event = signalrEvent }; - var scope = AuditScope.Create(new AuditScopeOptions() + var factory = AuditScopeFactory ?? Core.Configuration.AuditScopeFactory; + var scope = factory.Create(new AuditScopeOptions() { EventType = (AuditEventType ?? "{event}").Replace("{event}", signalrEvent.EventType.ToString()), AuditEvent = auditEvent, diff --git a/src/Audit.WCF/Audit.WCF.csproj b/src/Audit.WCF/Audit.WCF.csproj index c2a08298..436bbbc0 100644 --- a/src/Audit.WCF/Audit.WCF.csproj +++ b/src/Audit.WCF/Audit.WCF.csproj @@ -4,7 +4,7 @@ Generate detailed Audit Logs for WCF service calls. Copyright 2016 Audit.Wcf - 15.3.0 + 16.0.0 Federico Colombo net45 $(DefineConstants);STRONG_NAME diff --git a/src/Audit.WCF/AuditBehavior.cs b/src/Audit.WCF/AuditBehavior.cs index 1441d66c..5805e968 100644 --- a/src/Audit.WCF/AuditBehavior.cs +++ b/src/Audit.WCF/AuditBehavior.cs @@ -17,11 +17,11 @@ public class AuditBehavior : BehaviorExtensionElement /// Gets the current audit scope for the running thread. /// Get this property from an audited WCF method to get the current audit scope. /// - public static AuditScope CurrentAuditScope + public static IAuditScope CurrentAuditScope { get { - return CallContext.LogicalGetData(WcfContextScopeKey) as AuditScope; + return CallContext.LogicalGetData(WcfContextScopeKey) as IAuditScope; } internal set { diff --git a/src/Audit.WCF/AuditScopeAsyncResult.cs b/src/Audit.WCF/AuditScopeAsyncResult.cs index 36cb7ca6..e4ab6153 100644 --- a/src/Audit.WCF/AuditScopeAsyncResult.cs +++ b/src/Audit.WCF/AuditScopeAsyncResult.cs @@ -17,7 +17,7 @@ internal AuditScopeAsyncResult(IAsyncResult originalResult, AuditScopeState audi } internal AuditScopeState AuditScopeState => _auditScopeState; - internal AuditScope AuditScope => _auditScopeState.AuditScope; + internal IAuditScope AuditScope => _auditScopeState.AuditScope; public bool IsCompleted => _originalResult.IsCompleted; public WaitHandle AsyncWaitHandle => _originalResult.AsyncWaitHandle; public object AsyncState => _auditScopeState.OriginalUserState; diff --git a/src/Audit.WCF/AuditScopeState.cs b/src/Audit.WCF/AuditScopeState.cs index 21d75ed5..a1b161c8 100644 --- a/src/Audit.WCF/AuditScopeState.cs +++ b/src/Audit.WCF/AuditScopeState.cs @@ -5,7 +5,7 @@ namespace Audit.WCF { internal class AuditScopeState { - public AuditScope AuditScope { get; set; } + public IAuditScope AuditScope { get; set; } public AsyncCallback OriginalUserCallback { get; set; } public object OriginalUserState { get; set; } } diff --git a/src/Audit.WebApi.Core/Audit.WebApi.Core.csproj b/src/Audit.WebApi.Core/Audit.WebApi.Core.csproj index 2beefdfb..215dfe13 100644 --- a/src/Audit.WebApi.Core/Audit.WebApi.Core.csproj +++ b/src/Audit.WebApi.Core/Audit.WebApi.Core.csproj @@ -4,7 +4,7 @@ Generate detailed Audit Logs for AspNet Core Web API Controller calls. Copyright 2016 Audit.WebApi.Core - 15.3.0 + 16.0.0 Federico Colombo netstandard1.6;netstandard2.0;net451;netstandard2.1;netcoreapp3.0 TRACE;DEBUG;STRONG_NAME @@ -65,6 +65,6 @@ - + diff --git a/src/Audit.WebApi/ApiControllerExtensions.cs b/src/Audit.WebApi/ApiControllerExtensions.cs index 37999e3c..f0c0d65f 100644 --- a/src/Audit.WebApi/ApiControllerExtensions.cs +++ b/src/Audit.WebApi/ApiControllerExtensions.cs @@ -41,7 +41,7 @@ public static void AddAuditFilter(this System.Web.Http.HttpConfiguration httpCon /// /// The API controller. /// The current Audit Scope or NULL. - public static AuditScope GetCurrentAuditScope(this Microsoft.AspNetCore.Mvc.ControllerBase apiController) + public static IAuditScope GetCurrentAuditScope(this Microsoft.AspNetCore.Mvc.ControllerBase apiController) { return AuditApiAdapter.GetCurrentScope(apiController.HttpContext); } @@ -52,7 +52,7 @@ public static AuditScope GetCurrentAuditScope(this Microsoft.AspNetCore.Mvc.Cont /// The API controller. /// The current Audit Scope or NULL. /// The context wrapper instance to use to provide the context. Default is NULL to use the default ContextWrapper. - public static AuditScope GetCurrentAuditScope(this System.Web.Http.ApiController apiController, IContextWrapper contextWrapper = null) + public static IAuditScope GetCurrentAuditScope(this System.Web.Http.ApiController apiController, IContextWrapper contextWrapper = null) { return AuditApiAdapter.GetCurrentScope(apiController.Request, contextWrapper); } @@ -64,7 +64,7 @@ public static AuditScope GetCurrentAuditScope(this System.Web.Http.ApiController /// /// The http context to get the scope from. /// The current Audit Scope or NULL. - public static AuditScope GetCurrentAuditScope(this HttpContext httpContext) + public static IAuditScope GetCurrentAuditScope(this HttpContext httpContext) { return AuditApiAdapter.GetCurrentScope(httpContext); } @@ -82,7 +82,7 @@ public static void DiscardCurrentAuditScope(this HttpContext httpContext) /// The http request to get the scope from. /// The current Audit Scope or NULL. /// The context wrapper instance to use to provide the context. Default is NULL to use the default ContextWrapper. - public static AuditScope GetCurrentAuditScope(this HttpRequestMessage httpRequest, IContextWrapper contextWrapper = null) + public static IAuditScope GetCurrentAuditScope(this HttpRequestMessage httpRequest, IContextWrapper contextWrapper = null) { return AuditApiAdapter.GetCurrentScope(httpRequest, contextWrapper); } diff --git a/src/Audit.WebApi/Audit.WebApi.csproj b/src/Audit.WebApi/Audit.WebApi.csproj index b2c2c10a..d85bcd4f 100644 --- a/src/Audit.WebApi/Audit.WebApi.csproj +++ b/src/Audit.WebApi/Audit.WebApi.csproj @@ -4,7 +4,7 @@ Generate detailed Audit Logs for Web API Controller calls. Copyright 2016 Audit.WebApi - 15.3.0 + 16.0.0 Federico Colombo netstandard1.6;netstandard2.0;net45;netstandard2.1;netcoreapp3.0 TRACE;DEBUG;STRONG_NAME diff --git a/src/Audit.WebApi/AuditApiAdapter.Core.cs b/src/Audit.WebApi/AuditApiAdapter.Core.cs index 930cd1c6..370ef1a8 100644 --- a/src/Audit.WebApi/AuditApiAdapter.Core.cs +++ b/src/Audit.WebApi/AuditApiAdapter.Core.cs @@ -17,6 +17,8 @@ using Microsoft.AspNetCore.Mvc.Abstractions; using System.Reflection; using Microsoft.AspNetCore.Http.Extensions; +using System.Runtime.CompilerServices; +using Audit.Core.Providers; namespace Audit.WebApi { @@ -250,11 +252,11 @@ private IDictionary GetActionParameters(ControllerActionDescript return args; } - internal static AuditScope GetCurrentScope(HttpContext httpContext) + internal static IAuditScope GetCurrentScope(HttpContext httpContext) { if (httpContext == null) { - return AuditScopeFactory.CreateNoOp(); + return CreateNoOpAuditScope(); } return httpContext.Items[AuditApiHelper.AuditApiScopeKey] as AuditScope; @@ -270,6 +272,11 @@ internal static void DiscardCurrentScope(HttpContext httpContext) } } + [MethodImpl(MethodImplOptions.NoInlining)] + private static IAuditScope CreateNoOpAuditScope() + { + return new AuditScopeFactory().Create(new AuditScopeOptions { DataProvider = new NullDataProvider() }); + } } } #endif \ No newline at end of file diff --git a/src/Audit.WebApi/AuditApiAdapter.cs b/src/Audit.WebApi/AuditApiAdapter.cs index 6230591f..e99898a8 100644 --- a/src/Audit.WebApi/AuditApiAdapter.cs +++ b/src/Audit.WebApi/AuditApiAdapter.cs @@ -13,6 +13,8 @@ using System.Collections.Specialized; using System.Reflection; using System.Linq; +using System.Runtime.CompilerServices; +using Audit.Core.Providers; namespace Audit.WebApi { @@ -211,16 +213,22 @@ private static IDictionary ToDictionary(NameValueCollection col) return dict; } - internal static AuditScope GetCurrentScope(HttpRequestMessage request, IContextWrapper contextWrapper) + internal static IAuditScope GetCurrentScope(HttpRequestMessage request, IContextWrapper contextWrapper) { if (request == null) { - return AuditScopeFactory.CreateNoOp(); + return CreateNoOpAuditScope(); } var ctx = contextWrapper ?? new ContextWrapper(request); return ctx.Get(AuditApiHelper.AuditApiScopeKey); } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static IAuditScope CreateNoOpAuditScope() + { + return new AuditScopeFactory().Create(new AuditScopeOptions { DataProvider = new NullDataProvider() }); + } } } #endif \ No newline at end of file diff --git a/src/Audit.WebApi/AuditScopeFactory.cs b/src/Audit.WebApi/AuditScopeFactory.cs deleted file mode 100644 index 4fb181b3..00000000 --- a/src/Audit.WebApi/AuditScopeFactory.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Audit.Core; -using Audit.Core.Providers; -using System.Runtime.CompilerServices; - -namespace Audit.WebApi -{ - internal class AuditScopeFactory - { - /// - /// Creates a no op audit scope - /// - [MethodImpl(MethodImplOptions.NoInlining)] - internal static AuditScope CreateNoOp() => AuditScope.Create(new AuditScopeOptions - { - DataProvider = new NullDataProvider() - }); - } -} diff --git a/test/Audit.DynamicProxy.UnitTest/Audit.DynamicProxy.UnitTest.csproj b/test/Audit.DynamicProxy.UnitTest/Audit.DynamicProxy.UnitTest.csproj index be8f6733..26a20547 100644 --- a/test/Audit.DynamicProxy.UnitTest/Audit.DynamicProxy.UnitTest.csproj +++ b/test/Audit.DynamicProxy.UnitTest/Audit.DynamicProxy.UnitTest.csproj @@ -22,7 +22,7 @@ - + diff --git a/test/Audit.IntegrationTest/AmazonQLDBTests.cs b/test/Audit.IntegrationTest/AmazonQLDBTests.cs index fcac3c0c..2ac37979 100644 --- a/test/Audit.IntegrationTest/AmazonQLDBTests.cs +++ b/test/Audit.IntegrationTest/AmazonQLDBTests.cs @@ -39,7 +39,7 @@ public void Test_AmazonQLDB_HappyPath() var sb = "init"; - using (var scope = AuditScope.Create("test_table", () => sb, new { MyCustomField = "value" })) + using (var scope = new AuditScopeFactory().Create("test_table", () => sb, new { MyCustomField = "value" }, null, null)) { sb += "-end"; } diff --git a/test/Audit.IntegrationTest/ElasticsearchTests.cs b/test/Audit.IntegrationTest/ElasticsearchTests.cs index 161f0684..15320a55 100644 --- a/test/Audit.IntegrationTest/ElasticsearchTests.cs +++ b/test/Audit.IntegrationTest/ElasticsearchTests.cs @@ -41,7 +41,7 @@ public void Test_Elasticsearch_HappyPath() var sb = "init"; - using (var scope = AuditScope.Create("eventType", () => sb, new { MyCustomField = "value" })) + using (var scope = new AuditScopeFactory().Create("eventType", () => sb, new { MyCustomField = "value" }, null, null)) { sb += "-end"; } @@ -75,7 +75,7 @@ public async Task Test_Elasticsearch_HappyPath_Async() var sb = "init"; - using (var scope = await AuditScope.CreateAsync("eventType", () => sb, new { MyCustomField = "value" })) + using (var scope = await new AuditScopeFactory().CreateAsync("eventType", () => sb, new { MyCustomField = "value" }, null, null)) { sb += "-end"; } diff --git a/test/Audit.IntegrationTest/EntityFrameworkTests.Core.cs b/test/Audit.IntegrationTest/EntityFrameworkTests.Core.cs index 9d6e9d47..b3ffd09f 100644 --- a/test/Audit.IntegrationTest/EntityFrameworkTests.Core.cs +++ b/test/Audit.IntegrationTest/EntityFrameworkTests.Core.cs @@ -1122,11 +1122,11 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) optionsBuilder.UseLazyLoadingProxies(); } - public override void OnScopeCreated(AuditScope auditScope) + public override void OnScopeCreated(IAuditScope auditScope) { Database.BeginTransaction(); } - public override void OnScopeSaving(AuditScope auditScope) + public override void OnScopeSaving(IAuditScope auditScope) { if (auditScope.GetEntityFrameworkEvent().Entries[0].ColumnValues.ContainsKey("BloggerName") && auditScope.GetEntityFrameworkEvent().Entries[0].ColumnValues["BloggerName"].ToString() == "ROLLBACK") diff --git a/test/Audit.IntegrationTest/EntityFrameworkTests.NET45.cs b/test/Audit.IntegrationTest/EntityFrameworkTests.NET45.cs index b175aea2..4de594ca 100644 --- a/test/Audit.IntegrationTest/EntityFrameworkTests.NET45.cs +++ b/test/Audit.IntegrationTest/EntityFrameworkTests.NET45.cs @@ -451,11 +451,11 @@ public MyBaseContext() public class MyTransactionalContext : MyBaseContext { - public override void OnScopeCreated(AuditScope auditScope) + public override void OnScopeCreated(IAuditScope auditScope) { Database.BeginTransaction(); } - public override void OnScopeSaving(AuditScope auditScope) + public override void OnScopeSaving(IAuditScope auditScope) { if (auditScope.Event.GetEntityFrameworkEvent().Entries[0].ColumnValues.ContainsKey("BloggerName") && auditScope.Event.GetEntityFrameworkEvent().Entries[0].ColumnValues["BloggerName"].Equals("ROLLBACK")) diff --git a/test/Audit.IntegrationTest/IntegrationTests.cs b/test/Audit.IntegrationTest/IntegrationTests.cs index 81c1e05d..5c47d2e5 100644 --- a/test/Audit.IntegrationTest/IntegrationTests.cs +++ b/test/Audit.IntegrationTest/IntegrationTests.cs @@ -331,7 +331,7 @@ public void TestStressAzureBlob() { var eventType = "event" + rnd.Next(1, 4); //1..3 var x = "start"; - using (var s = AuditScope.Create(eventType, () => x, EventCreationPolicy.InsertOnStartReplaceOnEnd)) + using (var s = new AuditScopeFactory().Create(eventType, () => x, EventCreationPolicy.InsertOnStartReplaceOnEnd, null)) { x = "end"; } @@ -378,7 +378,7 @@ public void TestStressDynamo() { var eventType = "AuditEvents"; var x = "start"; - using (var s = AuditScope.Create(eventType, () => x, EventCreationPolicy.InsertOnStartReplaceOnEnd)) + using (var s = new AuditScopeFactory().Create(eventType, () => x, EventCreationPolicy.InsertOnStartReplaceOnEnd, null)) { x = "end"; } @@ -501,7 +501,7 @@ public void TestMongoDateSerialization() evId = s.EventId; }); var now = DateTime.UtcNow; - using (var s = AuditScope.Create("test", null, new { someDate = now })) + using (var s = new AuditScopeFactory().Create("test", null, new { someDate = now }, null, null)) { } Audit.Core.Configuration.ResetCustomActions(); @@ -795,7 +795,7 @@ public void TestInsert() { var ev = (AuditEvent)null; CustomerOrder order = null; - using (var audit = AuditScope.Create("Order:Create", () => new TestStruct() { Id = 123, Order = order })) + using (var audit = new AuditScopeFactory().Create("Order:Create", () => new TestStruct() { Id = 123, Order = order })) { ev = audit.Event; order = DbCreateOrder(); @@ -810,7 +810,7 @@ public void TestDelete() IntegrationTests.CustomerOrder order = DbCreateOrder(); var ev = (AuditEvent)null; var orderId = order.OrderId; - using (var audit = AuditScope.Create("Order:Delete", () => new TestStruct() { Id = 123, Order = order }, new { ReferenceId = order.OrderId })) + using (var audit = new AuditScopeFactory().Create("Order:Delete", () => new TestStruct() { Id = 123, Order = order }, new { ReferenceId = order.OrderId }, null, null)) { ev = audit.Event; DbDeteleOrder(order.OrderId); diff --git a/test/Audit.UnitTest/FileDataProviderTests.cs b/test/Audit.UnitTest/FileDataProviderTests.cs index 83b24861..ed7ef589 100644 --- a/test/Audit.UnitTest/FileDataProviderTests.cs +++ b/test/Audit.UnitTest/FileDataProviderTests.cs @@ -57,7 +57,7 @@ public void Test_FileDataProvider_Loop() Configuration.DataProvider = fdp; var guid = "x" + Guid.NewGuid().ToString(); - AuditScope.Log(guid, loop); + new AuditScopeFactory().Log(guid, loop); var ev = fdp.GetEvent(Path.Combine(_directory, guid)); @@ -82,7 +82,7 @@ public async Task Test_FileDataProvider_LoopAsync() Configuration.DataProvider = fdp; var guid = "x" + Guid.NewGuid().ToString(); - await AuditScope.CreateAndSaveAsync(guid, loop); + await new AuditScopeFactory().CreateAsync(new AuditScopeOptions(guid, extraFields: loop, isCreateAndSave: true)); var ev = await fdp.GetEventAsync(Path.Combine(_directory, guid)); @@ -113,7 +113,7 @@ public void Test_FileDataProvider_Error() var guid = "x" + Guid.NewGuid().ToString(); try { - AuditScope.CreateAndSave(guid, loop); + new AuditScopeFactory().Create(new AuditScopeOptions(guid, extraFields: loop, isCreateAndSave: true)); Assert.Fail("Should not get here. JsonSettings not respected?"); } catch (JsonSerializationException ex) @@ -142,7 +142,7 @@ public async Task Test_FileDataProvider_ErrorAsync() var guid = "x" + Guid.NewGuid().ToString(); try { - await AuditScope.CreateAndSaveAsync(guid, loop); + await new AuditScopeFactory().CreateAsync(new AuditScopeOptions(guid, extraFields: loop, isCreateAndSave: true)); Assert.Fail("Should not get here. JsonSettings not respected?"); } catch (JsonSerializationException ex) diff --git a/test/Audit.UnitTest/HttpClientTests.cs b/test/Audit.UnitTest/HttpClientTests.cs index 014de53a..4fe3f028 100644 --- a/test/Audit.UnitTest/HttpClientTests.cs +++ b/test/Audit.UnitTest/HttpClientTests.cs @@ -1,5 +1,8 @@ -using Audit.Http; +using Audit.Core; +using Audit.Core.Providers; +using Audit.Http; using Audit.Http.ConfigurationApi; +using Moq; using Newtonsoft.Json; using NUnit.Framework; using System; @@ -375,7 +378,7 @@ public async Task Test_HttpAction_AuditDisabled() actions.Add(JsonConvert.DeserializeObject(JsonConvert.SerializeObject(ev.GetHttpAction()))); })); - + var url = "http://google.com/?q=test"; using (var cli = new HttpClient(new AuditHttpClientHandler() { RequestFilter = _ => false })) { @@ -385,6 +388,30 @@ public async Task Test_HttpAction_AuditDisabled() Assert.AreEqual(0, actions.Count); } - } + [Test] + public async Task Test_HttpAction_CustomAuditScopeFactory() + { + var actions = new List(); + Audit.Core.Configuration.DataProvider = null; + var dp = new DynamicDataProvider(); + dp.AttachOnInsertAndReplace(ev => + { + actions.Add(JsonConvert.DeserializeObject(JsonConvert.SerializeObject(ev.GetHttpAction()))); + }); + + var factory = new Mock(); + factory.Setup(_ => _.Create(It.IsAny())) + .Returns(new AuditScope(new AuditScopeOptions() { DataProvider = dp, AuditEvent = new AuditEventHttpClient() })); + var url = "http://google.com/?q=test"; + using (var cli = new HttpClient(new AuditHttpClientHandler() { RequestFilter = _ => true, AuditScopeFactory = factory.Object })) + { + await cli.GetAsync(url); + } + + Assert.AreEqual(1, actions.Count); + Assert.AreEqual(url, actions[0].Url); + Assert.AreEqual("GET", actions[0].Method); + } + } } diff --git a/test/Audit.UnitTest/Log4netTests.cs b/test/Audit.UnitTest/Log4netTests.cs index 09d5fa0f..cdbcf694 100644 --- a/test/Audit.UnitTest/Log4netTests.cs +++ b/test/Audit.UnitTest/Log4netTests.cs @@ -33,7 +33,7 @@ public void Test_log4net_InsertOnStartReplaceOnEnd() _adapter.Clear(); - using (var s = AuditScope.Create(new AuditScopeOptions() + using (var s = new AuditScopeFactory().Create(new AuditScopeOptions() { CreationPolicy = EventCreationPolicy.InsertOnStartReplaceOnEnd, EventType = "Test_log4net_InsertOnStartReplaceOnEnd" @@ -59,7 +59,7 @@ public void Test_log4net_InsertOnStartInsertOnEnd() _adapter.Clear(); - using (var s = AuditScope.Create(new AuditScopeOptions() + using (var s = new AuditScopeFactory().Create(new AuditScopeOptions() { CreationPolicy = EventCreationPolicy.InsertOnStartInsertOnEnd, EventType = "Test_log4net_InsertOnStartInsertOnEnd", diff --git a/test/Audit.UnitTest/NLogTests.cs b/test/Audit.UnitTest/NLogTests.cs index 2083146b..c617bffa 100644 --- a/test/Audit.UnitTest/NLogTests.cs +++ b/test/Audit.UnitTest/NLogTests.cs @@ -30,7 +30,7 @@ public void Test_NLog_InsertOnEnd() _adapter.Logs.Clear(); - using (var s = AuditScope.Create(new AuditScopeOptions() + using (var s = new AuditScopeFactory().Create(new AuditScopeOptions() { CreationPolicy = EventCreationPolicy.InsertOnEnd, EventType = nameof(Test_NLog_InsertOnEnd), @@ -58,7 +58,7 @@ public void Test_NLog_InsertOnStartReplaceOnEnd() _adapter.Logs.Clear(); - using (var s = AuditScope.Create(new AuditScopeOptions() + using (var s = new AuditScopeFactory().Create(new AuditScopeOptions() { CreationPolicy = EventCreationPolicy.InsertOnStartReplaceOnEnd, EventType = nameof(Test_NLog_InsertOnStartReplaceOnEnd) @@ -84,7 +84,7 @@ public void Test_NLog_InsertOnStartInsertOnEnd() _adapter.Logs.Clear(); - using (var s = AuditScope.Create(new AuditScopeOptions() + using (var s = new AuditScopeFactory().Create(new AuditScopeOptions() { CreationPolicy = EventCreationPolicy.InsertOnStartInsertOnEnd, EventType = nameof(Test_NLog_InsertOnStartInsertOnEnd), diff --git a/test/Audit.UnitTest/SignalrTests.cs b/test/Audit.UnitTest/SignalrTests.cs index 8077beb9..46c206c2 100644 --- a/test/Audit.UnitTest/SignalrTests.cs +++ b/test/Audit.UnitTest/SignalrTests.cs @@ -161,7 +161,29 @@ public void Test_Signalr_Error() Assert.IsTrue(evs[0].GetSignalrEvent().Exception.Contains("SomeParameter")); } + [Test] + public void Test_Signalr_CustomAuditScopeFactory() + { + var evs = new List(); + Configuration.DataProvider = null; + + var dp = new DynamicDataProvider(); + dp.AttachOnInsertAndReplace(ev => { evs.Add(ev); }); + + var factory = new Mock(); + factory.Setup(_ => _.Create(It.IsAny())) + .Returns(new AuditScope(new AuditScopeOptions() { DataProvider = dp, AuditEvent = new AuditEventSignalr() })); + + var module = new TestAuditPipelineModule() + { + AuditScopeFactory = factory.Object + }; + + SimulateIncomingError(module, new ArgumentNullException("SomeParameter", "message"), "cnn-Error", "err", new object[] { 0 }); + Task.Delay(50).Wait(); + Assert.AreEqual(1, evs.Count); + } [Test] public void Test_Signalr_Stress() diff --git a/test/Audit.UnitTest/UdpProviderUnitTests.cs b/test/Audit.UnitTest/UdpProviderUnitTests.cs index 5fbdccd9..c554b20d 100644 --- a/test/Audit.UnitTest/UdpProviderUnitTests.cs +++ b/test/Audit.UnitTest/UdpProviderUnitTests.cs @@ -30,7 +30,7 @@ public void Test_UdpDataProvider_BasicTest(string ip, int port, bool multicast) var listener = Task.Factory.StartNew(() => { Listen(re, ip, port, multicast); }, cts.Token); re.WaitOne(); Task.Delay(1000).Wait(); - using (var scope = AuditScope.Create("Test_UdpDataProvider_BasicTest", null, EventCreationPolicy.InsertOnStartReplaceOnEnd, p)) + using (var scope = new AuditScopeFactory().Create("Test_UdpDataProvider_BasicTest", null, EventCreationPolicy.InsertOnStartReplaceOnEnd, p)) { Task.Delay(100).Wait(); } @@ -64,7 +64,7 @@ public async Task Test_UdpDataProvider_BasicTest_Async(string ip, int port, bool var listener = Task.Factory.StartNew(() => { Listen(re, ip, port, multicast); }, cts.Token); re.WaitOne(); await Task.Delay(1000); - using (var scope = await AuditScope.CreateAsync("Test_UdpDataProvider_BasicTest", null, EventCreationPolicy.InsertOnStartReplaceOnEnd)) + using (var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions("Test_UdpDataProvider_BasicTest", null, null, null, EventCreationPolicy.InsertOnStartReplaceOnEnd))) { Task.Delay(100).Wait(); await scope.SaveAsync(); @@ -126,7 +126,7 @@ public void Test_UdpDataProvider_MultiThread(string ip, int port, bool multicast int a = i; tasks.Add(new Task(() => { - using (var scope = AuditScope.Create("Test_UdpDataProvider_MultiThread_" + a, null, EventCreationPolicy.InsertOnEnd, p)) + using (var scope = new AuditScopeFactory().Create("Test_UdpDataProvider_MultiThread_" + a, null, EventCreationPolicy.InsertOnEnd, p)) { } })); @@ -164,7 +164,7 @@ public void Test_UdpDataProvider_BigPacket(string ip, int port, bool multicast) Task.Delay(1000).Wait(); var target = Enumerable.Range(1, 10000).Select(_ => (byte)255).ToArray(); - using (var scope = AuditScope.Create("Test_UdpDataProvider_BigPacket", () => target, EventCreationPolicy.InsertOnEnd, p)) + using (var scope = new AuditScopeFactory().Create("Test_UdpDataProvider_BigPacket", () => target, EventCreationPolicy.InsertOnEnd, p)) { } @@ -182,7 +182,7 @@ public void Test_UdpDataProvider_PacketOverflow(string ip, int port, bool multic var target = Enumerable.Range(1, 66000).Select(_ => (byte)255).ToArray(); Assert.Throws(() => { - using (var scope = AuditScope.Create("Test_UdpDataProvider_BigPacket", () => target, EventCreationPolicy.InsertOnEnd, p)) + using (var scope = new AuditScopeFactory().Create("Test_UdpDataProvider_BigPacket", () => target, EventCreationPolicy.InsertOnEnd, p)) { } }); diff --git a/test/Audit.UnitTest/UnitTest.Async.cs b/test/Audit.UnitTest/UnitTest.Async.cs index 7c2e672b..1fc8d786 100644 --- a/test/Audit.UnitTest/UnitTest.Async.cs +++ b/test/Audit.UnitTest/UnitTest.Async.cs @@ -16,6 +16,39 @@ namespace Audit.UnitTest { public class UnitTestAsync { + [Test] + public async Task Test_AuditScope_Log_Async() + { + Audit.Core.Configuration.SystemClock = new MyClock(); + var evs = new List(); + Audit.Core.Configuration.Setup() + .Use(x => x.OnInsertAndReplace(ev => { evs.Add(ev); })) + .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); + await AuditScope.LogAsync("test", new { field1 = "one" }); + + Assert.AreEqual(1, evs.Count); + Assert.AreEqual("test", evs[0].EventType); + Assert.AreEqual("one", evs[0].CustomFields["field1"]); + } + + [Test] + public async Task Test_AuditScope_CallingMethod_Async() + { + Audit.Core.Configuration.SystemClock = new MyClock(); + var evs = new List(); + Audit.Core.Configuration.Setup() + .Use(x => x.OnInsertAndReplace(ev => { evs.Add(ev); })) + .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); + using (var scope = await AuditScope.CreateAsync("test", () => "target")) + { + } + using (var scope = await new AuditScopeFactory().CreateAsync("test", () => "target")) + { + } + + Assert.AreEqual(2, evs.Count); + } + [Test] public async Task Test_DynamicAsyncProvider_Async() { @@ -37,7 +70,7 @@ public async Task Test_DynamicAsyncProvider_Async() .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd); var target = "x1"; - using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions(){ TargetGetter = () => target })) + using (var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions(){ TargetGetter = () => target })) { target = "x2"; await scope.SaveAsync(); @@ -68,7 +101,7 @@ public async Task Test_FileLog_HappyPath_Async() .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd); var target = "start"; - using (var scope = await AuditScope.CreateAsync("evt", () => target, new { X = 1 })) + using (var scope = await new AuditScopeFactory().CreateAsync("evt", () => target, new { X = 1 }, null, null)) { target = "end"; await scope.DisposeAsync(); @@ -103,7 +136,7 @@ public async Task Test_ScopeSaveMode_CreateAndSave_Async() modes.Add(scope.SaveMode); })); - using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { IsCreateAndSave = true })) + using (var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions() { IsCreateAndSave = true })) { await scope.SaveAsync(); } @@ -127,7 +160,7 @@ public async Task Test_ScopeSaveMode_InsertOnStartReplaceOnEnd_Async() modes.Add(scope.SaveMode); })); - using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { })) + using (var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions() { })) { await scope.SaveAsync(); } @@ -153,7 +186,7 @@ public async Task Test_ScopeSaveMode_InsertOnStartInsertOnEnd_Async() modes.Add(scope.SaveMode); })); - using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { })) + using (var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions() { })) { await scope.SaveAsync(); } @@ -179,7 +212,7 @@ public async Task Test_ScopeSaveMode_InsertOnEnd_Async() modes.Add(scope.SaveMode); })); - using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { })) + using (var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions() { })) { await scope.SaveAsync(); } @@ -204,7 +237,7 @@ public async Task Test_ScopeSaveMode_Manual_Async() modes.Add(scope.SaveMode); })); - using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { })) + using (var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions() { })) { await scope.SaveAsync(); } @@ -236,17 +269,18 @@ public async Task Test_ScopeActionsStress_Async() })); var tasks = new List(); + var factory = new AuditScopeFactory(); for (int i = 0; i < MAX; i++) { tasks.Add(Task.Factory.StartNew(async () => { - await AuditScope.LogAsync("LoginSuccess", new { username = "federico", id = i }); + await factory.LogAsync("LoginSuccess", new { username = "federico", id = i }); Audit.Core.Configuration.AddCustomAction(ActionType.OnEventSaving, ev => { //do nothing, just bother var d = ev.Event.Duration * 1234567; }); - await AuditScope.CreateAndSaveAsync("LoginFailed", new { username = "adriano", id = i * -1 }); + await factory.CreateAsync(new AuditScopeOptions("LoginFailed", extraFields: new { username = "adriano", id = i * -1 }, isCreateAndSave: true)); })); } await Task.WhenAll(tasks.ToArray()); @@ -268,7 +302,7 @@ public async Task Test_DynamicDataProvider_Async() .OnReplace((obj, ev) => onReplaceCount++) .OnInsertAndReplace(ev => onInsertOrReplaceCount++)); - var scope = await AuditScope.CreateAsync("et1", null, EventCreationPolicy.Manual); + var scope = await new AuditScopeFactory().CreateAsync("et1", null, EventCreationPolicy.Manual, null); await scope.SaveAsync(); scope.SetCustomField("field", "value"); Assert.AreEqual(1, onInsertCount); @@ -289,9 +323,9 @@ public async Task Test_StartAndSave_Async() provider.Setup(p => p.Serialize(It.IsAny())).CallBase(); var eventType = "event type"; - await AuditScope.LogAsync(eventType, new { ExtraField = "extra value" }); + await new AuditScopeFactory().LogAsync(eventType, new { ExtraField = "extra value" }); - await AuditScope.CreateAndSaveAsync(eventType, new { Extra1 = new { SubExtra1 = "test1" }, Extra2 = "test2" }, provider.Object); + await new AuditScopeFactory().CreateAsync(new AuditScopeOptions(eventType, extraFields: new { Extra1 = new { SubExtra1 = "test1" }, Extra2 = "test2" }, dataProvider: provider.Object, isCreateAndSave: true)); provider.Verify(p => p.InsertEventAsync(It.IsAny()), Times.Once); provider.Verify(p => p.ReplaceEvent(It.IsAny(), It.IsAny()), Times.Never); provider.Verify(p => p.ReplaceEventAsync(It.IsAny(), It.IsAny()), Times.Never); @@ -320,7 +354,7 @@ public async Task Test_CustomAction_OnCreating_Async() }); AuditEvent ev; - using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnStartInsertOnEnd, provider.Object)) + using (var scope = await new AuditScopeFactory().CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnStartInsertOnEnd, provider.Object)) { ev = scope.Event; } @@ -346,7 +380,7 @@ public async Task Test_CustomAction_OnSaving_Async() scope.Comment(comment); }); AuditEvent ev; - using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) + using (var scope = await new AuditScopeFactory().CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; await scope.SaveAsync(); @@ -368,7 +402,7 @@ public async Task Test_CustomAction_OnSaving_Discard_Async() scope.Discard(); }); AuditEvent ev; - using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) + using (var scope = await new AuditScopeFactory().CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; await scope.SaveAsync(); @@ -397,7 +431,7 @@ public async Task Test_CustomAction_OnCreating_Double_Async() scope.SetCustomField(key2, "test"); }); AuditEvent ev; - using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) + using (var scope = await new AuditScopeFactory().CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; } @@ -419,7 +453,7 @@ public async Task TestSave_Async() var target = "initial"; var eventType = "SomeEvent"; AuditEvent ev; - using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnEnd)) + using (var scope = await new AuditScopeFactory().CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnEnd, null)) { ev = scope.Event; scope.Comment("test"); @@ -440,7 +474,7 @@ public async Task Test_Dispose_Async() { var provider = new Mock(); - await using (var scope = await AuditScope.CreateAsync(null, null, EventCreationPolicy.InsertOnEnd, dataProvider: provider.Object)) + await using (var scope = await new AuditScopeFactory().CreateAsync(null, null, EventCreationPolicy.InsertOnEnd, dataProvider: provider.Object)) { } @@ -457,7 +491,7 @@ public async Task TestDiscard_Async() var target = "initial"; var eventType = "SomeEvent"; AuditEvent ev; - using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnEnd)) + using (var scope = await new AuditScopeFactory().CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnEnd, null)) { ev = scope.Event; scope.Comment("test"); @@ -477,7 +511,7 @@ public async Task Test_EventCreationPolicy_InsertOnEnd_Async() { var provider = new Mock(); Core.Configuration.DataProvider = provider.Object; - using (var scope = await AuditScope.CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnEnd)) + using (var scope = await new AuditScopeFactory().CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnEnd, null)) { scope.Comment("test"); await scope.SaveAsync(); // this should do nothing because of the creation policy (this is no more true, since v 4.6.2) @@ -494,7 +528,7 @@ public async Task Test_EventCreationPolicy_InsertOnStartReplaceOnEnd_Async() var provider = new Mock(); provider.Setup(p => p.InsertEventAsync(It.IsAny())).Returns(() => Task.FromResult((object)Guid.NewGuid())); Core.Configuration.DataProvider = provider.Object; - using (var scope = await AuditScope.CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartReplaceOnEnd)) + using (var scope = await new AuditScopeFactory().CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartReplaceOnEnd, null)) { scope.Comment("test"); await scope.DisposeAsync(); @@ -510,7 +544,7 @@ public async Task Test_EventCreationPolicy_InsertOnStartInsertOnEnd_Async() provider.Setup(p => p.InsertEvent(It.IsAny())).Returns(() => Guid.NewGuid()); provider.Setup(p => p.InsertEventAsync(It.IsAny())).Returns(() => Task.FromResult((object)Guid.NewGuid())); Core.Configuration.DataProvider = provider.Object; - using (var scope = await AuditScope.CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartInsertOnEnd)) + using (var scope = await new AuditScopeFactory().CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartInsertOnEnd, null)) { scope.Comment("test"); } @@ -526,14 +560,14 @@ public async Task Test_EventCreationPolicy_Manual_Async() var provider = new Mock(); provider.Setup(p => p.InsertEventAsync(It.IsAny())).Returns(() => Task.FromResult((object)Guid.NewGuid())); Core.Configuration.DataProvider = provider.Object; - using (var scope = await AuditScope.CreateAsync("SomeEvent", () => "target", EventCreationPolicy.Manual)) + using (var scope = await new AuditScopeFactory().CreateAsync("SomeEvent", () => "target", EventCreationPolicy.Manual, null)) { scope.Comment("test"); } provider.Verify(p => p.InsertEvent(It.IsAny()), Times.Never); provider.Verify(p => p.InsertEventAsync(It.IsAny()), Times.Never); - using (var scope = await AuditScope.CreateAsync("SomeEvent", () => "target", EventCreationPolicy.Manual)) + using (var scope = await new AuditScopeFactory().CreateAsync("SomeEvent", () => "target", EventCreationPolicy.Manual, null)) { scope.Comment("test"); await scope.SaveAsync(); @@ -548,7 +582,7 @@ public async Task Test_EventCreationPolicy_Manual_Async() public async Task Test_ExtraFields_Async() { Core.Configuration.DataProvider = new FileDataProvider(); - var scope = await AuditScope.CreateAsync("SomeEvent", null, new { @class = "class value", DATA = 123 }, EventCreationPolicy.Manual); + var scope = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions("SomeEvent", null, new { @class = "class value", DATA = 123 }, null, EventCreationPolicy.Manual)); scope.Comment("test"); var ev = scope.Event; scope.Discard(); @@ -563,9 +597,9 @@ public async Task Test_TwoScopes_Async() provider.Setup(p => p.InsertEvent(It.IsAny())).Returns(() => Guid.NewGuid()); provider.Setup(p => p.InsertEventAsync(It.IsAny())).Returns(() => Task.FromResult((object)Guid.NewGuid())); Core.Configuration.DataProvider = provider.Object; - var scope1 = await AuditScope.CreateAsync("SomeEvent1", null, new { @class = "class value1", DATA = 111 }, EventCreationPolicy.Manual); + var scope1 = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions("SomeEvent1", null, new { @class = "class value1", DATA = 111 }, null, EventCreationPolicy.Manual)); await scope1.SaveAsync(); - var scope2 = await AuditScope.CreateAsync("SomeEvent2", null, new { @class = "class value2", DATA = 222 }, EventCreationPolicy.Manual); + var scope2 = await new AuditScopeFactory().CreateAsync(new AuditScopeOptions("SomeEvent2", null, new { @class = "class value2", DATA = 222 }, null, EventCreationPolicy.Manual)); await scope2.SaveAsync(); Assert.NotNull(scope1.EventId); Assert.NotNull(scope2.EventId); diff --git a/test/Audit.UnitTest/UnitTest.cs b/test/Audit.UnitTest/UnitTest.cs index ebf83fd7..407fed39 100644 --- a/test/Audit.UnitTest/UnitTest.cs +++ b/test/Audit.UnitTest/UnitTest.cs @@ -27,6 +27,43 @@ public void Setup() Audit.Core.Configuration.ResetCustomActions(); } + [Test] + public void Test_AuditScope_Log() + { + Audit.Core.Configuration.SystemClock = new MyClock(); + var evs = new List(); + Audit.Core.Configuration.Setup() + .Use(x => x.OnInsertAndReplace(ev => { evs.Add(ev); })) + .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); + AuditScope.Log("test", new { field1 = "one" }); + + Assert.AreEqual(1, evs.Count); + Assert.AreEqual("test", evs[0].EventType); + Assert.AreEqual("one", evs[0].CustomFields["field1"]); + Assert.IsTrue(evs[0].Environment.CallingMethodName.Contains("Test_AuditScope_Log")); + } + + [Test] + public void Test_AuditScope_CallingMethod() + { + Audit.Core.Configuration.SystemClock = new MyClock(); + var evs = new List(); + Audit.Core.Configuration.Setup() + .Use(x => x.OnInsertAndReplace(ev => { evs.Add(ev); })) + .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); + using (var scope = AuditScope.Create("test", () => "target")) + { + } + using (var scope = new AuditScopeFactory().Create("test", () => "target")) + { + } + + Assert.AreEqual(2, evs.Count); + Assert.IsTrue(evs[0].Environment.CallingMethodName.Contains("Test_AuditScope_CallingMethod")); + Assert.IsTrue(evs[1].Environment.CallingMethodName.Contains("Test_AuditScope_CallingMethod")); + } + + [Test] public void Test_AuditScope_CustomSystemClock() { @@ -40,7 +77,7 @@ public void Test_AuditScope_CustomSystemClock() })) .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); - using (var scope = AuditScope.Create("Test_AuditScope_CustomSystemClock", () => new { someProp = true })) + using (var scope = new AuditScopeFactory().Create("Test_AuditScope_CustomSystemClock", () => new { someProp = true })) { scope.SetCustomField("test", 123); } @@ -66,7 +103,7 @@ public void Test_AuditScope_SetTargetGetter() var obj = new SomeClass() { Id = 1, Name = "Test" }; - using (var scope = AuditScope.Create("Test", () => new { ShouldNotUseThisObject = true })) + using (var scope = new AuditScopeFactory().Create("Test", () => new { ShouldNotUseThisObject = true })) { scope.SetTargetGetter(() => obj); obj.Id = 2; @@ -96,7 +133,7 @@ public void Test_AuditScope_SetTargetGetter_ReturnsNull() .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); - using (var scope = AuditScope.Create("Test", () => new { ShouldNotUseThisObject = true })) + using (var scope = new AuditScopeFactory().Create("Test", () => new { ShouldNotUseThisObject = true })) { scope.SetTargetGetter(() => null); } @@ -120,7 +157,7 @@ public void Test_AuditScope_SetTargetGetter_IsNull() .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); - using (var scope = AuditScope.Create("Test", () => new { ShouldNotUseThisObject = true })) + using (var scope = new AuditScopeFactory().Create("Test", () => new { ShouldNotUseThisObject = true })) { scope.SetTargetGetter(null); } @@ -149,7 +186,7 @@ public void Test_AuditEvent_CustomSerializer() }; Audit.Core.Configuration.JsonSettings = jSettings; - using (var scope = AuditScope.Create("TEST", null, null)) + using (var scope = new AuditScopeFactory().Create("TEST", null, null, null, null)) { } @@ -185,7 +222,7 @@ public void Test_AuditDisable_AllDisabled() })) .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd); - using (var scope = AuditScope.Create("", null, null)) + using (var scope = new AuditScopeFactory().Create("", null, null, null, null)) { scope.Save(); scope.SaveAsync().Wait(); @@ -210,7 +247,7 @@ public void Test_AuditDisable_OnAction() Audit.Core.Configuration.AuditDisabled = true; })); - using (var scope = AuditScope.Create("", null, null)) + using (var scope = new AuditScopeFactory().Create("", null, null, null, null)) { scope.Save(); scope.SaveAsync().Wait(); @@ -290,7 +327,7 @@ public void Test_FileLog_HappyPath() .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd); var target = "start"; - using (var scope = AuditScope.Create("evt", () => target, new {X = 1})) + using (var scope = new AuditScopeFactory().Create("evt", () => target, new {X = 1}, null, null)) { target = "end"; } @@ -323,7 +360,7 @@ public void Test_ScopeSaveMode_CreateAndSave() modes.Add(scope.SaveMode); })); - using (var scope = AuditScope.Create(new AuditScopeOptions() { IsCreateAndSave = true })) + using (var scope = new AuditScopeFactory().Create(new AuditScopeOptions() { IsCreateAndSave = true })) { scope.Save(); } @@ -347,7 +384,7 @@ public void Test_ScopeSaveMode_InsertOnStartReplaceOnEnd() modes.Add(scope.SaveMode); })); - using (var scope = AuditScope.Create(new AuditScopeOptions() { })) + using (var scope = new AuditScopeFactory().Create(new AuditScopeOptions() { })) { scope.Save(); } @@ -373,7 +410,7 @@ public void Test_ScopeSaveMode_InsertOnStartInsertOnEnd() modes.Add(scope.SaveMode); })); - using (var scope = AuditScope.Create(new AuditScopeOptions() { })) + using (var scope = new AuditScopeFactory().Create(new AuditScopeOptions() { })) { scope.Save(); } @@ -399,7 +436,7 @@ public void Test_ScopeSaveMode_InsertOnEnd() modes.Add(scope.SaveMode); })); - using (var scope = AuditScope.Create(new AuditScopeOptions() { })) + using (var scope = new AuditScopeFactory().Create(new AuditScopeOptions() { })) { scope.Save(); } @@ -424,7 +461,7 @@ public void Test_ScopeSaveMode_Manual() modes.Add(scope.SaveMode); })); - using (var scope = AuditScope.Create(new AuditScopeOptions() { })) + using (var scope = new AuditScopeFactory().Create(new AuditScopeOptions() { })) { scope.Save(); } @@ -456,17 +493,18 @@ public void Test_ScopeActionsStress() })); var tasks = new List(); + var factory = new AuditScopeFactory(); for (int i = 0; i < MAX; i++) { tasks.Add(Task.Factory.StartNew(() => { - AuditScope.Log("LoginSuccess", new { username = "federico", id = i }); + factory.Log("LoginSuccess", new { username = "federico", id = i }); Audit.Core.Configuration.AddCustomAction(ActionType.OnEventSaving, ev => { //do nothing, just bother var d = ev.Event.Duration * 1234567; }); - AuditScope.CreateAndSave("LoginFailed", new { username = "adriano", id = i * -1 }); + factory.Create(new AuditScopeOptions("LoginFailed", null, new { username = "adriano", id = i * -1 }, null, null, true)); })); } Task.WaitAll(tasks.ToArray()); @@ -487,7 +525,7 @@ public void Test_DynamicDataProvider() .OnReplace((obj, ev) => onReplaceCount++) .OnInsertAndReplace(ev => onInsertOrReplaceCount++)); - var scope = AuditScope.Create("et1", null, EventCreationPolicy.Manual); + var scope = new AuditScopeFactory().Create("et1", null, EventCreationPolicy.Manual, null); scope.Save(); scope.SetCustomField("field", "value"); Assert.AreEqual(1, onInsertCount); @@ -537,7 +575,7 @@ public void Test_FluentConfig_FileLog() .UseFileLogProvider(config => config.Directory(@"C:\").FilenamePrefix("prefix")) .WithCreationPolicy(EventCreationPolicy.Manual) .WithAction(action => action.OnScopeCreated(s => x++)); - var scope = AuditScope.Create("test", null); + var scope = new AuditScopeFactory().Create("test", null); scope.Dispose(); Assert.AreEqual(typeof(FileDataProvider), Core.Configuration.DataProvider.GetType()); Assert.AreEqual("prefix", (Core.Configuration.DataProvider as FileDataProvider).FilenamePrefix); @@ -553,7 +591,7 @@ public void Test_FluentConfig_EventLog() Core.Configuration.Setup() .UseEventLogProvider(config => config.LogName("LogName").SourcePath("SourcePath").MachineName("MachineName")) .WithCreationPolicy(EventCreationPolicy.Manual); - var scope = AuditScope.Create("test", null); + var scope = new AuditScopeFactory().Create("test", null); scope.Dispose(); Assert.AreEqual(typeof(EventLogDataProvider), Core.Configuration.DataProvider.GetType()); Assert.AreEqual("LogName", (Core.Configuration.DataProvider as EventLogDataProvider).LogName); @@ -569,9 +607,9 @@ public void Test_StartAndSave() provider.Setup(p => p.Serialize(It.IsAny())).CallBase(); var eventType = "event type"; - AuditScope.Log(eventType, new { ExtraField = "extra value" }); + new AuditScopeFactory().Log(eventType, new { ExtraField = "extra value" }); - AuditScope.CreateAndSave(eventType, new { Extra1 = new { SubExtra1 = "test1" }, Extra2 = "test2" }, provider.Object); + new AuditScopeFactory().Create(new AuditScopeOptions(eventType, null, new { Extra1 = new { SubExtra1 = "test1" }, Extra2 = "test2" }, provider.Object, null, true)); provider.Verify(p => p.InsertEvent(It.IsAny()), Times.Once); provider.Verify(p => p.ReplaceEvent(It.IsAny(), It.IsAny()), Times.Never); @@ -599,7 +637,7 @@ public void Test_CustomAction_OnCreating() }); AuditEvent ev; - using (var scope = AuditScope.Create(eventType, () => target, EventCreationPolicy.InsertOnStartInsertOnEnd, provider.Object)) + using (var scope = new AuditScopeFactory().Create(eventType, () => target, EventCreationPolicy.InsertOnStartInsertOnEnd, provider.Object)) { ev = scope.Event; } @@ -623,7 +661,7 @@ public void Test_CustomAction_OnSaving() scope.Comment(comment); }); AuditEvent ev; - using (var scope = AuditScope.Create(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) + using (var scope = new AuditScopeFactory().Create(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; scope.Save(); @@ -666,7 +704,7 @@ public void Test_CustomAction_OnSaving_Discard() scope.Discard(); }); AuditEvent ev; - using (var scope = AuditScope.Create(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) + using (var scope = new AuditScopeFactory().Create(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; scope.Save(); @@ -694,7 +732,7 @@ public void Test_CustomAction_OnCreating_Double() scope.SetCustomField(key2, "test"); }); AuditEvent ev; - using (var scope = AuditScope.Create(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) + using (var scope = new AuditScopeFactory().Create(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; } @@ -714,7 +752,7 @@ public void TestSave() var target = "initial"; var eventType = "SomeEvent"; AuditEvent ev; - using (var scope = AuditScope.Create(eventType, () => target, EventCreationPolicy.InsertOnEnd)) + using (var scope = new AuditScopeFactory().Create(eventType, () => target, EventCreationPolicy.InsertOnEnd, null)) { ev = scope.Event; scope.Comment("test"); @@ -733,7 +771,7 @@ public void Test_Dispose() { var provider = new Mock(); - using (var scope = AuditScope.Create(null, null, EventCreationPolicy.InsertOnEnd, provider.Object)) + using (var scope = new AuditScopeFactory().Create(null, null, EventCreationPolicy.InsertOnEnd, provider.Object)) { } @@ -749,7 +787,7 @@ public void TestDiscard() var target = "initial"; var eventType = "SomeEvent"; AuditEvent ev; - using (var scope = AuditScope.Create(eventType, () => target, EventCreationPolicy.InsertOnEnd)) + using (var scope = new AuditScopeFactory().Create(eventType, () => target, EventCreationPolicy.InsertOnEnd, null)) { ev = scope.Event; scope.Comment("test"); @@ -768,7 +806,7 @@ public void Test_EventCreationPolicy_InsertOnEnd() { var provider = new Mock(); Core.Configuration.DataProvider = provider.Object; - using (var scope = AuditScope.Create("SomeEvent", () => "target", EventCreationPolicy.InsertOnEnd)) + using (var scope = new AuditScopeFactory().Create("SomeEvent", () => "target", EventCreationPolicy.InsertOnEnd, null)) { scope.Comment("test"); scope.Save(); // this should do nothing because of the creation policy (this is no more true, since v 4.6.2) @@ -783,7 +821,7 @@ public void Test_EventCreationPolicy_InsertOnStartReplaceOnEnd() var provider = new Mock(); provider.Setup(p => p.InsertEvent(It.IsAny())).Returns(() => Guid.NewGuid()); Core.Configuration.DataProvider = provider.Object; - using (var scope = AuditScope.Create("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartReplaceOnEnd)) + using (var scope = new AuditScopeFactory().Create("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartReplaceOnEnd, null)) { scope.Comment("test"); } @@ -797,7 +835,7 @@ public void Test_EventCreationPolicy_InsertOnStartInsertOnEnd() var provider = new Mock(); provider.Setup(p => p.InsertEvent(It.IsAny())).Returns(() => Guid.NewGuid()); Core.Configuration.DataProvider = provider.Object; - using (var scope = AuditScope.Create("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartInsertOnEnd)) + using (var scope = new AuditScopeFactory().Create("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartInsertOnEnd, null)) { scope.Comment("test"); } @@ -811,13 +849,13 @@ public void Test_EventCreationPolicy_Manual() var provider = new Mock(); provider.Setup(p => p.InsertEvent(It.IsAny())).Returns(() => Guid.NewGuid()); Core.Configuration.DataProvider = provider.Object; - using (var scope = AuditScope.Create("SomeEvent", () => "target", EventCreationPolicy.Manual)) + using (var scope = new AuditScopeFactory().Create("SomeEvent", () => "target", EventCreationPolicy.Manual, null)) { scope.Comment("test"); } provider.Verify(p => p.InsertEvent(It.IsAny()), Times.Never); - using (var scope = AuditScope.Create("SomeEvent", () => "target", EventCreationPolicy.Manual)) + using (var scope = new AuditScopeFactory().Create("SomeEvent", () => "target", EventCreationPolicy.Manual, null)) { scope.Comment("test"); scope.Save(); @@ -832,7 +870,7 @@ public void Test_EventCreationPolicy_Manual() public void Test_ExtraFields() { Core.Configuration.DataProvider = new FileDataProvider(); - var scope = AuditScope.Create("SomeEvent", null, new { @class = "class value", DATA = 123 }, EventCreationPolicy.Manual); + var scope = new AuditScopeFactory().Create(new AuditScopeOptions("SomeEvent", null, new { @class = "class value", DATA = 123 }, null, EventCreationPolicy.Manual)); scope.Comment("test"); var ev = scope.Event; scope.Discard(); @@ -846,9 +884,9 @@ public void Test_TwoScopes() var provider = new Mock(); provider.Setup(p => p.InsertEvent(It.IsAny())).Returns(() => Guid.NewGuid()); Core.Configuration.DataProvider = provider.Object; - var scope1 = AuditScope.Create("SomeEvent1", null, new { @class = "class value1", DATA = 111 }, EventCreationPolicy.Manual); + var scope1 = new AuditScopeFactory().Create(new AuditScopeOptions("SomeEvent1", null, new { @class = "class value1", DATA = 111 }, null, EventCreationPolicy.Manual)); scope1.Save(); - var scope2 = AuditScope.Create("SomeEvent2", null, new { @class = "class value2", DATA = 222 }, EventCreationPolicy.Manual); + var scope2 = new AuditScopeFactory().Create(new AuditScopeOptions("SomeEvent2", null, new { @class = "class value2", DATA = 222 }, null, EventCreationPolicy.Manual)); scope2.Save(); Assert.NotNull(scope1.EventId); Assert.NotNull(scope2.EventId); diff --git a/test/testns.bat b/test/testns.bat index eaf13604..82ee945f 100644 --- a/test/testns.bat +++ b/test/testns.bat @@ -20,6 +20,7 @@ cd test cd Audit.Mvc.UnitTest echo ---------------------------------------------- RUNNING MVC UNIT TESTS (1/17) ---------------------------------------------- +TITLE RUNNING MVC UNIT TESTS (1/17) dotnet test --logger:"console;verbosity=normal" echo Running... @@ -28,13 +29,16 @@ cd .. cd Audit.UnitTest echo ---------------------------------------------- RUNNING GENERAL UNIT TESTS (2/17) ---------------------------------------------- +TITLE RUNNING GENERAL UNIT TESTS (2/17) dotnet test --logger:"console;verbosity=normal" echo Running... cd .. + cd Audit.WebApi.UnitTest echo ---------------------------------------------- RUNNING WEB API UNIT TESTS (3/17) ---------------------------------------------- +TITLE RUNNING WEB API UNIT TESTS (3/17) dotnet test --logger:"console;verbosity=normal" echo Running... @@ -43,11 +47,13 @@ cd .. cd Audit.Integration.AspNetCore echo ---------------------------------------------- RUNNING ASP NET CORE UNIT TESTS (4/17) ---------------------------------------------- +TITLE RUNNING ASP NET CORE UNIT TESTS (4/17) dotnet run cd .. cd Audit.DynamicProxy.UnitTest echo ---------------------------------------------- RUNNING DYNAMIC PROXY UNIT TESTS (5/17) ---------------------------------------------- +TITLE RUNNING DYNAMIC PROXY UNIT TESTS (5/17) dotnet test --logger:"console;verbosity=normal" echo Running... @@ -55,6 +61,7 @@ cd .. cd Audit.EntityFramework.Core.UnitTest echo ---------------------------------------------- RUNNING EF CORE UNIT TESTS (6/17) ---------------------------------------------- +TITLE RUNNING EF CORE UNIT TESTS (6/17) dotnet test --logger:"console;verbosity=normal" echo Running... @@ -62,6 +69,7 @@ cd .. cd Audit.EntityFramework.UnitTest echo ---------------------------------------------- RUNNING EF FULL UNIT TESTS (7/17) ---------------------------------------------- +TITLE RUNNING EF FULL UNIT TESTS (7/17) IF NOT EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe" ( echo The file does not exist exit /B 1 @@ -76,12 +84,14 @@ cd .. cd Audit.EntityFramework.Full.UnitTest echo ---------------------------------------------- RUNNING EF FULL UNIT TESTS (8/17) ---------------------------------------------- +TITLE RUNNING EF FULL UNIT TESTS (8/17) dotnet test --logger:"console;verbosity=normal" echo Running... cd .. cd Audit.Redis.UnitTest echo ---------------------------------------------- RUNNING REDIS UNIT TESTS (9/17) ---------------------------------------------- +TITLE RUNNING REDIS UNIT TESTS (9/17) dotnet test --logger:"console;verbosity=normal" echo Running... @@ -89,24 +99,34 @@ cd .. cd Audit.IntegrationTest echo ---------------------------------------------- RUNNING GENERAL INTEGRATION TEST (10/16) ---------------------------------------------- +TITLE RUNNING GENERAL INTEGRATION TEST (10/16) dotnet test --logger:"console;verbosity=normal" --filter "TestCategory!=AzureDocDb&TestCategory!=AzureBlob&TestCategory!=WCF&TestCategory!=Elasticsearch&TestCategory!=Dynamo&TestCategory!=PostgreSQL" echo ---------------------------------------------- RUNNING PostgreSQL INTEGRATION TEST (11/17) ---------------------------------------------- +TITLE RUNNING PostgreSQL INTEGRATION TEST (11/17) dotnet test --logger:"console;verbosity=normal" --filter "TestCategory=PostgreSQL" echo ---------------------------------------------- RUNNING Azure Cosmos DB INTEGRATION TEST (12/17) ---------------------------------------------- +TITLE Azure Cosmos DB INTEGRATION TEST (12/17) dotnet test --logger:"console;verbosity=normal" --filter "TestCategory=AzureDocDb" echo ---------------------------------------------- RUNNING Azure BLOB INTEGRATION TEST (13/17) ---------------------------------------------- +TITLE RUNNING Azure BLOB INTEGRATION TEST (13/17) dotnet test --logger:"console;verbosity=normal" --filter "TestCategory=AzureBlob" echo ---------------------------------------------- RUNNING WCF SYNC INTEGRATION TEST (14/17) ---------------------------------------------- +TITLE RUNNING WCF SYNC INTEGRATION TEST (14/17) dotnet test --logger:"console;verbosity=normal" -f net452 --filter "TestCategory=WCF&TestCategory!=Async" echo ---------------------------------------------- RUNNING WCF ASYNC INTEGRATION TEST (15/17) ---------------------------------------------- +TITLE RUNNING WCF ASYNC INTEGRATION TEST (15/17) dotnet test --logger:"console;verbosity=normal" -f net452 --filter "TestCategory=WCF&TestCategory=Async" echo ---------------------------------------------- RUNNING ELASTICSEARCH INTEGRATION TEST (16/17) ---------------------------------------------- +TITLE RUNNING ELASTICSEARCH INTEGRATION TEST (16/17) dotnet test --logger:"console;verbosity=normal" --filter "TestCategory=Elasticsearch" echo ---------------------------------------------- RUNNING DYNAMO DB INTEGRATION TEST (17/17) ---------------------------------------------- +TITLE RUNNING DYNAMO DB INTEGRATION TEST (17/17) dotnet test --logger:"console;verbosity=normal" --filter "TestCategory=Dynamo" cd .. +title Audit.NET Unit Tests Runner + ECHO. ECHO --- PRESS ENTER TO STOP THE SERVICES (or CTRL+C to cancel) pause>nul @@ -116,4 +136,8 @@ net stop mysql80 net stop postgresql-x64-9.6 taskkill /f /im java.exe taskkill /f /im mongod.exe -taskkill /f /im redis-server.exe \ No newline at end of file +taskkill /f /im redis-server.exe + +echo Enabling GitHub nuget source +nuget sources enable -name GitHub +echo.