Auditor
Sun May 12 2024 08:06:12 GMT+0000 (Coordinated Universal Time)
Saved by @Samarmhamed78
#AuditEntity public class AuditEntity { [Key] public Guid Id { get; set; } public string OldValues { get; set; } public string NewValues { get; set; } public DateTimeOffset DateTimeOffset { get; set; } public EntityState EntityState { get; set; } public string ByUser { get; set; } public Nullable<Guid> AuditMetaDataId { get; set; } [ForeignKey(nameof(AuditMetaDataId))] public virtual AuditMetaDataEntity AuditMetaData { get; set; } } -------------------------------------------------------- #AuditMetaDataEntity public class AuditMetaDataEntity { [Key] public Guid Id { get; set; } public Guid HashPrimaryKey { get; set; } public string SchemaTable { get; set; } public string ReadablePrimaryKey { get; set; } public string Schema { get; set; } public string Table { get; set; } public string DisplayName { get; set; } } -------------------------------------------------------- #extensions internal static class InternalExtensions { internal static bool ShouldBeAudited(this EntityEntry entry) { return entry.State != EntityState.Detached && entry.State != EntityState.Unchanged && !(entry.Entity is AuditEntity) && !(entry.Entity is AuditMetaDataEntity) && entry.IsAuditable(); } internal static bool IsAuditable(this EntityEntry entityEntry) { AuditableAttribute enableAuditAttribute = (AuditableAttribute)Attribute.GetCustomAttribute(entityEntry.Entity.GetType(), typeof(AuditableAttribute)); return enableAuditAttribute != null; } internal static bool IsAuditable(this PropertyEntry propertyEntry) { Type entityType = propertyEntry.EntityEntry.Entity.GetType(); PropertyInfo propertyInfo = entityType.GetProperty(propertyEntry.Metadata.Name); bool disableAuditAttribute = Attribute.IsDefined(propertyInfo, typeof(NotAuditableAttribute)); return IsAuditable(propertyEntry.EntityEntry) && !disableAuditAttribute; } } public static class Extensions { public static string ToReadablePrimaryKey(this EntityEntry entry) { IKey primaryKey = entry.Metadata.FindPrimaryKey(); if (primaryKey == null) { return null; } else { return string.Join(",", (primaryKey.Properties.ToDictionary(x => x.Name, x => x.PropertyInfo.GetValue(entry.Entity))).Select(x => x.Key + "=" + x.Value)); } } public static Guid ToGuidHash(this string readablePrimaryKey) { using (SHA512 sha512 = SHA512.Create()) { byte[] hashValue = sha512.ComputeHash(Encoding.Default.GetBytes(readablePrimaryKey)); byte[] reducedHashValue = new byte[16]; for (int i = 0; i < 16; i++) { reducedHashValue[i] = hashValue[i * 4]; } return new Guid(reducedHashValue); } } } -------------------------------------------------------- #Attribute [AttributeUsage(AttributeTargets.Class)] public sealed class AuditableAttribute : Attribute { } [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public sealed class NotAuditableAttribute : Attribute { } -------------------------------------------------------- #AuditEntry internal class AuditEntry { private string _readablePrimaryKey; public string ReadablePrimaryKey { get { if (string.IsNullOrEmpty(_readablePrimaryKey)) _readablePrimaryKey = Entry.ToReadablePrimaryKey(); return _readablePrimaryKey; } set { _readablePrimaryKey = value; } } public Guid HashReferenceId { get; set; } public EntityEntry Entry { get; } public string TableName { get; set; } public string DisplayName { get; set; } public string SchemaName { get; set; } public Dictionary<string, object> OldValues { get; } = new Dictionary<string, object>(); public Dictionary<string, object> NewValues { get; } = new Dictionary<string, object>(); public EntityState EntityState { get; set; } public string ByUser { get; set; } public List<PropertyEntry> TemporaryProperties { get; } = new List<PropertyEntry>(); public bool HasTemporaryProperties => TemporaryProperties.Any(); public AuditEntry(EntityEntry entry, ICurrentUser currentUser) { Entry = entry; ReadablePrimaryKey = Entry.ToReadablePrimaryKey(); HashReferenceId = ReadablePrimaryKey.ToGuidHash(); TableName = entry.Metadata.GetTableName(); DisplayName = entry.Metadata.DisplayName(); SchemaName = entry.Metadata.GetSchema()!=null ? entry.Metadata.GetSchema():"db" ; EntityState = entry.State; ByUser = currentUser == default ? "Unknown" : currentUser.UserName; foreach (PropertyEntry property in entry.Properties) { if (property.IsAuditable()) { if (property.IsTemporary) { TemporaryProperties.Add(property); continue; } string propertyName = property.Metadata.Name; switch (entry.State) { case EntityState.Added: NewValues[propertyName] = property.CurrentValue; break; case EntityState.Deleted: OldValues[propertyName] = property.OriginalValue; break; case EntityState.Modified: if (property.IsModified) { OldValues[propertyName] = property.OriginalValue; NewValues[propertyName] = property.CurrentValue; } break; } } } } public void Update() { // Get the final value of the temporary properties foreach (var prop in TemporaryProperties) { NewValues[prop.Metadata.Name] = prop.CurrentValue; } if (TemporaryProperties != default && TemporaryProperties.Count(x => x.Metadata.IsKey()) > 0) { ReadablePrimaryKey = Entry.ToReadablePrimaryKey(); HashReferenceId = ReadablePrimaryKey.ToGuidHash(); } } public AuditMetaDataEntity ToAuditMetaDataEntity() { AuditMetaDataEntity auditMetaData = new AuditMetaDataEntity(); auditMetaData.DisplayName = DisplayName; auditMetaData.Schema = SchemaName; auditMetaData.Table = TableName; auditMetaData.SchemaTable = $"{(!string.IsNullOrEmpty(SchemaName) ? SchemaName + "." : "")}{TableName}"; auditMetaData.ReadablePrimaryKey = ReadablePrimaryKey; auditMetaData.HashPrimaryKey = HashReferenceId; return auditMetaData; } public AuditEntity ToAuditEntity(AuditMetaDataEntity auditMetaData) { AuditEntity audit = new AuditEntity(); audit.OldValues = OldValues.Count == 0 ? " " : JsonConvert.SerializeObject(OldValues); audit.NewValues = NewValues.Count == 0 ? " " : JsonConvert.SerializeObject(NewValues); audit.EntityState = EntityState; audit.DateTimeOffset = DateTimeOffset.UtcNow; audit.ByUser = ByUser; audit.AuditMetaData = auditMetaData; return audit; } public AuditEntity ToAuditEntity() { AuditEntity audit = new AuditEntity(); audit.OldValues = OldValues.Count == 0 ? null : JsonConvert.SerializeObject(OldValues); audit.NewValues = NewValues.Count == 0 ? null : JsonConvert.SerializeObject(NewValues); audit.EntityState = EntityState; audit.DateTimeOffset = DateTimeOffset.UtcNow; audit.ByUser = ByUser; return audit; } }
Comments