예제 #1
0
        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);
        }
예제 #2
0
        /// <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;
        }
예제 #3
0
        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);
        }
예제 #4
0
        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;
        }
예제 #6
0
        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();
                }
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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"]);
        }
예제 #12
0
        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();
        }
예제 #13
0
        /// <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);
        }
예제 #14
0
        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));
        }
예제 #15
0
        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"]);
        }
예제 #16
0
        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));
        }
예제 #17
0
        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));
        }
예제 #18
0
        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());
        }
예제 #19
0
        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"]);
        }
예제 #20
0
        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"]);
        }
예제 #21
0
        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);
        }
예제 #22
0
        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);
        }
예제 #23
0
        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);
        }
예제 #24
0
        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);
        }
예제 #26
0
        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));
        }
예제 #27
0
        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);
        }
예제 #28
0
        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();
                }
            }
        }