/// <summary>
        /// Creates an audit log entry for a <see cref="DbEntityEntry"/> that has an <see cref="EntityState"/> of <see cref="EntityState.Added"/> or <see cref="EntityState.Modified"/>
        /// It will create an audit log entry for each property that has changed
        /// </summary>
        private static AuditLog CreateAuditLogEntryForAddedOrModified(ObjectContext objectContext,
                                                                      DbEntityEntry dbEntry,
                                                                      string tableName,
                                                                      Person person,
                                                                      DateTime changeDate,
                                                                      AuditLogEventType auditLogEventType,
                                                                      DbPropertyEntry modifiedProperty)
        {
            var propertyName = modifiedProperty.Name;

            if (!string.Equals(propertyName, $"{tableName}ID", StringComparison.InvariantCultureIgnoreCase) && !string.Equals(propertyName, "TenantID", StringComparison.InvariantCultureIgnoreCase))
            {
                var optionalAuditDescriptionString = GetAuditDescriptionStringIfAnyForProperty(objectContext, dbEntry, propertyName, auditLogEventType);
                var auditLogEntry = CreateAuditLogEntryImpl(dbEntry,
                                                            tableName,
                                                            person,
                                                            changeDate,
                                                            auditLogEventType,
                                                            propertyName,
                                                            modifiedProperty.CurrentValue,
                                                            modifiedProperty.OriginalValue,
                                                            optionalAuditDescriptionString,
                                                            objectContext);
                return(auditLogEntry);
            }
            return(null);
        }
Beispiel #2
0
 /// <summary>
 /// Enum types are equal by primary key
 /// </summary>
 public bool Equals(AuditLogEventType other)
 {
     if (other == null)
     {
         return(false);
     }
     return(other.AuditLogEventTypeID == AuditLogEventTypeID);
 }
 /// <summary>
 /// Constructor for building a new object with MinimalConstructor required fields, using objects whenever possible
 /// </summary>
 public AuditLog(Person person, DateTime auditLogDate, AuditLogEventType auditLogEventType, string tableName, int recordID, string columnName, string newValue) : this()
 {
     // Mark this as a new object by setting primary key with special value
     this.AuditLogID = ModelObjectHelpers.MakeNextUnsavedPrimaryKeyValue();
     this.PersonID   = person.PersonID;
     this.Person     = person;
     person.AuditLogs.Add(this);
     this.AuditLogDate        = auditLogDate;
     this.AuditLogEventTypeID = auditLogEventType.AuditLogEventTypeID;
     this.TableName           = tableName;
     this.RecordID            = recordID;
     this.ColumnName          = columnName;
     this.NewValue            = newValue;
 }
        /// <summary>
        /// Creates an audit log entry for a <see cref="DbEntityEntry"/> that has an <see cref="EntityState"/> of <see cref="EntityState.Deleted"/>
        /// Deleted log entries do not have columns/property names, so there will just be one record created
        /// </summary>
        private static AuditLog CreateAuditLogEntryForDeleted(ObjectContext objectContext,
                                                              DbEntityEntry dbEntry,
                                                              string tableName,
                                                              Person person,
                                                              DateTime changeDate,
                                                              AuditLogEventType auditLogEventType)
        {
            var auditableEntityDeleted         = GetIAuditableEntityFromEntity(dbEntry.Entity, tableName);
            var optionalAuditDescriptionString = auditLogEventType.GetAuditStringForOperationType(tableName, null, auditableEntityDeleted.AuditDescriptionString);
            var auditLogEntry = CreateAuditLogEntryImpl(dbEntry,
                                                        tableName,
                                                        person,
                                                        changeDate,
                                                        auditLogEventType,
                                                        "*ALL",
                                                        AuditLogEventType.Deleted.AuditLogEventTypeDisplayName,
                                                        null,
                                                        optionalAuditDescriptionString,
                                                        objectContext);

            return(auditLogEntry);
        }
        private static AuditLog CreateAuditLogEntryImpl(DbEntityEntry dbEntry,
                                                        string tableName,
                                                        Person person,
                                                        DateTime changeDate,
                                                        AuditLogEventType auditLogEventType,
                                                        string propertyName,
                                                        object newValue,
                                                        object originalValue,
                                                        string optionalAuditDescriptionString,
                                                        ObjectContext objectContext)
        {
            var recordID       = (int)dbEntry.Property(PrimaryKeyName).CurrentValue;
            var newValueString = newValue != null?newValue.ToString() : string.Empty;

            var auditLog = new AuditLog(person, changeDate, auditLogEventType, tableName, recordID, propertyName, newValueString)
            {
                OriginalValue = originalValue != null?originalValue.ToString() : null,
                                    AuditDescription = optionalAuditDescriptionString
            };

            AddAdditionalRecordColumns(dbEntry, tableName, auditLog);
            return(auditLog);
        }
 /// <summary>
 /// Creates a "blank" object of this type and populates primitives with defaults
 /// </summary>
 public static AuditLog CreateNewBlank(Person person, AuditLogEventType auditLogEventType)
 {
     return(new AuditLog(person, default(DateTime), auditLogEventType, default(string), default(int), default(string), default(string)));
 }
        /// <summary>
        /// TODO: should be able to refactor these convert enum to human readable string functions to one call
        /// </summary>
        private static string ConvertProjectLocationAreaEnumToHumanReadableString(ObjectStateEntry objectStateEntry, AuditLogEventType auditLogEventType)
        {
            string oldName;

            var originalValue = objectStateEntry.OriginalValues[PropertyNameProjectLocationAreaID];
            var currentValue  = objectStateEntry.CurrentValues[PropertyNameProjectLocationAreaID];

            if (originalValue is DBNull)
            {
                oldName = "";
            }
            else
            {
                oldName = string.Empty;// ProjectLocationArea.AllLookupDictionary[((int) originalValue)].ProjectLocationAreaDisplayName;
            }

            string newName;

            if (currentValue is DBNull)
            {
                newName = "";
            }
            else
            {
                newName = string.Empty; //ProjectLocationArea.AllLookupDictionary[(int) currentValue].ProjectLocationAreaDisplayName;
            }
            return(auditLogEventType.GetAuditStringForOperationType("Location", oldName, newName));
        }
        /// <summary>
        /// TODO: should be able to refactor these convert enum to human readable string functions to one call
        /// </summary>
        private static string ConvertProjectImageTimingEnumToHumanReadableString(ObjectStateEntry objectStateEntry, AuditLogEventType auditLogEventType)
        {
            string oldName;
            string newName;

            var originalValue = objectStateEntry.OriginalValues[PropertyNameProjectImageTimingID];
            var currentValue  = objectStateEntry.CurrentValues[PropertyNameProjectImageTimingID];

            if (originalValue is DBNull)
            {
                oldName = "";
            }
            else
            {
                var oldPrimaryKeyValue = (int)originalValue;
                oldName = ProjectImageTiming.AllLookupDictionary[oldPrimaryKeyValue].ProjectImageTimingDisplayName;
            }

            if (currentValue is DBNull)
            {
                newName = "";
            }
            else
            {
                newName = ProjectImageTiming.AllLookupDictionary[(int)currentValue].ProjectImageTimingDisplayName;
            }

            return(auditLogEventType.GetAuditStringForOperationType("Image Timing", oldName, newName));
        }
        private static string ConvertEnumsToHumanReadableString(string propertyName, ObjectStateEntry objectStateEntry, AuditLogEventType auditLogEventType)
        {
            switch (propertyName)
            {
            case PropertyNameProjectStageID:
                return(ConvertProjectStageEnumToHumanReadableString(objectStateEntry, auditLogEventType));

            case PropertyNameProjectImageTimingID:
                return(ConvertProjectImageTimingEnumToHumanReadableString(objectStateEntry, auditLogEventType));

            case PropertyNameProjectLocationAreaID:
                return(ConvertProjectLocationAreaEnumToHumanReadableString(objectStateEntry, auditLogEventType));

            default:
                // deliberately do nothing for now, expand as needed for other enum
                return(null);
            }
        }
        /// <summary>
        /// Gets the audit description string for a property that came from a <see cref="DbEntityEntry"/> that has an <see cref="EntityState"/> of <see cref="EntityState.Added"/> or <see cref="EntityState.Modified"/>
        /// This will attempt to look up a foreign key and return a more descriptive string for that fk property
        /// </summary>
        public static string GetAuditDescriptionStringIfAnyForProperty(ObjectContext objectContext, DbEntityEntry dbEntry, string propertyName, AuditLogEventType auditLogEventType)
        {
            var objectStateEntry = objectContext.ObjectStateManager.GetObjectStateEntry(dbEntry.Entity);
            // find foreign key relationships for given propertyname
            var relatedEnds = GetDependentForeignKeyRelatedEndsForProperty(objectStateEntry, propertyName);

            foreach (var end in relatedEnds)
            {
                var elementType = end.RelationshipSet.ElementType as AssociationType;
                if (elementType == null || !elementType.IsForeignKey)
                {
                    continue;
                }

                foreach (var constraint in elementType.ReferentialConstraints)
                {
                    // Multiplicity many means we are looking at a foreign key in a dependent entity
                    // I assume that ToRole will point to a dependent entity, don't know if it can be FromRole
                    Check.Require(constraint.ToRole.RelationshipMultiplicity == RelationshipMultiplicity.Many);
                    // If not 1 then it is a composite key I guess. Becomes a lot more difficult to handle.
                    Check.Require(constraint.ToProperties.Count == 1);

                    var    entityName = constraint.FromRole.Name;
                    string auditDescriptionStringForOriginalValue = null;
                    if (!IgnoredTables.Contains(entityName))
                    {
                        var constraintProperty = constraint.ToProperties[0];
                        var principalEntity    = (EntityReference)end;

                        var newEntityKey = principalEntity.EntityKey;
                        var auditDescriptionStringForNewValue = GetAuditDescriptionStringForEntityKey(objectContext, newEntityKey, entityName);

                        if (newEntityKey != null)
                        {
                            var oldEntityKey = CreateEntityKeyForValue(newEntityKey.EntitySetName,
                                                                       principalEntity.EntityKey.EntityKeyValues[0].Key,
                                                                       objectStateEntry.OriginalValues[constraintProperty.Name]);
                            auditDescriptionStringForOriginalValue = GetAuditDescriptionStringForEntityKey(objectContext, oldEntityKey, entityName);
                        }
                        return(auditLogEventType.GetAuditStringForOperationType(entityName, auditDescriptionStringForOriginalValue, auditDescriptionStringForNewValue));
                    }
                }
            }

            var enumsToHumanReadableString = ConvertEnumsToHumanReadableString(propertyName, objectStateEntry, auditLogEventType);

            if (enumsToHumanReadableString != null)
            {
                return(enumsToHumanReadableString);
            }

            return(null);
        }