Browse Source

Refactor `DisableAuditingAttribute` to allow it to ignore changes to `AuditProperties`.

Resolve #23168
pull/23174/head
maliming 11 months ago
parent
commit
e770f89548
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 2
      framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/DisableAuditingAttribute.cs
  2. 21
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  3. 77
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Auditing/Auditing_Tests.cs
  4. 9
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs

2
framework/src/Volo.Abp.Auditing.Contracts/Volo/Abp/Auditing/DisableAuditingAttribute.cs

@ -5,5 +5,7 @@ namespace Volo.Abp.Auditing;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]
public class DisableAuditingAttribute : Attribute
{
public bool UpdateModificationProps { get; set; } = true;
public bool PublishEntityEvent { get; set; } = true;
}

21
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -428,20 +428,29 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext,
case EntityState.Modified:
if (entry.Properties.Any(x => x.IsModified && (x.Metadata.ValueGenerated == ValueGenerated.Never || x.Metadata.ValueGenerated == ValueGenerated.OnAdd)))
{
if (entry.Properties.Where(x => x.IsModified).All(x => x.Metadata.IsForeignKey()))
var modifiedProperties = entry.Properties.Where(x => x.IsModified).ToList();
if (modifiedProperties.All(x => x.Metadata.IsForeignKey()))
{
// Skip `PublishEntityDeletedEvent/PublishEntityUpdatedEvent` if only foreign keys have changed.
break;
}
ApplyAbpConceptsForModifiedEntity(entry);
if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted)
var disableAuditingAttributes = modifiedProperties.Select(x => x.Metadata.PropertyInfo?.GetCustomAttribute<DisableAuditingAttribute>()).ToList();
if (disableAuditingAttributes.Any(x => x == null || x.UpdateModificationProps))
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity);
ApplyAbpConceptsForModifiedEntity(entry);
}
else
if (disableAuditingAttributes.Any(x => x == null || x.PublishEntityEvent))
{
EntityChangeEventHelper.PublishEntityUpdatedEvent(entry.Entity);
if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted)
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity);
}
else
{
EntityChangeEventHelper.PublishEntityUpdatedEvent(entry.Entity);
}
}
}
else if (EntityChangeOptions.Value.PublishEntityUpdatedEventWhenNavigationChanges &&

77
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Auditing/Auditing_Tests.cs

@ -1,6 +1,10 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NSubstitute;
using Shouldly;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.TestApp;
using Volo.Abp.TestApp.Testing;
using Xunit;
@ -9,6 +13,16 @@ namespace Volo.Abp.EntityFrameworkCore.Auditing;
public class Auditing_Tests : Auditing_Tests<AbpEntityFrameworkCoreTestModule>
{
protected IEntityChangeEventHelper EntityChangeEventHelper;
protected override void AfterAddApplication(IServiceCollection services)
{
EntityChangeEventHelper = Substitute.For<IEntityChangeEventHelper>();
services.Replace(ServiceDescriptor.Singleton(EntityChangeEventHelper));
base.AfterAddApplication(services);
}
[Fact]
public async Task Should_Not_Set_Modification_If_Properties_Generated_By_Database()
{
@ -24,7 +38,6 @@ public class Auditing_Tests : Auditing_Tests<AbpEntityFrameworkCoreTestModule>
douglas.ShouldNotBeNull();
douglas.LastModificationTime.ShouldBeNull();
douglas.LastModificationTime.ShouldBeNull();
douglas.LastModifierId.ShouldBeNull();
}));
}
@ -71,4 +84,66 @@ public class Auditing_Tests : Auditing_Tests<AbpEntityFrameworkCoreTestModule>
douglas.LastModifierId.ShouldBe(CurrentUserId);
}));
}
[Fact]
public async Task Should_Not_Set_Modification_If_Properties_HasDisableAuditing_UpdateModificationProps()
{
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
douglas.DisableAuditingUpdateModificationPropsProperty = Guid.NewGuid().ToString();
}));
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.LastModificationTime.ShouldBeNull();
douglas.LastModifierId.ShouldBeNull();
}));
EntityChangeEventHelper.Received().PublishEntityUpdatedEvent(Arg.Any<object>());
}
[Fact]
public async Task Should_Not_PublishEntityEvent_If_Properties_HasDisableAuditing_PublishEntityEventProperty()
{
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
douglas.DisableAuditingPublishEntityEventProperty = Guid.NewGuid().ToString();
}));
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.LastModificationTime.ShouldNotBeNull();
}));
EntityChangeEventHelper.DidNotReceive().PublishEntityUpdatedEvent(Arg.Any<object>());
}
[Fact]
public async Task Should_Set_Modification_And_PublishEntityEvent_If_Properties_HasDisableAuditing()
{
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.GetAsync(TestDataBuilder.UserDouglasId);
douglas.DisableAuditingProperty = Guid.NewGuid().ToString();
}));
await WithUnitOfWorkAsync((async () =>
{
var douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.LastModificationTime.ShouldNotBeNull();
}));
EntityChangeEventHelper.Received().PublishEntityUpdatedEvent(Arg.Any<object>());
}
}

9
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs

@ -34,6 +34,15 @@ public class Person : FullAuditedAggregateRoot<Guid>, IMultiTenant, IHasEntityVe
public int EntityVersion { get; set; }
[DisableAuditing(UpdateModificationProps = false)]
public string DisableAuditingUpdateModificationPropsProperty { get; set; }
[DisableAuditing(PublishEntityEvent = false)]
public string DisableAuditingPublishEntityEventProperty { get; set; }
[DisableAuditing]
public string DisableAuditingProperty { get; set; }
private Person()
{
}

Loading…
Cancel
Save