public async Task Test_CustomAction_OnCreating_Double_Async() { var provider = new Mock <AuditDataProvider>(); provider.Setup(p => p.Serialize(It.IsAny <string>())).CallBase(); var eventType = "event type 1"; var target = "test"; var key1 = "key1"; var key2 = "key2"; Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope => { scope.SetCustomField(key1, "test"); }); Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope => { scope.Event.CustomFields.Remove(key1); scope.SetCustomField(key2, "test"); }); AuditEvent ev; using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; } Core.Configuration.ResetCustomActions(); Assert.False(ev.CustomFields.ContainsKey(key1)); Assert.True(ev.CustomFields.ContainsKey(key2)); provider.Verify(p => p.InsertEvent(It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.ReplaceEvent(It.IsAny <object>(), It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.ReplaceEventAsync(It.IsAny <object>(), It.IsAny <AuditEvent>()), Times.Never); }
/// <summary> /// Occurs before the action method is invoked. /// </summary> internal async Task BeforeExecutingAsync(ActionExecutingContext actionContext, bool includeHeaders, bool includeRequestBody, bool serializeParams, string eventTypeName) { var httpContext = actionContext.HttpContext; var actionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor; var auditAction = await CreateOrUpdateAction(actionContext, includeHeaders, includeRequestBody, serializeParams, eventTypeName); var eventType = (eventTypeName ?? "{verb} {controller}/{action}").Replace("{verb}", auditAction.HttpMethod) .Replace("{controller}", auditAction.ControllerName) .Replace("{action}", auditAction.ActionName) .Replace("{url}", auditAction.RequestUrl); // Create the audit scope var auditEventAction = new AuditEventWebApi() { Action = auditAction }; var auditScope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = eventType, AuditEvent = auditEventAction, CallingMethod = actionDescriptor.MethodInfo }); httpContext.Items[AuditApiHelper.AuditApiActionKey] = auditAction; httpContext.Items[AuditApiHelper.AuditApiScopeKey] = auditScope; }
public async Task Test_CustomAction_OnCreating_Async() { var provider = new Mock <AuditDataProvider>(); provider.Setup(p => p.Serialize(It.IsAny <string>())).CallBase(); var eventType = "event type 1"; var target = "test"; Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope => { scope.SetCustomField("custom field", "test"); if (scope.EventType == eventType) { scope.Discard(); } }); Core.Configuration.AddCustomAction(ActionType.OnEventSaving, scope => { Assert.True(false, "This should not be executed"); }); AuditEvent ev; using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnStartInsertOnEnd, provider.Object)) { ev = scope.Event; } Core.Configuration.ResetCustomActions(); Assert.True(ev.CustomFields.ContainsKey("custom field")); provider.Verify(p => p.InsertEvent(It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.ReplaceEvent(It.IsAny <object>(), It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.ReplaceEventAsync(It.IsAny <object>(), It.IsAny <AuditEvent>()), Times.Never); }
public async Task Test_CustomAction_OnSaving_Async() { var provider = new Mock <AuditDataProvider>(); provider.Setup(p => p.Serialize(It.IsAny <string>())).CallBase(); //provider.Setup(p => p.InsertEvent(It.IsAny<AuditEvent>())).Returns((AuditEvent e) => e.Comments); var eventType = "event type 1"; var target = "test"; var comment = "comment test"; Core.Configuration.AddCustomAction(ActionType.OnEventSaving, scope => { scope.Comment(comment); }); AuditEvent ev; using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.Manual, provider.Object)) { ev = scope.Event; await scope.SaveAsync(); } Core.Configuration.ResetCustomActions(); Assert.True(ev.Comments.Contains(comment)); provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Once); }
/// <summary> /// Occurs before the action method is invoked. /// </summary> /// <param name="actionContext">The action context.</param> private async Task BeforeExecutingAsync(ActionExecutingContext actionContext) { var httpContext = actionContext.HttpContext; var actionDescriptior = actionContext.ActionDescriptor as ControllerActionDescriptor; var auditAction = new AuditApiAction { UserName = httpContext.User?.Identity.Name, IpAddress = httpContext.Connection?.RemoteIpAddress.ToString(), RequestUrl = string.Format("{0}://{1}{2}", httpContext.Request.Scheme, httpContext.Request.Host, httpContext.Request.Path), HttpMethod = actionContext.HttpContext.Request.Method, FormVariables = httpContext.Request.HasFormContentType ? ToDictionary(httpContext.Request.Form) : null, Headers = IncludeHeaders ? ToDictionary(httpContext.Request.Headers) : null, ActionName = actionDescriptior != null ? actionDescriptior.ActionName : actionContext.ActionDescriptor.DisplayName, ControllerName = actionDescriptior != null ? actionDescriptior.ControllerName : null, ActionParameters = GetActionParameters(actionContext.ActionArguments), RequestBody = new BodyContent { Type = httpContext.Request.ContentType, Length = httpContext.Request.ContentLength, Value = IncludeRequestBody ? GetRequestBody(actionContext) : null } }; var eventType = (EventTypeName ?? "{verb} {controller}/{action}").Replace("{verb}", auditAction.HttpMethod) .Replace("{controller}", auditAction.ControllerName) .Replace("{action}", auditAction.ActionName); // Create the audit scope var auditEventAction = new AuditEventWebApi() { Action = auditAction }; var auditScope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = eventType, AuditEvent = auditEventAction, CallingMethod = actionDescriptior.MethodInfo }); httpContext.Items[AuditApiActionKey] = auditAction; httpContext.Items[AuditApiScopeKey] = auditScope; }
public async Task Test_ScopeSaveMode_CreateAndSave_Async() { var modes = new List <SaveMode>(); Audit.Core.Configuration.Setup() .UseDynamicProvider(x => x .OnInsert(ev => { }) .OnReplace((id, ev) => { })) .WithCreationPolicy(EventCreationPolicy.Manual) .WithAction(a => a .OnEventSaving(scope => { modes.Add(scope.SaveMode); })); using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { IsCreateAndSave = true })) { await scope.SaveAsync(); } Assert.AreEqual(1, modes.Count); Assert.AreEqual(SaveMode.InsertOnStart, modes[0]); }
/// <inheritdoc /> public virtual async Task DeleteAsync(TEntity item, CancellationToken cancellationToken = default) { AuditScope auditScope = null; TKey id = item.Id; await DecoratedService.DeleteAsync(item, cancellationToken); try { auditScope = await AuditScope.CreateAsync($"{EntityName}:Delete", () => item); auditScope.Event.Environment.UserName = UserContext.CurrentUser; auditScope.Event.Target.Type = $"{EntityFullName}"; // Set the deleted item to null. This prevents Audit.NET from replicating the audit details of the // "Old" object into "New". // ReSharper disable once RedundantAssignment item = default; } catch (Exception e) { Logger.Warning(e, "Auditing failed for DeleteAsync of type {Entity} with ID {Id}.", EntityName, id); } finally { if (auditScope != null) { await auditScope.DisposeAsync(); } } }
public async Task TestAzureCosmos_CustomIdAsync() { var dp = new AzureCosmos.Providers.AzureCosmosDataProvider() { Endpoint = AzureSettings.AzureDocDbUrl, Database = "Audit", Container = "AuditTest", AuthKey = AzureSettings.AzureDocDbAuthKey }; var eventType = TestContext.CurrentContext.Test.Name + new Random().Next(1000, 9999); var id = Guid.NewGuid().ToString(); var auditEvent = new AuditEventWithId() { Id = id }; using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { DataProvider = dp, EventType = eventType, CreationPolicy = EventCreationPolicy.InsertOnStartReplaceOnEnd, AuditEvent = auditEvent })) { scope.SetCustomField("value", "added"); }; var ev = await dp.GetEventAsync(id); Assert.AreEqual(id, auditEvent.Id); Assert.AreEqual(auditEvent.CustomFields["value"], ev.CustomFields["value"]); Assert.AreEqual(eventType, auditEvent.EventType); }
public async Task Test_Elasticsearch_HappyPath_Async() { var ins = new List <Core.AuditEvent>(); var repl = new List <Core.AuditEvent>(); var ela = GetElasticsearchDataProvider(ins, repl); var guids = new List <string>(); ela.IndexBuilder = ev => "auditevent2"; ela.IdBuilder = ev => { var g = Guid.NewGuid().ToString().Replace("-", "/"); guids.Add(g); return(g); }; Audit.Core.Configuration.Setup() .UseCustomProvider(ela) .WithCreationPolicy(Core.EventCreationPolicy.InsertOnStartReplaceOnEnd) .ResetActions(); var sb = "init"; using (var scope = await AuditScope.CreateAsync("eventType", () => sb, new { MyCustomField = "value" })) { sb += "-end"; } Assert.AreEqual(1, guids.Count); Assert.AreEqual(1, ins.Count); Assert.AreEqual(1, repl.Count); Assert.AreEqual("\"init\"", ins[0].Target.SerializedOld); Assert.AreEqual(null, ins[0].Target.SerializedNew); Assert.AreEqual("\"init\"", repl[0].Target.SerializedOld); Assert.AreEqual("\"init-end\"", repl[0].Target.SerializedNew); }
public async Task Redis_PubSub_Basic_Async() { var key = Guid.NewGuid().ToString(); Core.Configuration.Setup() .UseRedis(redis => redis .ConnectionString(RedisCnnString) .AsPubSub(h => h .Channel("mychannel:audit"))) .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); var mx = GetMultiplexer(); var list = new List <AuditEvent>(); var subs = mx.GetSubscriber(); await subs.SubscribeAsync("mychannel:audit", (ch, x) => { list.Add(JsonConvert.DeserializeObject <AuditEvent>(x)); }); using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_PubSub_Basic_1" })) { await scope.DisposeAsync(); } using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_PubSub_Basic_2" })) { await scope.DisposeAsync(); } await Task.Delay(1000); Assert.AreEqual(2, list.Count); Assert.AreEqual("Redis_PubSub_Basic_1", list[0].EventType); Assert.AreEqual("Redis_PubSub_Basic_2", list[1].EventType); }
public async Task Test_UdpDataProvider_BasicTest_Async(string ip, int port, bool multicast) { stop = false; events.Clear(); var p = new Udp.Providers.UdpDataProvider(); p.RemoteAddress = IPAddress.Parse(ip); p.RemotePort = port; var cts = new CancellationTokenSource(); var re = new ManualResetEvent(false); 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, p)) { Task.Delay(100).Wait(); await scope.SaveAsync(); scope.Discard(); } await Task.Delay(2000); stop = true; cts.Cancel(); await Task.Delay(2000); Assert.AreEqual(2, events.Count); Assert.AreEqual("Test_UdpDataProvider_BasicTest", events[0].EventType); Assert.AreEqual("Test_UdpDataProvider_BasicTest", events[1].EventType); Assert.NotNull(events[0].CustomFields["UdpEventId"]); Assert.AreEqual(events[0].CustomFields["UdpEventId"], events[1].CustomFields["UdpEventId"]); }
static async Task Main(string[] args) { Console.WriteLine("Start"); var order = new Order(); using (var audit = AuditScope.Create("Order:Update", () => order, new { UserName = "******" })) { Console.WriteLine("Audit"); order.Status = EnumStatus.Finish; audit.Comment("commit"); } AuditScope auditScope = null; try { auditScope = await AuditScope.CreateAsync("Test:Identity", () => order, new { user = "******" }); { order.Status = EnumStatus.Start; } auditScope.Comment("01"); } finally { if (auditScope != null) { await auditScope.DisposeAsync(); } } Console.ReadKey(); }
/// <summary> /// Occurs before the action method is invoked. /// </summary> /// <param name="actionContext">The action context.</param> public async Task BeforeExecutingAsync(HttpActionContext actionContext, IContextWrapper contextWrapper, bool includeHeaders, bool includeRequestBody, bool serializeParams, string eventTypeName) { var request = actionContext.Request; var auditAction = new AuditApiAction { UserName = actionContext.RequestContext?.Principal?.Identity?.Name, IpAddress = contextWrapper.GetClientIp(), RequestUrl = request.RequestUri?.AbsoluteUri, HttpMethod = actionContext.Request.Method?.Method, FormVariables = contextWrapper.GetFormVariables(), Headers = includeHeaders ? ToDictionary(request.Headers) : null, ActionName = actionContext.ActionDescriptor?.ActionName, ControllerName = actionContext.ActionDescriptor?.ControllerDescriptor?.ControllerName, ActionParameters = GetActionParameters(actionContext.ActionArguments, serializeParams), RequestBody = includeRequestBody ? GetRequestBody(contextWrapper) : null }; var eventType = (eventTypeName ?? "{verb} {controller}/{action}").Replace("{verb}", auditAction.HttpMethod) .Replace("{controller}", auditAction.ControllerName) .Replace("{action}", auditAction.ActionName); // Create the audit scope var auditEventAction = new AuditEventWebApi() { Action = auditAction }; var options = new AuditScopeOptions() { EventType = eventType, AuditEvent = auditEventAction, CallingMethod = (actionContext.ActionDescriptor as ReflectedHttpActionDescriptor)?.MethodInfo }; var auditScope = await AuditScope.CreateAsync(options); contextWrapper.Set(AuditApiActionKey, auditAction); contextWrapper.Set(AuditApiScopeKey, auditScope); }
public async Task TestSave_Async() { var provider = new Mock <AuditDataProvider>(); provider.Setup(p => p.Serialize(It.IsAny <string>())).CallBase(); Core.Configuration.DataProvider = provider.Object; var target = "initial"; var eventType = "SomeEvent"; AuditEvent ev; using (var scope = await AuditScope.CreateAsync(eventType, () => target, EventCreationPolicy.InsertOnEnd)) { ev = scope.Event; scope.Comment("test"); scope.SetCustomField <string>("custom", "value"); target = "final"; await scope.SaveAsync(); // this should do nothing because of the creation policy (this no more true since v4.6.2) provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Once); } Assert.AreEqual(eventType, ev.EventType); Assert.True(ev.Comments.Contains("test")); provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Exactly(1)); provider.Verify(p => p.InsertEvent(It.IsAny <AuditEvent>()), Times.Exactly(1)); }
public async Task Redis_Hash_Basic_Async() { var key = Guid.NewGuid().ToString(); var ids = new List <object>(); Core.Configuration.ResetCustomActions(); Core.Configuration.Setup() .UseRedis(redis => redis .ConnectionString(RedisCnnString) .AsHash(h => h .Key(ev => key) .HashField(ev => ev.EventType))) .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd) .WithAction(_ => _.OnEventSaved(scope => { ids.Add(scope.EventId); })); using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_Hash_Basic_1" })) { await scope.DisposeAsync(); } using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_Hash_Basic_2" })) { await scope.DisposeAsync(); } using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_Hash_Basic_1", ExtraFields = new { test = "updated" } })) { await scope.DisposeAsync(); } var mx = GetMultiplexer(); var db = mx.GetDatabase(); var values = db.HashGetAll(key); var v1 = db.HashGet(key, "Redis_Hash_Basic_1"); var v2 = db.HashGet(key, "Redis_Hash_Basic_2"); var evFromApi = await Configuration.DataProvider.GetEventAsync(ids[0]); db.KeyDelete(key); Core.Configuration.ResetCustomActions(); Assert.AreEqual(6, ids.Count); Assert.AreEqual(2, values.Length); Assert.AreEqual("Redis_Hash_Basic_1", evFromApi.EventType); Assert.IsTrue(v1.HasValue); Assert.IsTrue(v2.HasValue); Assert.AreEqual("updated", JsonConvert.DeserializeObject <AuditEvent>(v1).CustomFields["test"]); }
public async Task Test_KafkaDataProvider_Stress() { var locker = new object(); var reports = new List <DeliveryResult <Null, AuditEvent> >(); string topic = "topic-" + Guid.NewGuid(); const string host = "localhost:9092"; var pConfig = new ProducerConfig() { BootstrapServers = host, ClientId = Dns.GetHostName() }; Audit.Core.Configuration.Setup() .UseKafka(_ => _ .ProducerConfig(pConfig) .Topic(topic) .ResultHandler(rpt => { lock (locker) { reports.Add(rpt); } })) .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); Action <int> insertAction = async(int index) => { var scope = await AuditScope.CreateAsync("type1", null, new { index = index }); await scope.DisposeAsync(); }; int count = 50; var tasks = new List <Task>(); for (int i = 0; i < count; i++) { tasks.Add(new Task(() => insertAction(i))); tasks[i].Start(); } await Task.WhenAll(tasks.ToArray()); var waiterTime = Task.Delay(10000); var waiterCount = new Task(() => { while (true) { lock (locker) if (reports.Count >= count) { break; } } ; }); await Task.WhenAny(new Task[] { waiterTime, waiterCount }); Assert.AreEqual(count, reports.Count); Assert.IsTrue(reports.All(r => r.Status == PersistenceStatus.Persisted)); }
public async Task Test_Dispose_Async() { var provider = new Mock <AuditDataProvider>(); await using (var scope = await AuditScope.CreateAsync(null, null, EventCreationPolicy.InsertOnEnd, dataProvider: provider.Object)) { } provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Exactly(1)); }
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); scope.Comment("test"); var ev = scope.Event; scope.Discard(); Assert.AreEqual("123", ev.CustomFields["DATA"].ToString()); Assert.AreEqual("class value", ev.CustomFields["class"].ToString()); }
public async Task Test_AuditScopeCreation_WithExistingAuditEvent_WithCustomFields_Async() { var evs_onScopeCreated = new List <AuditEvent>(); var evs_Provider = new List <AuditEvent>(); Audit.Core.Configuration.Setup() .AuditDisabled(false) .UseDynamicProvider(x => x .OnInsertAndReplace(ev => { evs_Provider.Add(AuditEvent.FromJson(ev.ToJson())); })) .WithCreationPolicy(EventCreationPolicy.InsertOnEnd) .WithAction(_ => _.OnScopeCreated(scope => { evs_onScopeCreated.Add(AuditEvent.FromJson(scope.Event.ToJson())); })); var auditEvent = new AuditEvent() { EventType = "test", CustomFields = new Dictionary <string, object>() { { "FromCustomField", 1 } } }; var options = new AuditScopeOptions() { AuditEvent = auditEvent, ExtraFields = new { FromAnon = 2 } }; using (var scope = await AuditScope.CreateAsync(options)) { scope.SetCustomField("FromScope", 3); } Assert.AreEqual(1, evs_onScopeCreated.Count); Assert.AreEqual(2, evs_onScopeCreated[0].CustomFields.Count); Assert.IsTrue(evs_onScopeCreated[0].CustomFields.ContainsKey("FromCustomField")); Assert.IsTrue(evs_onScopeCreated[0].CustomFields.ContainsKey("FromAnon")); Assert.AreEqual(1, evs_onScopeCreated[0].CustomFields["FromCustomField"]); Assert.AreEqual(2, evs_onScopeCreated[0].CustomFields["FromAnon"]); Assert.AreEqual(1, evs_Provider.Count); Assert.AreEqual(3, evs_Provider[0].CustomFields.Count); Assert.IsTrue(evs_Provider[0].CustomFields.ContainsKey("FromCustomField")); Assert.IsTrue(evs_Provider[0].CustomFields.ContainsKey("FromAnon")); Assert.IsTrue(evs_Provider[0].CustomFields.ContainsKey("FromScope")); Assert.AreEqual(1, evs_Provider[0].CustomFields["FromCustomField"]); Assert.AreEqual(2, evs_Provider[0].CustomFields["FromAnon"]); Assert.AreEqual(3, evs_Provider[0].CustomFields["FromScope"]); }
public async Task Test_KafkaDataProvider_HappyPath_Async() { var reports = new List <DeliveryResult <Null, AuditEvent> >(); const string topic = "my-audit-topic-happypath-async"; const string host = "localhost:9092"; var pConfig = new ProducerConfig() { BootstrapServers = host, ClientId = Dns.GetHostName() }; Audit.Core.Configuration.Setup() .UseKafka(_ => _ .ProducerConfig(pConfig) .Topic(topic) .ResultHandler(rpt => { reports.Add(rpt); })) .WithCreationPolicy(EventCreationPolicy.InsertOnStartInsertOnEnd); var guid = Guid.NewGuid(); var scope = await AuditScope.CreateAsync("type1", null, new { custom_field = guid }); scope.Event.CustomFields["custom_field"] = "UPDATED:" + guid; await scope.DisposeAsync(); Assert.AreEqual(2, reports.Count); Assert.AreEqual(PersistenceStatus.Persisted, reports[0].Status); Assert.AreEqual(PersistenceStatus.Persisted, reports[1].Status); var cv = new ConsumerBuilder <Null, AuditEvent>(new ConsumerConfig() { BootstrapServers = host, ClientId = Dns.GetHostName(), GroupId = "test-" + guid, AutoOffsetReset = AutoOffsetReset.Earliest, }).SetValueDeserializer(new DefaultJsonSerializer <AuditEvent>()).Build(); cv.Subscribe(topic); await Task.Delay(1000); cv.Seek(new TopicPartitionOffset(topic, reports[0].Partition, reports[0].Offset)); var r1 = cv.Consume(1000); cv.Seek(new TopicPartitionOffset(topic, reports[1].Partition, reports[1].Offset)); var r2 = cv.Consume(1000); Assert.IsNotNull(r1); Assert.IsNotNull(r2); Assert.AreEqual(guid.ToString(), r1.Message.Value.CustomFields["custom_field"]); Assert.AreEqual("UPDATED:" + guid, r2.Message.Value.CustomFields["custom_field"]); }
public async Task Redis_SortedSet_Basic_Async() { var key = Guid.NewGuid().ToString(); var ids = new List <object>(); Core.Configuration.ResetCustomActions(); Core.Configuration.Setup() .UseRedis(redis => redis .ConnectionString(RedisCnnString) .AsSortedSet(h => h .Key(ev => key) .Score(ev => (double)ev.CustomFields["Score"]))) .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd) .WithAction(_ => _.OnEventSaved(scope => { ids.Add(scope.EventId); })); using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_SortedSet_Basic_1", ExtraFields = new { Score = 12.34 } })) { await scope.DisposeAsync(); } using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_SortedSet_Basic_2", ExtraFields = new { Score = -56.78 } })) { await scope.DisposeAsync(); } var mx = GetMultiplexer(); var db = mx.GetDatabase(); var values = await db.SortedSetRangeByRankWithScoresAsync(key); var evFromApi = await Configuration.DataProvider.GetEventAsync(ids[0]); await db.KeyDeleteAsync(key); Core.Configuration.ResetCustomActions(); Assert.AreEqual(4, ids.Count); Assert.AreEqual(4, values.Length); Assert.AreEqual(-56.78, values[0].Score); Assert.AreEqual("Redis_SortedSet_Basic_1", evFromApi.EventType); Assert.AreEqual("Redis_SortedSet_Basic_2", JsonConvert.DeserializeObject <AuditEvent>(values[0].Element).EventType); Assert.AreEqual(12.34, values[3].Score); Assert.AreEqual("Redis_SortedSet_Basic_1", JsonConvert.DeserializeObject <AuditEvent>(values[3].Element).EventType); }
public async Task Redis_List_Basic_Async() { var key = Guid.NewGuid().ToString(); var ids = new List <object>(); Core.Configuration.ResetCustomActions(); Core.Configuration.Setup() .UseRedis(redis => redis .ConnectionString(RedisCnnString) .AsList(s => s .Key(ev => key))) .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd) .WithAction(_ => _.OnEventSaved(scope => { ids.Add(scope.EventId); })); using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_List_Basic_1" })) { await scope.DisposeAsync(); } using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_List_Basic_2" })) { await scope.DisposeAsync(); } var mx = GetMultiplexer(); var db = mx.GetDatabase(); var values = await db.ListRangeAsync(key); var aev1 = Newtonsoft.Json.JsonConvert.DeserializeObject <AuditEvent>(values[0]); var aev2 = Newtonsoft.Json.JsonConvert.DeserializeObject <AuditEvent>(values[3]); var evFromApi = await Configuration.DataProvider.GetEventAsync(ids[0]); await db.KeyDeleteAsync(key); Core.Configuration.ResetCustomActions(); Assert.AreEqual(4, ids.Count); Assert.AreEqual(4, values.Length); Assert.AreEqual(evFromApi.EventType, aev2.EventType); Assert.AreEqual(evFromApi.StartDate, aev2.StartDate); Assert.AreEqual("Redis_List_Basic_2", aev1.EventType); Assert.AreEqual("Redis_List_Basic_1", aev2.EventType); }
public async Task Test_EventCreationPolicy_InsertOnStartReplaceOnEnd_Async() { var provider = new Mock <AuditDataProvider>(); provider.Setup(p => p.InsertEventAsync(It.IsAny <AuditEvent>())).Returns(() => Task.FromResult((object)Guid.NewGuid())); Core.Configuration.DataProvider = provider.Object; using (var scope = await AuditScope.CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnStartReplaceOnEnd)) { scope.Comment("test"); await scope.DisposeAsync(); } provider.Verify(p => p.ReplaceEventAsync(It.IsAny <object>(), It.IsAny <AuditEvent>()), Times.Once); provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Once); }
public async Task Redis_String_Basic_Async() { var key = Guid.NewGuid().ToString(); var ids = new List <object>(); Core.Configuration.Setup() .UseRedis(redis => redis .ConnectionString(RedisCnnString) .AsString(s => s .Key(ev => key))) .WithCreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd) .WithAction(_ => _.OnEventSaved(scope => { ids.Add(scope.EventId); })); using (var scope = await AuditScope.CreateAsync(new AuditScopeOptions() { EventType = "Redis_String_Basic_Async" })) { scope.SetCustomField("custom", new List <int>() { 1, 2, 3, 4, 5 }); await scope.DisposeAsync(); } var mx = GetMultiplexer(); var db = mx.GetDatabase(); var value = await db.StringGetAsync(key); var evFromApi = await Configuration.DataProvider.GetEventAsync(key); var aev = Newtonsoft.Json.JsonConvert.DeserializeObject <AuditEvent>(value); await db.KeyDeleteAsync(key); Configuration.ResetCustomActions(); Assert.AreEqual(2, ids.Count); Assert.AreEqual(ids[0], ids[1]); Assert.AreEqual(evFromApi.EventType, aev.EventType); Assert.AreEqual(evFromApi.StartDate, aev.StartDate); Assert.AreEqual(evFromApi.EndDate, aev.EndDate); Assert.AreEqual("Redis_String_Basic_Async", aev.EventType); Assert.AreEqual(new List <int>() { 1, 2, 3, 4, 5 }, (aev.CustomFields["custom"] as JToken).ToObject <List <int> >()); }
/// <inheritdoc /> public virtual async Task <IEnumerable <TEntity> > RetrieveAsync( Expression <Func <TEntity, bool> > filter = null, PagingContext pagingContext = null, Func <IQueryable <TEntity>, IOrderedQueryable <TEntity> > sortCondition = null, CancellationToken cancellationToken = default, params Expression <Func <TEntity, object> >[] includes) { IEnumerable <TEntity> entities = await DecoratedService.RetrieveAsync( filter, pagingContext, sortCondition, cancellationToken, includes); IEnumerable <TEntity> retrieved = entities.ToList(); AuditScope auditScope = null; try { // Due to size constraints, only audit the number of objects retrieved rather than the objects // themselves. var options = new AuditScopeOptions { EventType = $"{EntityName}:Retrieve+", ExtraFields = new { Count = retrieved.Count() }, AuditEvent = new AuditEvent { Target = new AuditTarget() } }; auditScope = await AuditScope.CreateAsync(options); auditScope.Event.Environment.UserName = UserContext.CurrentUser; auditScope.Event.Target.Type = $"{EntityFullName}"; } catch (Exception e) { Logger.Warning(e, "Auditing failed for RetrieveAsync+ of type {Entity}.", EntityName); } finally { if (auditScope != null) { await auditScope.DisposeAsync(); } } return(retrieved); }
public async Task Test_EventCreationPolicy_InsertOnEnd_Async() { var provider = new Mock <AuditDataProvider>(); Core.Configuration.DataProvider = provider.Object; using (var scope = await AuditScope.CreateAsync("SomeEvent", () => "target", EventCreationPolicy.InsertOnEnd)) { 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) } provider.Verify(p => p.ReplaceEvent(It.IsAny <object>(), It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.ReplaceEventAsync(It.IsAny <object>(), It.IsAny <AuditEvent>()), Times.Never); provider.Verify(p => p.InsertEventAsync(It.IsAny <AuditEvent>()), Times.Exactly(1)); provider.Verify(p => p.InsertEvent(It.IsAny <AuditEvent>()), Times.Exactly(1)); }
public async Task Test_AsyncDynamicDataProvider_FluentApi_Async() { int ins = 0; int upd = 0; var dyn = new DynamicAsyncDataProvider(_ => _ .OnInsert(async ev => { ins++; await Task.Delay(0); }) .OnReplace(async(id, ev) => { upd++; await Task.Delay(0); })); using (var scope = await AuditScope.CreateAsync(_ => _ .CreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd) .DataProvider(dyn)).ConfigureAwait(false)) { } Assert.AreEqual(1, ins); Assert.AreEqual(1, upd); }
public async Task Test_AuditScope_CallingMethod_Async() { Audit.Core.Configuration.SystemClock = new MyClock(); var evs = new List <AuditEvent>(); 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); }
/// <inheritdoc /> public virtual async Task <TEntity> RetrieveAsync( TKey id, CancellationToken cancellationToken = default, params Expression <Func <TEntity, object> >[] includes) { TEntity retrieved = default; AuditScope auditScope = null; var isServiceException = false; try { auditScope = await AuditScope.CreateAsync($"{EntityName}:Retrieve", () => retrieved); auditScope.Event.Environment.UserName = UserContext.CurrentUser; auditScope.Event.Target.Type = $"{EntityFullName}"; try { retrieved = await DecoratedService.RetrieveAsync(id, cancellationToken, includes); } catch { isServiceException = true; auditScope.Discard(); throw; } } catch (Exception e) { if (isServiceException) { throw; } Logger.Warning(e, "Auditing failed for RetrieveAsync of type {Entity} with ID {Id}.", EntityName, id); } finally { if (auditScope != null) { await auditScope.DisposeAsync(); } } return(retrieved); }
/// <inheritdoc /> public virtual async Task UpdateAsync(TEntity item, CancellationToken cancellationToken = default) { AuditScope auditScope = null; var isServiceException = false; TKey id = item.Id; TEntity original = await ReadOnlyRepository.RetrieveAsync(id, cancellationToken); try { auditScope = await AuditScope.CreateAsync($"{EntityName}:Update", () => original); auditScope.Event.Environment.UserName = UserContext.CurrentUser; auditScope.Event.Target.Type = $"{EntityFullName}"; try { await DecoratedService.UpdateAsync(item, cancellationToken); } catch { isServiceException = true; auditScope.Discard(); throw; } // Assign the updated item back to the original. This allows Audit.NET to determine what was changed. // ReSharper disable once RedundantAssignment original = item; } catch (Exception e) { if (isServiceException) { throw; } Logger.Warning(e, "Auditing failed for UpdateAsync of type {Entity} with ID {Id}.", EntityName, id); } finally { if (auditScope != null) { await auditScope.DisposeAsync(); } } }