如何审核角色删除?
How to audit role removals?
从用户中删除角色后,我需要跟踪是谁做的(即哪个 AbpUser)以及他们何时做的。
显而易见的解决方案是重新定义 UserRole 实体,使其继承自 FullAuditedEntity 而不是 CreationAuditedEntity,但 UserRole 实体是在 nuget 包中定义的,所以我不能简单地更改定义。
有没有办法实现我没有看到的这种行为?
这是我到目前为止尝试过的方法。
方法 1:我尝试通过在 AbpUserRole table 上设置删除触发器来在数据库级别处理此问题,这会将记录插入 AbpUserRoleDeleted table,但我想不出一种找出哪个 AbpUser 使用这种方法进行删除的方法。我只能跟踪操作发生的时间。
方法 2:我尝试侦听 UserRole 实体上的 EntityDeleted 域事件,但它似乎没有被触发。有趣的是,当我从用户中删除角色时会触发 EntityUpdated 事件,但即使假设此事件只会在删除 UserRole 时触发,事件数据仍然不包括删除的人。如果是这样,我可以手动将审计信息保存在单独的 table 中,就像数据库删除触发器一样,但这次我将拥有负责删除的 AbpUser。
方法 3:我尝试按照 here 的步骤扩展 UserRole 实体。我能够实现 IDeletionAudited 接口并生成在 AbpUserRoles table 上创建关联列的迁移,但是从用户中删除角色执行的是硬删除而不是软删除,所以我无法判断列甚至会被填充。我假设他们没有。
方法 4:我尝试为 UserRole 实体启用实体历史记录,但它似乎只跟踪创建 UserRole 实体的时间。
这似乎工作正常。
//src\aspnet-core\src\Company.App.EntityFrameworkCore\EntityFrameworkCore\AppDbContext.cs
namespace Company.App.EntityFrameworkCore
{
public class AppDbContext : AbpZeroDbContext<Tenant, Role, User, AppDbContext>, IAbpPersistedGrantDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
ChangeTracker.StateChanged += OnEntityStateChanged;
}
private void OnEntityStateChanged(object sender, EntityStateChangedEventArgs e)
{
if (e.Entry.Entity is UserRole && e.NewState == EntityState.Deleted)
{
//update instead of delete
e.Entry.State = EntityState.Modified;
e.Entry.CurrentValues["IsDeleted"] = true;
e.Entry.CurrentValues["DeletionTime"] = DateTime.Now;
e.Entry.CurrentValues["DeleterUserId"] = AbpSession.UserId;
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//use query filter on the `IsDeleted` shadow property
modelBuilder.Entity<UserRole>().HasQueryFilter(p => !EF.Property<bool>(p, "IsDeleted"));
modelBuilder.Entity<UserRole>().Property<bool>("IsDeleted");
modelBuilder.Entity<UserRole>().Property<DateTime?>("DeletionTime").IsRequired(false);
modelBuilder.Entity<UserRole>().Property<long?>("DeleterUserId").IsRequired(false);
}
}
}
从用户中删除角色后,我需要跟踪是谁做的(即哪个 AbpUser)以及他们何时做的。
显而易见的解决方案是重新定义 UserRole 实体,使其继承自 FullAuditedEntity 而不是 CreationAuditedEntity,但 UserRole 实体是在 nuget 包中定义的,所以我不能简单地更改定义。
有没有办法实现我没有看到的这种行为?
这是我到目前为止尝试过的方法。
方法 1:我尝试通过在 AbpUserRole table 上设置删除触发器来在数据库级别处理此问题,这会将记录插入 AbpUserRoleDeleted table,但我想不出一种找出哪个 AbpUser 使用这种方法进行删除的方法。我只能跟踪操作发生的时间。
方法 2:我尝试侦听 UserRole 实体上的 EntityDeleted 域事件,但它似乎没有被触发。有趣的是,当我从用户中删除角色时会触发 EntityUpdated 事件,但即使假设此事件只会在删除 UserRole 时触发,事件数据仍然不包括删除的人。如果是这样,我可以手动将审计信息保存在单独的 table 中,就像数据库删除触发器一样,但这次我将拥有负责删除的 AbpUser。
方法 3:我尝试按照 here 的步骤扩展 UserRole 实体。我能够实现 IDeletionAudited 接口并生成在 AbpUserRoles table 上创建关联列的迁移,但是从用户中删除角色执行的是硬删除而不是软删除,所以我无法判断列甚至会被填充。我假设他们没有。
方法 4:我尝试为 UserRole 实体启用实体历史记录,但它似乎只跟踪创建 UserRole 实体的时间。
这似乎工作正常。
//src\aspnet-core\src\Company.App.EntityFrameworkCore\EntityFrameworkCore\AppDbContext.cs
namespace Company.App.EntityFrameworkCore
{
public class AppDbContext : AbpZeroDbContext<Tenant, Role, User, AppDbContext>, IAbpPersistedGrantDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
ChangeTracker.StateChanged += OnEntityStateChanged;
}
private void OnEntityStateChanged(object sender, EntityStateChangedEventArgs e)
{
if (e.Entry.Entity is UserRole && e.NewState == EntityState.Deleted)
{
//update instead of delete
e.Entry.State = EntityState.Modified;
e.Entry.CurrentValues["IsDeleted"] = true;
e.Entry.CurrentValues["DeletionTime"] = DateTime.Now;
e.Entry.CurrentValues["DeleterUserId"] = AbpSession.UserId;
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//use query filter on the `IsDeleted` shadow property
modelBuilder.Entity<UserRole>().HasQueryFilter(p => !EF.Property<bool>(p, "IsDeleted"));
modelBuilder.Entity<UserRole>().Property<bool>("IsDeleted");
modelBuilder.Entity<UserRole>().Property<DateTime?>("DeletionTime").IsRequired(false);
modelBuilder.Entity<UserRole>().Property<long?>("DeleterUserId").IsRequired(false);
}
}
}