diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs index 5ea616d8f9..60d92b82b1 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/AuditLogConsts.cs @@ -5,6 +5,6 @@ public static int MaxClientIpAddressLength = 64; public static int MaxClientNameLength = 128; public static int MaxBrowserInfoLength = 512; - public static int MaxExceptionLength = 2000; + public static int MaxExceptionsLength = 8*1024; } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs index 7b80e0f695..63a54b536d 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditLog.cs @@ -11,35 +11,35 @@ namespace Volo.Abp.AuditLogging { public class AuditLog : Entity, IHasExtraProperties, IMultiTenant { - public virtual Guid? TenantId { get; set; } + public virtual Guid? TenantId { get; protected set; } - public virtual Guid? UserId { get; set; } + public virtual Guid? UserId { get; protected set; } - public virtual Guid? ImpersonatorUserId { get; set; } + public virtual Guid? ImpersonatorUserId { get; protected set; } - public virtual Guid? ImpersonatorTenantId { get; set; } + public virtual Guid? ImpersonatorTenantId { get; protected set; } - public virtual DateTime ExecutionTime { get; set; } + public virtual DateTime ExecutionTime { get; protected set; } - public virtual int ExecutionDuration { get; set; } + public virtual int ExecutionDuration { get; protected set; } - public virtual string ClientIpAddress { get; set; } + public virtual string ClientIpAddress { get; protected set; } - public virtual string ClientName { get; set; } + public virtual string ClientName { get; protected set; } - public virtual string BrowserInfo { get; set; } + public virtual string BrowserInfo { get; protected set; } - public virtual List Exceptions { get; } + public virtual string Exceptions { get; set; } - public Dictionary ExtraProperties { get; } + public Dictionary ExtraProperties { get; set; } public ICollection EntityChanges { get; } - public ICollection Actions { get; set; } + public ICollection Actions { get; protected set; } protected AuditLog() { - + ExtraProperties = new Dictionary(); } public AuditLog(IGuidGenerator guidGenerator, AuditLogInfo auditInfo) @@ -55,9 +55,9 @@ namespace Volo.Abp.AuditLogging ImpersonatorUserId = auditInfo.ImpersonatorUserId; ImpersonatorTenantId = auditInfo.ImpersonatorTenantId; ExtraProperties = auditInfo.ExtraProperties; - EntityChanges = auditInfo.EntityChanges.Select(e => new EntityChange(e)).ToList(); + EntityChanges = auditInfo.EntityChanges.Select(e => new EntityChange(guidGenerator, Id, e)).ToList(); Actions = auditInfo.Actions.Select(e => new AuditLogAction(guidGenerator.Create(), Id, e)).ToList(); - Exceptions = auditInfo.Exceptions.Select(e => e.ToString()).ToList(); + Exceptions = String.Join(Environment.NewLine, auditInfo.Exceptions.Select(e=>e.ToString()).ToArray()); } } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditingStore.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditingStore.cs index 887ff4e97c..84e65e832b 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditingStore.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/AuditingStore.cs @@ -1,21 +1,24 @@ using System.Threading.Tasks; using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; namespace Volo.Abp.AuditLogging { public class AuditingStore : IAuditingStore, ITransientDependency { private readonly IAuditLogRepository _auditLogRepository; + private readonly IGuidGenerator _guidGenerator; - public AuditingStore(IAuditLogRepository auditLogRepository) + public AuditingStore(IAuditLogRepository auditLogRepository, IGuidGenerator guidGenerator) { _auditLogRepository = auditLogRepository; + _guidGenerator = guidGenerator; } public async Task SaveAsync(AuditLogInfo auditInfo) { - await _auditLogRepository.InsertAsync(new AuditLog(auditInfo)); + await _auditLogRepository.InsertAsync(new AuditLog(_guidGenerator, auditInfo)); } } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/EntityChange.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/EntityChange.cs index 38baef3788..b4f58f2f23 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/EntityChange.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/EntityChange.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities; +using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; namespace Volo.Abp.AuditLogging @@ -20,21 +22,23 @@ namespace Volo.Abp.AuditLogging public virtual string EntityTypeFullName { get; protected set; } - public ICollection PropertyChanges { get; protected set; } + public ICollection PropertyChanges { get; protected set; } protected EntityChange() { } - public EntityChange(EntityChangeInfo entityChangeInfo) + public EntityChange(IGuidGenerator guidGenerator, Guid auditLogId, EntityChangeInfo entityChangeInfo) { + Id = guidGenerator.Create(); + AuditLogId = auditLogId; TenantId = entityChangeInfo.TenantId; ChangeTime = entityChangeInfo.ChangeTime; ChangeType = entityChangeInfo.ChangeType; EntityId = entityChangeInfo.EntityId; EntityTypeFullName = entityChangeInfo.EntityTypeFullName; - PropertyChanges = entityChangeInfo.PropertyChanges; //Copy instead of assiging + PropertyChanges = entityChangeInfo.PropertyChanges.Select( p=> new EntityPropertyChange(guidGenerator, Id, p)).ToList(); } } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/EntityPropertyChange.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/EntityPropertyChange.cs new file mode 100644 index 0000000000..4da4dea2c8 --- /dev/null +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/EntityPropertyChange.cs @@ -0,0 +1,35 @@ +using System; +using Volo.Abp.Auditing; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Guids; + +namespace Volo.Abp.AuditLogging +{ + public class EntityPropertyChange : Entity + { + public virtual Guid EntityChangeId { get; protected set; } + + public virtual string NewValue { get; protected set; } + + public virtual string OriginalValue { get; protected set; } + + public virtual string PropertyName { get; protected set; } + + public virtual string PropertyTypeFullName { get; protected set; } + + protected EntityPropertyChange() + { + + } + + public EntityPropertyChange(IGuidGenerator guidGenerator, Guid entityChangeId, EntityPropertyChangeInfo entityChangeInfo) + { + EntityChangeId = entityChangeId; + Id = guidGenerator.Create(); + NewValue = entityChangeInfo.NewValue; + OriginalValue = entityChangeInfo.OriginalValue; + PropertyName = entityChangeInfo.PropertyName; + PropertyTypeFullName = entityChangeInfo.PropertyTypeFullName; + } + } +} \ No newline at end of file diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingtDbContextModelBuilderExtensions.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingtDbContextModelBuilderExtensions.cs index 7e6394974e..d4d9b53515 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingtDbContextModelBuilderExtensions.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingtDbContextModelBuilderExtensions.cs @@ -1,5 +1,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.Modeling; namespace Volo.Abp.AuditLogging.EntityFrameworkCore { @@ -22,12 +23,19 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore b.ToTable(tablePrefix + "AuditLogs", schema); b.Property(x => x.ClientIpAddress).HasMaxLength(AuditLogConsts.MaxClientIpAddressLength).HasColumnName(nameof(AuditLog.ClientIpAddress)); - b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength); //TODO: Add HasColumnNames - b.Property(x => x.BrowserInfo).HasMaxLength(AuditLogConsts.MaxBrowserInfoLength); - b.Property(x => x.Exceptions).HasMaxLength(AuditLogConsts.MaxExceptionLength); + b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength).HasColumnName(nameof(AuditLog.ClientName)); + b.Property(x => x.BrowserInfo).HasMaxLength(AuditLogConsts.MaxBrowserInfoLength).HasColumnName(nameof(AuditLog.BrowserInfo)); + b.Property(x => x.Exceptions).HasMaxLength(AuditLogConsts.MaxExceptionsLength).HasColumnName(nameof(AuditLog.Exceptions)); + b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLog.ExecutionDuration)); + b.Property(x => x.ImpersonatorTenantId).HasColumnName(nameof(AuditLog.ImpersonatorTenantId)); + b.Property(x => x.ImpersonatorUserId).HasColumnName(nameof(AuditLog.ImpersonatorUserId)); + b.Property(x => x.UserId).HasColumnName(nameof(AuditLog.UserId)); + b.Property(x => x.TenantId).HasColumnName(nameof(AuditLog.TenantId)); - b.HasOne().WithMany().HasForeignKey(x => x.EntityChanges); - b.HasMany().WithOne().HasForeignKey(x => x.); + b.ConfigureExtraProperties(); + + b.HasMany().WithOne().HasForeignKey(x => x.AuditLogId); + b.HasMany().WithOne().HasForeignKey(x => x.AuditLogId); b.HasIndex(x => new { x.TenantId, x.UserId, x.ExecutionTime }); }); @@ -36,19 +44,42 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore { b.ToTable(tablePrefix + "EntityChanges", schema); - b.Property(x => x.EntityTypeFullName).IsRequired(); - b.Property(x => x.EntityId).IsRequired(); + b.Property(x => x.EntityTypeFullName).IsRequired().HasColumnName(nameof(EntityChange.EntityTypeFullName)); + b.Property(x => x.EntityId).IsRequired().HasColumnName(nameof(EntityChange.EntityId)); + b.Property(x => x.AuditLogId).IsRequired().HasColumnName(nameof(EntityChange.AuditLogId)); + b.Property(x => x.ChangeTime).IsRequired().HasColumnName(nameof(EntityChange.ChangeTime)); + b.Property(x => x.ChangeType).IsRequired().HasColumnName(nameof(EntityChange.ChangeType)); + b.Property(x => x.TenantId).IsRequired().HasColumnName(nameof(EntityChange.TenantId)); + + b.HasMany().WithOne().HasForeignKey(x => x.EntityChangeId); b.HasIndex(x => new { x.TenantId, x.EntityTypeFullName}); }); + builder.Entity(b => + { + b.ToTable(tablePrefix + "EntityPropertyChanges", schema); + + b.Property(x => x.NewValue).IsRequired().HasColumnName(nameof(EntityPropertyChange.NewValue)); + b.Property(x => x.PropertyName).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyName)); + b.Property(x => x.PropertyTypeFullName).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyTypeFullName)); + b.Property(x => x.OriginalValue).HasColumnName(nameof(EntityPropertyChange.OriginalValue)); + + b.HasIndex(x => new { x.PropertyName}); + }); + builder.Entity(b => { b.ToTable(tablePrefix + "AuditLogActions", schema); - b.Property(x => x.ServiceName).HasMaxLength(AuditLogActionConsts.MaxServiceNameLength); - b.Property(x => x.MethodName).HasMaxLength(AuditLogActionConsts.MaxMethodNameLength); - b.Property(x => x.Parameters).HasMaxLength(AuditLogActionConsts.MaxParametersLength); + b.Property(x => x.ServiceName).HasMaxLength(AuditLogActionConsts.MaxServiceNameLength).HasColumnName(nameof(AuditLogAction.ServiceName)); + b.Property(x => x.MethodName).HasMaxLength(AuditLogActionConsts.MaxMethodNameLength).HasColumnName(nameof(AuditLogAction.MethodName)); + b.Property(x => x.Parameters).HasMaxLength(AuditLogActionConsts.MaxParametersLength).HasColumnName(nameof(AuditLogAction.Parameters)); + b.Property(x => x.AuditLogId).HasColumnName(nameof(AuditLogAction.AuditLogId)); + b.Property(x => x.ExecutionTime).HasColumnName(nameof(AuditLogAction.ExecutionTime)); + b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLogAction.ExecutionDuration)); + + b.ConfigureExtraProperties(); b.HasIndex(x => new { x.ServiceName, x.ExecutionTime}); }); diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs index 55f837773d..b77bb7d592 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs @@ -8,6 +8,10 @@ using Volo.Abp.Modularity; namespace Volo.Abp.AuditLogging.EntityFrameworkCore { + [DependsOn( + typeof(AbpAuditLoggingTestBaseModule), + typeof(AbpAuditLoggingEntityFrameworkCoreModule) + )] public class AbpAuditLoggingEntityFrameworkCoreTestModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo/Abp/AuditLogging/AuditStore_Basic_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo/Abp/AuditLogging/AuditStore_Basic_Tests.cs index 709d9c60dd..0f0409f691 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo/Abp/AuditLogging/AuditStore_Basic_Tests.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo/Abp/AuditLogging/AuditStore_Basic_Tests.cs @@ -27,11 +27,7 @@ namespace Volo.Abp.AuditLogging ExecutionDuration = 42, ClientIpAddress = "153.1.7.61", ClientName = "MyDesktop", - BrowserInfo = "Chrome", - //ServiceName = "SampleService2", - //MethodName = "SampleMethod2", - //Parameters = "SampleParameter", - //Exceptions = new Exceptions("something went wrong.") + BrowserInfo = "Chrome" }; await _auditingStore.SaveAsync(auditLog);