/// <summary> /// Occurs before the action method is invoked. /// </summary> /// <param name="actionContext">The action context.</param> public override void OnActionExecuting(HttpActionContext actionContext) { var request = actionContext.Request; var contextWrapper = new ContextWrapper(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 = actionContext.ActionArguments }; 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 = AuditScope.Create(options); contextWrapper.Set(AuditApiActionKey, auditAction); contextWrapper.Set(AuditApiScopeKey, auditScope); }
/// <summary> /// Creates the Audit scope asynchronously. /// </summary> public async Task <IAuditScope> CreateAuditScopeAsync(IAuditDbContext context, EntityFrameworkEvent efEvent) { var typeName = context.GetType().Name; var eventType = context.AuditEventType?.Replace("{context}", typeName).Replace("{database}", efEvent.Database) ?? typeName; var auditEfEvent = new AuditEventEntityFramework { EntityFrameworkEvent = efEvent }; if (context.ExtraFields != null && context.ExtraFields.Count > 0) { auditEfEvent.CustomFields = new Dictionary <string, object>(context.ExtraFields); } 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); context.OnScopeCreated(scope); return(scope); }
/// <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); }
/// <summary> /// Creates the Audit scope asynchronously. /// </summary> public async Task <IAuditScope> CreateAuditScopeAsync(IAuditDbContext context, EntityFrameworkEvent efEvent) { var typeName = context.GetType().Name; var eventType = context.AuditEventType?.Replace("{context}", typeName).Replace("{database}", efEvent.Database) ?? typeName; var auditEfEvent = new AuditEventEntityFramework { EntityFrameworkEvent = efEvent }; 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) { scope.SetCustomField(field.Key, field.Value); } } context.OnScopeCreated(scope); return(scope); }
/// <inheritdoc /> public virtual bool Exists(TKey id) { bool exists = DecoratedService.Exists(id); try { var options = new AuditScopeOptions { EventType = $"{EntityName}:Exists", ExtraFields = new { Id = id, Exists = exists }, AuditEvent = new AuditEvent { Target = new AuditTarget() } }; using (var auditScope = AuditScope.Create(options)) { auditScope.Event.Environment.UserName = UserContext.CurrentUser; auditScope.Event.Target.Type = $"{EntityFullName}"; } } catch (Exception e) { Logger.Warning(e, "Auditing failed for Exists of type {Entity} with ID {Id}.", EntityName, id); } return(exists); }
/// <inheritdoc /> public virtual int Count(Expression <Func <TEntity, bool> > filter = null) { int count = DecoratedService.Count(filter); try { var options = new AuditScopeOptions { EventType = $"{EntityName}:Count", ExtraFields = new { Count = count }, AuditEvent = new AuditEvent { Target = new AuditTarget() } }; using (var auditScope = AuditScope.Create(options)) { auditScope.Event.Environment.UserName = UserContext.CurrentUser; auditScope.Event.Target.Type = $"{EntityFullName}"; } } catch (Exception e) { Logger.Warning(e, "Auditing failed for Count of type {Entity}.", EntityName); } return(count); }
/// <inheritdoc /> public virtual IEnumerable <TEntity> Retrieve( Expression <Func <TEntity, bool> > filter = null, PagingContext pagingContext = null, Func <IQueryable <TEntity>, IOrderedQueryable <TEntity> > sortCondition = null, params Expression <Func <TEntity, object> >[] includes) { IEnumerable <TEntity> retrieved = DecoratedService.Retrieve(filter, pagingContext, sortCondition, includes).ToList(); 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() } }; using (var auditScope = AuditScope.Create(options)) { auditScope.Event.Environment.UserName = UserContext.CurrentUser; auditScope.Event.Target.Type = $"{EntityFullName}"; } } catch (Exception e) { Logger.Warning(e, "Auditing failed for Retrieve+ of type {Entity}.", EntityName); } return(retrieved); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { var request = filterContext.HttpContext.Request; var auditAction = new AuditAction() { UserName = (request.IsAuthenticated) ? filterContext.HttpContext.User?.Identity.Name : "Anonymous", IpAddress = request.ServerVariables?["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress, RequestUrl = request.RawUrl, HttpMethod = request.HttpMethod, FormVariables = ToDictionary(request.Form), Headers = IncludeHeaders ? ToDictionary(request.Headers) : null, ActionName = filterContext.ActionDescriptor?.ActionName, ControllerName = filterContext.ActionDescriptor?.ControllerDescriptor?.ControllerName, ActionParameters = filterContext.ActionParameters?.ToDictionary(k => k.Key, v => v.Value) }; 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 AuditEventMvcAction() { Action = auditAction }; var options = new AuditScopeOptions() { EventType = eventType, AuditEvent = auditEventAction, CallingMethod = (filterContext.ActionDescriptor as ReflectedActionDescriptor)?.MethodInfo }; var auditScope = AuditScope.Create(options); filterContext.HttpContext.Items[AuditActionKey] = auditAction; filterContext.HttpContext.Items[AuditScopeKey] = auditScope; base.OnActionExecuting(filterContext); }
public void Test_AuditScopeCreation_WithExistingAuditEvent_WithCustomFields() { 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 = AuditScope.Create(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"]); }
/// <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); }
private async Task <IAuditScope> CreateAuditScopeAsync(AuditEventCommandEntityFramework cmdEvent) { var eventType = AuditEventType? .Replace("{database}", cmdEvent.CommandEvent.Database) .Replace("{method}", cmdEvent.CommandEvent.Method.ToString()); var factory = Core.Configuration.AuditScopeFactory; var options = new AuditScopeOptions() { EventType = eventType, AuditEvent = cmdEvent, SkipExtraFrames = 3 }; return(await factory.CreateAsync(options)); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { if (Configuration.AuditDisabled || IsActionIgnored(filterContext.ActionDescriptor)) { base.OnActionExecuting(filterContext); return; } var request = filterContext.HttpContext.Request; var auditAction = new AuditAction() { UserName = (request.IsAuthenticated) ? filterContext.HttpContext.User?.Identity.Name : "Anonymous", IpAddress = request.ServerVariables?["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress, #if NET45 RequestUrl = request.Unvalidated.RawUrl, FormVariables = ToDictionary(request.Unvalidated.Form), Headers = IncludeHeaders ? ToDictionary(request.Unvalidated.Headers) : null, #else RequestUrl = request.RawUrl, FormVariables = ToDictionary(request.Form), Headers = IncludeHeaders ? ToDictionary(request.Headers) : null, #endif RequestBody = IncludeRequestBody ? GetRequestBody(filterContext.HttpContext) : null, HttpMethod = request.HttpMethod, ActionName = filterContext.ActionDescriptor?.ActionName, ControllerName = filterContext.ActionDescriptor?.ControllerDescriptor?.ControllerName, ActionParameters = GetActionParameters(filterContext), TraceId = 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 AuditEventMvcAction() { Action = auditAction }; var options = new AuditScopeOptions() { EventType = eventType, AuditEvent = auditEventAction, CallingMethod = (filterContext.ActionDescriptor as ReflectedActionDescriptor)?.MethodInfo }; var auditScope = AuditScope.Create(options); filterContext.HttpContext.Items[AuditActionKey] = auditAction; filterContext.HttpContext.Items[AuditScopeKey] = auditScope; base.OnActionExecuting(filterContext); }
/// <inheritdoc /> public virtual async Task <int> CountAsync( Expression <Func <TEntity, bool> > filter = null, CancellationToken cancellationToken = default) { int count = await DecoratedService.CountAsync(filter, cancellationToken); AuditScope auditScope = null; try { var options = new AuditScopeOptions { EventType = $"{EntityName}:Count", ExtraFields = new { Count = 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 CountAsync of type {Entity}.", EntityName); } finally { if (auditScope != null) { await auditScope.DisposeAsync(); } } return(count); }
public void Test_DataProviderFactory() { GetProviderCount = 0; var options = new AuditScopeOptions(_ => _.DataProvider(GetProvider).CreationPolicy(EventCreationPolicy.InsertOnStartReplaceOnEnd)); Assert.AreEqual(0, GetProviderCount); using (var scope = AuditScope.Create(options)) { Assert.AreEqual(1, GetProviderCount); scope.SetCustomField("custom", "value"); scope.Save(); } Assert.AreEqual(1, GetProviderCount); options = new AuditScopeOptions(_ => _.DataProvider(GetProvider).CreationPolicy(EventCreationPolicy.Manual)); using (var scope = new AuditScope(options)) { Assert.AreEqual(2, GetProviderCount); scope.Save(); scope.Save(); } Assert.AreEqual(2, GetProviderCount); Audit.Core.Configuration.DataProviderFactory = GetProvider; using (var scope = AuditScope.Create("Test", null, new { custom = "value" })) { Assert.AreEqual(3, GetProviderCount); scope.Discard(); } Assert.AreEqual(3, GetProviderCount); Audit.Core.Configuration.Setup().UseFactory(GetProvider); using (var scope = AuditScope.Create("Test", null, new { custom = "value" })) { Assert.AreEqual(4, GetProviderCount); scope.Save(); } Assert.AreEqual(4, GetProviderCount); }
/// <inheritdoc /> public virtual async Task <bool> ExistsAsync(TKey id, CancellationToken cancellationToken = default) { bool exists = await DecoratedService.ExistsAsync(id, cancellationToken); AuditScope auditScope = null; try { var options = new AuditScopeOptions { EventType = $"{EntityName}:Exists", ExtraFields = new { Id = id, Exists = exists }, 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 ExistsAsync of type {Entity} with ID {Id}.", EntityName, id); } finally { if (auditScope != null) { await auditScope.DisposeAsync(); } } return(exists); }
public void Test_AuditScopeCreation_WithExistingAuditEvent_WithEventType() { var evs = new List <AuditEvent>(); Audit.Core.Configuration.Setup() .AuditDisabled(false) .UseDynamicProvider(x => x .OnInsertAndReplace(ev => { evs.Add(AuditEvent.FromJson(ev.ToJson())); })) .WithCreationPolicy(EventCreationPolicy.InsertOnEnd); var auditEvent = new AuditEvent() { EventType = "test" }; var options = new AuditScopeOptions() { EventType = null, // NULL means do not override eventtype AuditEvent = auditEvent }; // scope with pre-assigned event type using (var scope = AuditScope.Create(options)) { } // scope with event type to override options.EventType = "override"; using (var scope = AuditScope.Create(options)) { } Assert.AreEqual(2, evs.Count); Assert.AreEqual("test", evs[0].EventType); Assert.AreEqual("override", evs[1].EventType); }
/// <summary> /// Intercepts the specified invocation. /// </summary> public void Intercept(IInvocation invocation) { var intEvent = CreateAuditInterceptEvent(invocation); if (intEvent == null) { // bypass invocation.Proceed(); return; } var method = invocation.MethodInvocationTarget; var eventTypeAttribute = method.GetCustomAttribute(typeof(EventTypeAttribute), false); var eventType = eventTypeAttribute != null ? ((EventTypeAttribute)eventTypeAttribute).EventType : Settings.EventType?.Replace("{class}", intEvent.ClassName).Replace("{method}", intEvent.MethodName); var isAsync = method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null; intEvent.IsAsync = isAsync; var auditEventIntercept = new AuditEventIntercept() { InterceptEvent = intEvent }; var scopeOptions = new AuditScopeOptions() { EventType = eventType, CreationPolicy = Settings.EventCreationPolicy, DataProvider = Settings.AuditDataProvider, AuditEvent = auditEventIntercept }; var scope = AuditScope.Create(scopeOptions); AuditProxy.CurrentScope = scope; // Call the intercepted method (sync part) try { invocation.Proceed(); } catch (Exception ex) { intEvent.Exception = ex.GetExceptionInfo(); scope.Dispose(); throw; } // Handle async calls var returnType = method.ReturnType; if (isAsync) { if (typeof(Task).IsAssignableFrom(returnType)) { invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation, intEvent, scope); return; } } // Is a Sync method (or an Async method that does not returns a Task or Task<>). // Avoid Task and Task<T> serialization (i.e. when a sync method returns a Task) object returnValue = typeof(Task).IsAssignableFrom(returnType) ? null : invocation.ReturnValue; SuccessAuditInterceptEvent(invocation, intEvent, returnValue); if (!isAsync) { AuditProxy.CurrentScope = null; } scope.Dispose(); }