Browse Source

Remove `dynamic claim cache` when deleting organization's role.

pull/18204/head
maliming 2 years ago
parent
commit
ee3377adf5
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 6
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs
  2. 11
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleManager.cs
  3. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs
  4. 15
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs
  5. 10
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs
  6. 59
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor_Tests.cs
  7. 6
      modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs
  8. 17
      modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs

6
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs

@ -41,6 +41,12 @@ public interface IOrganizationUnitRepository : IBasicRepository<OrganizationUnit
CancellationToken cancellationToken = default
);
Task<List<OrganizationUnit>> GetListByRoleAsync(
Guid roleId,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<IdentityRole>> GetRolesAsync(
OrganizationUnit organizationUnit,
string sorting = null,

11
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRoleManager.cs

@ -22,6 +22,8 @@ public class IdentityRoleManager : RoleManager<IdentityRole>, IDomainService
protected IStringLocalizer<IdentityResource> Localizer { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected IIdentityUserRepository UserRepository { get; }
protected IOrganizationUnitRepository OrganizationUnitRepository { get; }
protected OrganizationUnitManager OrganizationUnitManager { get; }
protected IDistributedCache<AbpDynamicClaimCacheItem> DynamicClaimCache { get; }
public IdentityRoleManager(
@ -33,6 +35,8 @@ public class IdentityRoleManager : RoleManager<IdentityRole>, IDomainService
IStringLocalizer<IdentityResource> localizer,
ICancellationTokenProvider cancellationTokenProvider,
IIdentityUserRepository userRepository,
IOrganizationUnitRepository organizationUnitRepository,
OrganizationUnitManager organizationUnitManager,
IDistributedCache<AbpDynamicClaimCacheItem> dynamicClaimCache)
: base(
store,
@ -44,6 +48,8 @@ public class IdentityRoleManager : RoleManager<IdentityRole>, IDomainService
Localizer = localizer;
CancellationTokenProvider = cancellationTokenProvider;
UserRepository = userRepository;
OrganizationUnitRepository = organizationUnitRepository;
OrganizationUnitManager = organizationUnitManager;
DynamicClaimCache = dynamicClaimCache;
}
@ -84,11 +90,16 @@ public class IdentityRoleManager : RoleManager<IdentityRole>, IDomainService
}
var userIdList = await UserRepository.GetUserIdListByRoleIdAsync(role.Id, cancellationToken: CancellationToken);
var orgList = await OrganizationUnitRepository.GetListByRoleAsync(role.Id, includeDetails: false, cancellationToken: CancellationToken);
var result = await base.DeleteAsync(role);
if (result.Succeeded)
{
Logger.LogDebug($"Remove dynamic claims cache for users of role: {role.Id}");
await DynamicClaimCache.RemoveManyAsync(userIdList.Select(userId => AbpDynamicClaimCacheItem.CalculateCacheKey(userId, role.TenantId)), token: CancellationToken);
foreach (var organizationUnit in orgList)
{
await OrganizationUnitManager.RemoveDynamicClaimCacheAsync(organizationUnit);
}
}
return result;

2
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs

@ -205,7 +205,7 @@ public class OrganizationUnitManager : DomainService
await OrganizationUnitRepository.UpdateAsync(organizationUnit);
}
protected virtual async Task RemoveDynamicClaimCacheAsync(OrganizationUnit organizationUnit)
public virtual async Task RemoveDynamicClaimCacheAsync(OrganizationUnit organizationUnit)
{
Logger.LogDebug($"Remove dynamic claims cache for users of organization: {organizationUnit.Id}");
var userIds = await OrganizationUnitRepository.GetMemberIdsAsync(organizationUnit.Id);

15
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs

@ -69,6 +69,21 @@ public class EfCoreOrganizationUnitRepository
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<OrganizationUnit>> GetListByRoleAsync(
Guid roleId,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var dbContext = await GetDbContextAsync();
var query = from organizationRole in dbContext.Set<OrganizationUnitRole>()
join organizationUnit in dbContext.OrganizationUnits.IncludeDetails(includeDetails) on organizationRole.OrganizationUnitId equals organizationUnit.Id
where organizationRole.RoleId == roleId
select organizationUnit;
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<OrganizationUnit> GetAsync(
string displayName,
bool includeDetails = true,

10
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs

@ -53,6 +53,16 @@ public class MongoOrganizationUnitRepository
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<OrganizationUnit>> GetListByRoleAsync(
Guid roleId,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(cancellationToken))
.Where(x => x.Roles.Any(r => r.RoleId == roleId))
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<OrganizationUnit>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,

59
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributor_Tests.cs

@ -209,4 +209,63 @@ public class IdentityDynamicClaimsPrincipalContributor_Tests : AbpIdentityDomain
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "moderator");
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "manager"); //manager role from OU111 is deleted.
}
[Fact]
public async Task Should_Get_Correct_Claims_After_User_Organization_Role_Or_Member_Changed()
{
ClaimsPrincipal claimsPrincipal = null;
await UsingUowAsync(async () =>
{
var user = await _identityUserManager.GetByIdAsync(_testData.UserBobId);
user.ShouldNotBeNull();
claimsPrincipal = await _abpUserClaimsPrincipalFactory.CreateAsync(user);
claimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "supporter");
claimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "moderator");
claimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "manager");
var dynamicClaimsPrincipal = await _abpClaimsPrincipalFactory.CreateDynamicAsync(claimsPrincipal);
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "supporter");
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "moderator");
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "manager");
var ou = await _organizationUnitRepository.GetAsync("OU111", true);
ou.ShouldNotBeNull();
ou.Roles.Count.ShouldBe(2);
ou.Roles.ShouldContain(x => x.RoleId == _testData.RoleModeratorId);
ou.Roles.ShouldContain(x => x.RoleId == _testData.RoleManagerId);
ou.AddRole(_testData.RoleSaleId);
await _identityUserManager.AddToOrganizationUnitAsync(user, ou);
await _organizationUnitManager.UpdateAsync(ou);
});
var dynamicClaimsPrincipal = await _abpClaimsPrincipalFactory.CreateDynamicAsync(claimsPrincipal);
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "supporter");
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "moderator");
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "manager");
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "sale");
await UsingUowAsync(async () =>
{
var saleRole = await _identityRoleRepository.GetAsync(_testData.RoleSaleId);
await _identityRoleManager.DeleteAsync(saleRole);
});
dynamicClaimsPrincipal = await _abpClaimsPrincipalFactory.CreateDynamicAsync(claimsPrincipal);
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "supporter");
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "moderator");
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "manager");
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "sale");
await UsingUowAsync(async () =>
{
var user = await _identityUserManager.GetByIdAsync(_testData.UserBobId);
user.ShouldNotBeNull();
var ou = await _organizationUnitRepository.GetAsync("OU111", true);
ou.ShouldNotBeNull();
await _identityUserManager.RemoveFromOrganizationUnitAsync(user.Id, ou.Id);
});
dynamicClaimsPrincipal = await _abpClaimsPrincipalFactory.CreateDynamicAsync(claimsPrincipal);
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "supporter");
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "moderator");
dynamicClaimsPrincipal.Claims.ShouldContain(x => x.Type == ClaimTypes.Role && x.Value == "manager");
dynamicClaimsPrincipal.Claims.ShouldNotContain(x => x.Type == ClaimTypes.Role && x.Value == "sale");
}
}

6
modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs

@ -114,6 +114,12 @@ public class AbpIdentityTestDataBuilder : ITransientDependency
_ou111.AddRole(_moderatorRole.Id);
_ou111.AddRole(_managerRole.Id);
await _organizationUnitRepository.InsertAsync(_ou111);
var _ou222 = new OrganizationUnit(_guidGenerator.Create(), "OU222");
_ou222.Code = OrganizationUnit.CreateCode(1, 1, 1);
_ou222.AddRole(_moderatorRole.Id);
_ou222.AddRole(_managerRole.Id);
await _organizationUnitRepository.InsertAsync(_ou222);
}
private async Task AddUsers()

17
modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs

@ -66,6 +66,23 @@ public abstract class OrganizationUnitRepository_Tests<TStartupModule> : AbpIden
ous.ShouldContain(ou => ou.Id == ouIds.First());
}
[Fact]
public async Task GetListByRoleAsync()
{
var ous = await _organizationUnitRepository.GetListByRoleAsync(_testData.RoleManagerId);
ous.Count.ShouldBe(2);
ous.ShouldContain(ou => ou.DisplayName == "OU111");
ous.ShouldContain(ou => ou.DisplayName == "OU222");
ous = await _organizationUnitRepository.GetListByRoleAsync(_testData.RoleModeratorId);
ous.Count.ShouldBe(2);
ous.ShouldContain(ou => ou.DisplayName == "OU111");
ous.ShouldContain(ou => ou.DisplayName == "OU222");
ous = await _organizationUnitRepository.GetListByRoleAsync(_testData.RoleSaleId);
ous.Count.ShouldBe(0);
}
[Fact]
public async Task AddMemberToOrganizationUnit()
{

Loading…
Cancel
Save