Browse Source

Merge pull request #7935 from abpframework/role-change-handling

Handle role name changed & role deleted events to update related permission grants
pull/7952/head
liangshiwei 6 years ago
committed by GitHub
parent
commit
2900170553
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleNameChangedEto.cs
  2. 3
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs
  3. 12
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs
  4. 5
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleNameChangedEvent.cs
  5. 35
      modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleDeletedEventHandler.cs
  6. 60
      modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleUpdateEventHandler.cs
  7. 105
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/Distributed_Role_Change_Events_Test.cs
  8. 60
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/RoleChangingEvents_Test.cs
  9. 4
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator.cs
  10. 22
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs

16
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityRoleNameChangedEto.cs

@ -0,0 +1,16 @@
using System;
namespace Volo.Abp.Identity
{
[Serializable]
public class IdentityRoleNameChangedEto
{
public Guid Id { get; set; }
public Guid? TenantId { get; set; }
public string Name { get; set; }
public string OldName { get; set; }
}
}

3
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs

@ -40,6 +40,9 @@ namespace Volo.Abp.Identity
options.EtoMappings.Add<IdentityClaimType, IdentityClaimTypeEto>(typeof(AbpIdentityDomainModule));
options.EtoMappings.Add<IdentityRole, IdentityRoleEto>(typeof(AbpIdentityDomainModule));
options.EtoMappings.Add<OrganizationUnit, OrganizationUnitEto>(typeof(AbpIdentityDomainModule));
options.AutoEventSelectors.Add<IdentityUser>();
options.AutoEventSelectors.Add<IdentityRole>();
});
var identityBuilder = context.Services.AddAbpIdentity(options =>

12
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs

@ -108,12 +108,24 @@ namespace Volo.Abp.Identity
Name = name;
AddLocalEvent(
#pragma warning disable 618
new IdentityRoleNameChangedEvent
#pragma warning restore 618
{
IdentityRole = this,
OldName = oldName
}
);
AddDistributedEvent(
new IdentityRoleNameChangedEto
{
Id = Id,
Name = Name,
OldName = oldName,
TenantId = TenantId
}
);
}
public override string ToString()

5
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleNameChangedEvent.cs

@ -1,5 +1,8 @@
namespace Volo.Abp.Identity
using System;
namespace Volo.Abp.Identity
{
[Obsolete("Use the distributed event (IdentityRoleNameChangedEto) instead.")]
public class IdentityRoleNameChangedEvent
{
public IdentityRole IdentityRole { get; set; }

35
modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleDeletedEventHandler.cs

@ -1,26 +1,27 @@
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Identity;
namespace Volo.Abp.PermissionManagement.Identity
{
// public class RoleDeletedEventHandler :
// ILocalEventHandler<EntityDeletedEventData<IdentityRole>>,
// ITransientDependency
// {
// protected IPermissionManager PermissionManager { get; }
//
// public RoleDeletedEventHandler(IPermissionManager permissionManager)
// {
// PermissionManager = permissionManager;
// }
//
// public virtual async Task HandleEventAsync(EntityDeletedEventData<IdentityRole> eventData)
// {
// await PermissionManager.DeleteAsync(RolePermissionValueProvider.ProviderName, eventData.Entity.Name);
// }
// }
public class RoleDeletedEventHandler :
IDistributedEventHandler<EntityDeletedEto<IdentityRoleEto>>,
ITransientDependency
{
protected IPermissionManager PermissionManager { get; }
public RoleDeletedEventHandler(IPermissionManager permissionManager)
{
PermissionManager = permissionManager;
}
public async Task HandleEventAsync(EntityDeletedEto<IdentityRoleEto> eventData)
{
await PermissionManager.DeleteAsync(RolePermissionValueProvider.ProviderName, eventData.Entity.Name);
}
}
}

60
modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleUpdateEventHandler.cs

@ -1,45 +1,33 @@
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.EventBus;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Identity;
namespace Volo.Abp.PermissionManagement.Identity
{
//TODO: This code can not be here!
public class RoleUpdateEventHandler :
IDistributedEventHandler<IdentityRoleNameChangedEto>,
ITransientDependency
{
protected IPermissionManager PermissionManager { get; }
protected IPermissionGrantRepository PermissionGrantRepository { get; }
public RoleUpdateEventHandler(
IPermissionManager permissionManager,
IPermissionGrantRepository permissionGrantRepository)
{
PermissionManager = permissionManager;
PermissionGrantRepository = permissionGrantRepository;
}
// public class RoleUpdateEventHandler :
// ILocalEventHandler<IdentityRoleNameChangedEvent>,
// ITransientDependency
// {
// protected IIdentityRoleRepository RoleRepository { get; }
// protected IPermissionManager PermissionManager { get; }
// protected IPermissionGrantRepository PermissionGrantRepository { get; }
//
// public RoleUpdateEventHandler(
// IIdentityRoleRepository roleRepository,
// IPermissionManager permissionManager,
// IPermissionGrantRepository permissionGrantRepository)
// {
// RoleRepository = roleRepository;
// PermissionManager = permissionManager;
// PermissionGrantRepository = permissionGrantRepository;
// }
//
// public virtual async Task HandleEventAsync(IdentityRoleNameChangedEvent eventData)
// {
// var role = await RoleRepository.FindAsync(eventData.IdentityRole.Id, false);
// if (role == null)
// {
// return;
// }
//
// var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync(RolePermissionValueProvider.ProviderName, eventData.OldName);
// foreach (var permissionGrant in permissionGrantsInRole)
// {
// await PermissionManager.UpdateProviderKeyAsync(permissionGrant, eventData.IdentityRole.Name);
// }
// }
// }
public async Task HandleEventAsync(IdentityRoleNameChangedEto eventData)
{
var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync(RolePermissionValueProvider.ProviderName, eventData.OldName);
foreach (var permissionGrant in permissionGrantsInRole)
{
await PermissionManager.UpdateProviderKeyAsync(permissionGrant, eventData.Name);
}
}
}
}

105
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/Distributed_Role_Change_Events_Test.cs

@ -0,0 +1,105 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Identity;
using Shouldly;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.PermissionManagement;
using Volo.Abp.PermissionManagement.Identity;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.Identity
{
public class Distributed_Role_Change_Events_Test : AbpIdentityDomainTestBase
{
protected readonly IIdentityRoleRepository RoleRepository;
protected readonly IPermissionGrantRepository PermissionGrantRepository;
protected readonly IdentityRoleManager RoleManager;
protected readonly ILookupNormalizer LookupNormalizer;
protected readonly IUnitOfWorkManager UowManager;
protected readonly IDistributedCache<PermissionGrantCacheItem> Cache;
public Distributed_Role_Change_Events_Test()
{
RoleRepository = GetRequiredService<IIdentityRoleRepository>();
;
PermissionGrantRepository = GetRequiredService<IPermissionGrantRepository>();
;
RoleManager = GetRequiredService<IdentityRoleManager>();
;
LookupNormalizer = GetRequiredService<ILookupNormalizer>();
;
UowManager = GetRequiredService<IUnitOfWorkManager>();
Cache = GetRequiredService<IDistributedCache<PermissionGrantCacheItem>>();
}
[Fact]
public void Should_Register_Handler()
{
var x = GetRequiredService<IOptions<AbpDistributedEntityEventOptions>>();
GetRequiredService<IOptions<AbpDistributedEntityEventOptions>>()
.Value
.AutoEventSelectors
.ShouldContain(m => m.Name == "Entity:" + typeof(IdentityRole).FullName);
GetRequiredService<IOptions<AbpDistributedEventBusOptions>>()
.Value
.Handlers
.ShouldContain(h => h == typeof(RoleUpdateEventHandler) || h == typeof(RoleDeletedEventHandler));
}
[Fact]
public async Task Role_Updated_Distributed_Event_Test()
{
var role = await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName("moderator"));
var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name);
permissionGrantsInRole.ShouldNotBeNull();
permissionGrantsInRole.Count.ShouldBeGreaterThan(0);
var count = permissionGrantsInRole.Count;
using (var uow = UowManager.Begin())
{
var identityResult = await RoleManager.SetRoleNameAsync(role, "TestModerator");
identityResult.Succeeded.ShouldBeTrue();
await RoleRepository.UpdateAsync(role);
await uow.CompleteAsync();
}
role = await RoleRepository.GetAsync(role.Id);
role.Name.ShouldBe("TestModerator");
permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name);
permissionGrantsInRole.Count.ShouldBe(count);
}
[Fact]
public async Task Role_Deleted_Distributed_Event_Test()
{
var role = await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName("moderator"));
var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name);
var caches = permissionGrantsInRole.Select(x => new KeyValuePair<string, PermissionGrantCacheItem>(
PermissionGrantCacheItem.CalculateCacheKey(x.Name, x.ProviderName, x.ProviderKey),
new PermissionGrantCacheItem(true))).ToList();
await Cache.SetManyAsync(caches);
using (var uow = UowManager.Begin())
{
await RoleRepository.DeleteAsync(role);
await uow.CompleteAsync();
}
var permissionGrantCaches = await Cache.GetManyAsync(caches.Select(x=>x.Key));
foreach (var cache in permissionGrantCaches)
{
cache.Value.ShouldBeNull();
}
}
}
}

60
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/RoleChangingEvents_Test.cs

@ -1,60 +0,0 @@
using Microsoft.AspNetCore.Identity;
using Shouldly;
using System.Threading.Tasks;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Guids;
using Volo.Abp.PermissionManagement;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.Identity
{
//TODO: This code can not be here!
//https://github.com/abpframework/abp/commit/847f526041145b62376b760776829d5ce257da1c
// public class RoleChangingEvents_Test : AbpIdentityDomainTestBase
// {
// protected readonly IIdentityRoleRepository RoleRepository;
// protected readonly IPermissionGrantRepository PermissionGrantRepository;
// protected readonly IdentityRoleManager RoleManager;
// protected readonly ILookupNormalizer LookupNormalizer;
// protected readonly IGuidGenerator GuidGenerator;
// protected readonly IUnitOfWorkManager UowManager;
//
// public RoleChangingEvents_Test()
// {
// RoleRepository = GetRequiredService<IIdentityRoleRepository>(); ;
// PermissionGrantRepository = GetRequiredService<IPermissionGrantRepository>(); ;
// RoleManager = GetRequiredService<IdentityRoleManager>(); ;
// LookupNormalizer = GetRequiredService<ILookupNormalizer>(); ;
// GuidGenerator = GetRequiredService<IGuidGenerator>();
// UowManager = GetRequiredService<IUnitOfWorkManager>();
// }
//
// [Fact(Skip = "https://github.com/abpframework/abp/actions/runs/454248191")]
// public async Task Role_Update_Event_Test()
// {
// var role = await RoleRepository
// .FindByNormalizedNameAsync(LookupNormalizer.NormalizeName("moderator"))
// ;
//
// var permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name);
// permissionGrantsInRole.ShouldNotBeNull();
// permissionGrantsInRole.Count.ShouldBeGreaterThan(0);
// var count = permissionGrantsInRole.Count;
//
// using (var uow = UowManager.Begin())
// {
// var identityResult = await RoleManager.SetRoleNameAsync(role, "TestModerator");
// identityResult.Succeeded.ShouldBeTrue();
// var xx = await RoleRepository.UpdateAsync(role);
// await uow.CompleteAsync();
// }
//
// role = await RoleRepository.GetAsync(role.Id);
// role.Name.ShouldBe("TestModerator");
//
// permissionGrantsInRole = await PermissionGrantRepository.GetListAsync("R", role.Name);
// permissionGrantsInRole.Count.ShouldBe(count);
// }
// }
}

4
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator.cs

@ -7,7 +7,9 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.PermissionManagement
{
public class PermissionGrantCacheItemInvalidator : ILocalEventHandler<EntityChangedEventData<PermissionGrant>>, ITransientDependency
public class PermissionGrantCacheItemInvalidator :
ILocalEventHandler<EntityChangedEventData<PermissionGrant>>,
ITransientDependency
{
protected ICurrentTenant CurrentTenant { get; }

22
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManager.cs

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
@ -24,6 +25,8 @@ namespace Volo.Abp.PermissionManagement
protected IReadOnlyList<IPermissionManagementProvider> ManagementProviders => _lazyProviders.Value;
protected PermissionManagementOptions Options { get; }
protected IDistributedCache<PermissionGrantCacheItem> Cache { get; }
private readonly Lazy<List<IPermissionManagementProvider>> _lazyProviders;
@ -33,10 +36,12 @@ namespace Volo.Abp.PermissionManagement
IServiceProvider serviceProvider,
IGuidGenerator guidGenerator,
IOptions<PermissionManagementOptions> options,
ICurrentTenant currentTenant)
ICurrentTenant currentTenant,
IDistributedCache<PermissionGrantCacheItem> cache)
{
GuidGenerator = guidGenerator;
CurrentTenant = currentTenant;
Cache = cache;
PermissionGrantRepository = permissionGrantRepository;
PermissionDefinitionManager = permissionDefinitionManager;
Options = options.Value;
@ -104,9 +109,21 @@ namespace Volo.Abp.PermissionManagement
await provider.SetAsync(permissionName, providerKey, isGranted);
}
public virtual async Task<PermissionGrant> UpdateProviderKeyAsync(PermissionGrant permissionGrant, string providerKey)
{
using (CurrentTenant.Change(permissionGrant.TenantId))
{
//Invalidating the cache for the old key
await Cache.RemoveAsync(
PermissionGrantCacheItem.CalculateCacheKey(
permissionGrant.Name,
permissionGrant.ProviderName,
permissionGrant.ProviderKey
)
);
}
permissionGrant.ProviderKey = providerKey;
return await PermissionGrantRepository.UpdateAsync(permissionGrant);
}
@ -114,7 +131,6 @@ namespace Volo.Abp.PermissionManagement
public virtual async Task DeleteAsync(string providerName, string providerKey)
{
var permissionGrants = await PermissionGrantRepository.GetListAsync(providerName, providerKey);
//TODO: Use DeleteManyAsync method
foreach (var permissionGrant in permissionGrants)
{
await PermissionGrantRepository.DeleteAsync(permissionGrant);

Loading…
Cancel
Save