Ejemplo n.º 1
0
        public void Log(AuditObjectData auditObject)
        {
            AuditSubjectData auditSubjectData = _auditDataService.Get();

            AuditEntity audit = new AuditEntity(
                auditObjectData: auditObject,
                auditSubjectData: auditSubjectData);

            _dbContext.Audit.Add(audit);

            int changes = _dbContext.SaveChanges();

            if (changes <= 0)
            {
                _logger.LogError($"Failed to add audit data");
            }
        }
Ejemplo n.º 2
0
        public async Task LogAsync(AuditObjectData auditObject)
        {
            AuditSubjectData auditSubjectData = _auditDataService.Get();

            AuditEntity audit = new AuditEntity(
                auditObjectData: auditObject,
                auditSubjectData: auditSubjectData);

            _dbContext.Audit.Add(audit);

            int changes = await _dbContext.SaveChangesAsync();

            if (changes <= 0)
            {
                _logger.LogError($"Failed to add audit");
            }
        }
        public static async Task <ProccessChangeTrackerResult> ProccessChangeTrackerAsync(ChangeTracker changeTracker, AuditOptions auditOptions = null, CancellationToken cancellationToken = default)
        {
            if (auditOptions == null)
            {
                auditOptions = new AuditOptions();
            }

            List <AuditObjectData> dbAuditDataList = new List <AuditObjectData>();
            bool requiresCustomBatch = false;

            foreach (EntityEntry entry in changeTracker.Entries())
            {
                if (entry.Entity.GetType().GetCustomAttributes(typeof(AuditIgnoreAttribute), true).Any())
                {
                    continue;
                }

                switch (entry.State)
                {
                case Microsoft.EntityFrameworkCore.EntityState.Added:
                {
                    AuditObjectData auditData;

                    if (entry.IsKeySet)
                    {
                        auditData = new AuditObjectData(
                            actionType: ActionTypes.Add,
                            objectType: entry.Entity.GetType().Name,
                            objectIdentifier: entry.GetPrimaryKey(),
                            objectMetadata: entry.GetMetadata());
                    }
                    else
                    {
                        PropertyEntry objectIdentifierProperty = entry.Metadata.FindPrimaryKey().Properties
                                                                 .Select(x => entry.Property(x.Name))
                                                                 .FirstOrDefault();

                        auditData = new AuditObjectData(
                            actionType: ActionTypes.Add,
                            objectType: entry.Entity.GetType().Name,
                            objectIdentifierProperty: objectIdentifierProperty,
                            objectMetadata: entry.GetMetadata());

                        requiresCustomBatch = true;
                    }

                    dbAuditDataList.Add(auditData);

                    break;
                }

                case Microsoft.EntityFrameworkCore.EntityState.Modified:
                {
                    AuditObjectData auditData = new AuditObjectData(
                        actionType: ActionTypes.Update,
                        objectType: entry.Entity.GetType().Name,
                        objectIdentifier: entry.GetPrimaryKey(),
                        objectMetadata: entry.GetMetadata(onlyModified: true));

                    dbAuditDataList.Add(auditData);

                    break;
                }

                case Microsoft.EntityFrameworkCore.EntityState.Deleted:
                {
                    if (auditOptions.AuditCascadeDelete)
                    {
                        IEnumerable <AuditObjectData> cascadeDeleteAuditData = await CascadeDelete(entry, changeTracker, cancellationToken);

                        dbAuditDataList.AddRange(cascadeDeleteAuditData);
                    }

                    AuditObjectData auditData = new AuditObjectData(
                        actionType: ActionTypes.Delete,
                        objectType: entry.Entity.GetType().Name,
                        objectIdentifier: entry.GetPrimaryKey(),
                        objectMetadata: entry.GetMetadata());

                    dbAuditDataList.Add(auditData);

                    break;
                }
                }
            }

            return(new ProccessChangeTrackerResult(
                       requiresCustomBatch: requiresCustomBatch,
                       auditObjectData: dbAuditDataList));
        }
        private static async Task <IEnumerable <AuditObjectData> > CascadeDelete(EntityEntry entityEntry, ChangeTracker changeTracker, CancellationToken cancellationToken)
        {
            if (entityEntry.Entity.GetType().GetCustomAttributes(typeof(AuditIgnoreCascadeAttribute), true).Any())
            {
                return(new List <AuditObjectData>());
            }

            List <AuditObjectData> auditObjects = new List <AuditObjectData>();

            foreach (NavigationEntry navigation in entityEntry.Navigations)
            {
                if (navigation.Metadata.ForeignKey.PrincipalEntityType.ClrType == entityEntry.Entity.GetType() &&
                    navigation.Metadata.ForeignKey.DeleteBehavior == Microsoft.EntityFrameworkCore.DeleteBehavior.Cascade)
                {
                    if (navigation.Metadata.PropertyInfo.GetCustomAttributes(typeof(AuditIgnoreCascadeAttribute)).Any())
                    {
                        continue;
                    }

                    if (!navigation.IsLoaded)
                    {
                        await navigation.LoadAsync();
                    }

                    Type type;
                    if (navigation.Metadata.ClrType.IsGenericType)
                    {
                        if (navigation.Metadata.ClrType.GetGenericArguments().Length != 1)
                        {
                            //TODO: log unsupported
                            Trace.TraceInformation($"Unsupported navigation type for cascade delete. {navigation.Metadata.Name}");
                            continue;
                        }

                        type = navigation.Metadata.ClrType.GetGenericArguments()[0];
                    }
                    else
                    {
                        type = navigation.Metadata.ClrType;
                    }

                    IEnumerable <EntityEntry> navigationEntries = changeTracker.Entries()
                                                                  .Where(x => x.Entity.GetType() == type);

                    foreach (EntityEntry navigationEntry in navigationEntries)
                    {
                        IEnumerable <AuditObjectData> childrenAuditObjects = await CascadeDelete(navigationEntry, changeTracker, cancellationToken);

                        auditObjects.AddRange(childrenAuditObjects);

                        AuditObjectData auditObjectData = new AuditObjectData(
                            actionType: ActionTypes.Delete,
                            objectType: type.Name,
                            objectIdentifier: navigationEntry.GetPrimaryKey(),
                            objectMetadata: navigationEntry.GetMetadata());

                        auditObjects.Add(auditObjectData);
                    }
                }
            }

            return(auditObjects);
        }
Ejemplo n.º 5
0
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (context.HttpContext.Items.TryGetValue(AUDIT_PROCCESSINT_KEY, out object auditProccessing))
            {
                await next();

                return;
            }

            context.HttpContext.Items.Add(AUDIT_PROCCESSINT_KEY, null);

            ActionExecutedContext resultContext = await next();

            ControllerActionDescriptor actionDescriptor = ((ControllerActionDescriptor)context.ActionDescriptor);

            if (actionDescriptor.MethodInfo.GetCustomAttributes(true).Any(x => x.GetType() == typeof(AuditIgnoreAttribute)))
            {
                return;
            }

            if (!actionDescriptor.MethodInfo.CustomAttributes.Any(x => x.AttributeType == typeof(AuditAttribute)) &&
                actionDescriptor.ControllerTypeInfo.GetCustomAttributes(true).Any(x => x.GetType() == typeof(AuditIgnoreAttribute)))
            {
                return;
            }

            IAuditLogger auditLogger  = context.HttpContext.RequestServices.GetRequiredService <IAuditLogger>();
            AuditOptions auditOptions = context.HttpContext.RequestServices.GetRequiredService <IOptions <AuditOptions> >().Value;

            KeyValuePair <string, object> objectIdentifierResult;

            AuditObjectIdentifierKey objectIdentitiferKey = actionDescriptor.MethodInfo.GetCustomAttribute <AuditObjectIdentifierKey>();

            if (objectIdentitiferKey != null)
            {
                objectIdentifierResult = resultContext.RouteData.Values
                                         .Where(x => x.Key == objectIdentitiferKey.ObjectKey)
                                         .SingleOrDefault();
            }
            else
            {
                objectIdentifierResult = resultContext.RouteData.Values
                                         .Where(x => x.Key != "area")
                                         .Where(x => x.Key != "controller")
                                         .Where(x => x.Key != "action")
                                         .LastOrDefault();
            }

            string objectIdentifier = null;

            if (objectIdentifierResult.Value != null)
            {
                objectIdentifier = objectIdentifierResult.Value.ToString();
            }

            switch (resultContext.Result)
            {
            case OkObjectResult _:
            {
                OkObjectResult okObjectResult = (OkObjectResult)resultContext.Result;

                AuditObjectData auditObject = new AuditObjectData(
                    actionType: ActionTypes.Get,
                    objectType: okObjectResult.Value.GetType().GetNameWithGeneric(),
                    objectIdentifier: objectIdentifier,
                    objectMetadata: JsonConvert.SerializeObject(okObjectResult.Value));

                await auditLogger.LogAsync(auditObject);

                break;
            }

            case ViewResult _:
            {
                ViewResult viewResult = (ViewResult)resultContext.Result;

                List <AuditObjectData> auditObjects = new List <AuditObjectData>();

                if (viewResult.Model != null)
                {
                    AuditObjectData auditObject = new AuditObjectData(
                        actionType: ActionTypes.Get,
                        objectType: viewResult.GetType().Name,
                        objectIdentifier: objectIdentifier,
                        objectMetadata: JsonConvert.SerializeObject(viewResult.Model));

                    auditObjects.Add(auditObject);
                }

                if (auditOptions.AuditViewData && viewResult.ViewData.Any())
                {
                    AuditObjectData auditObject = new AuditObjectData(
                        actionType: ActionTypes.Get,
                        objectType: viewResult.ViewData.GetType().Name,
                        objectIdentifier: objectIdentifier,
                        objectMetadata: JsonConvert.SerializeObject(viewResult.ViewData));

                    auditObjects.Add(auditObject);
                }

                await auditLogger.LogAsync(auditObjects);

                break;
            }

            case BadRequestObjectResult _:
            {
                if (!auditOptions.AuditBadRequest)
                {
                    break;
                }

                BadRequestObjectResult badRequestObjectResult = (BadRequestObjectResult)resultContext.Result;

                AuditObjectData auditObject = new AuditObjectData(
                    actionType: ActionTypes.BadRequest,
                    objectType: badRequestObjectResult.Value.GetType().Name,
                    objectIdentifier: objectIdentifier,
                    objectMetadata: JsonConvert.SerializeObject(badRequestObjectResult.Value));

                await auditLogger.LogAsync(auditObject);

                break;
            }

            case FileContentResult _:
            {
                FileContentResult fileContentResult = (FileContentResult)resultContext.Result;

                AuditObjectData auditObjectData = new AuditObjectData(
                    actionType: ActionTypes.Get,
                    objectType: resultContext.Result.GetType().Name,
                    objectIdentifier: objectIdentifier,
                    objectMetadata: JsonConvert.SerializeObject(new { fileContentResult.ContentType, fileContentResult.FileDownloadName }));

                await auditLogger.LogAsync(auditObjectData);

                break;
            }

            case RedirectResult _:
            case RedirectToActionResult _:
            case RedirectToPageResult _:
            case RedirectToRouteResult _:
            case LocalRedirectResult _:
            {
                break;
            }

            default:
            {
                if (resultContext.Result != null)
                {
                    AuditObjectData auditObject = new AuditObjectData(
                        actionType: ActionTypes.Get,
                        objectType: resultContext.Result.GetType().Name,
                        objectIdentifier: objectIdentifier,
                        objectMetadata: null);

                    await auditLogger.LogAsync(auditObject);
                }

                break;
            }
            }
        }