diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs index b1c1df1676..20f39bc55f 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs @@ -98,12 +98,14 @@ public interface IOrganizationUnitRepository : IBasicRepository> GetMemberIdsAsync( Guid id, + bool includeChildren = false, CancellationToken cancellationToken = default ); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs index 4ca6d9fab3..f10113eb05 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs @@ -395,14 +395,14 @@ public class IdentityUserManager : UserManager, IDomainService var sourceOrganization = await OrganizationUnitRepository.GetAsync(sourceOrganizationId, cancellationToken: CancellationToken); Logger.LogDebug($"Remove dynamic claims cache for users of organization: {sourceOrganizationId}"); - var userIdList = await OrganizationUnitRepository.GetMemberIdsAsync(sourceOrganizationId, cancellationToken: CancellationToken); + var userIdList = await OrganizationUnitRepository.GetMemberIdsAsync(sourceOrganizationId, includeChildren: true, cancellationToken: CancellationToken); await DynamicClaimCache.RemoveManyAsync(userIdList.Select(userId => AbpDynamicClaimCacheItem.CalculateCacheKey(userId, sourceOrganization.TenantId)), token: CancellationToken); var targetOrganization = targetOrganizationId.HasValue ? await OrganizationUnitRepository.GetAsync(targetOrganizationId.Value, cancellationToken: CancellationToken) : null; if (targetOrganization != null) { Logger.LogDebug($"Remove dynamic claims cache for users of organization: {targetOrganizationId}"); - userIdList = await OrganizationUnitRepository.GetMemberIdsAsync(targetOrganizationId.Value, cancellationToken: CancellationToken); + userIdList = await OrganizationUnitRepository.GetMemberIdsAsync(targetOrganizationId.Value, includeChildren: true, cancellationToken: CancellationToken); await DynamicClaimCache.RemoveManyAsync(userIdList.Select(userId => AbpDynamicClaimCacheItem.CalculateCacheKey(userId, targetOrganization.TenantId)), token: CancellationToken); } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index 86682b85db..2069a8f69f 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -420,9 +421,20 @@ public class EfCoreIdentityUserRepository : EfCoreRepository().FirstOrDefaultAsync(x => x.Id == sourceOrganizationId, cancellationToken: cancellationToken); + if (sourceOrganization == null) + { + throw new EntityNotFoundException(typeof(OrganizationUnit), sourceOrganizationId); + } + + var allSourceOrganizationIds = await (await GetDbContextAsync()).Set() + .Where(x => x.Code.StartsWith(sourceOrganization.Code)) + .Select(x => x.Id).ToArrayAsync(cancellationToken: cancellationToken); + var users = await (await GetDbContextAsync()).Set().Where(x => x.OrganizationUnitId == targetOrganizationId).Select(x => x.UserId).ToArrayAsync(cancellationToken: cancellationToken); - await (await GetDbContextAsync()).Set().Where(x => x.OrganizationUnitId == sourceOrganizationId && !users.Contains(x.UserId)).ExecuteUpdateAsync(t => t.SetProperty(e => e.OrganizationUnitId, targetOrganizationId), GetCancellationToken(cancellationToken)); - await (await GetDbContextAsync()).Set().Where(x => x.OrganizationUnitId == sourceOrganizationId).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); + + await (await GetDbContextAsync()).Set().Where(x => allSourceOrganizationIds.Contains(x.OrganizationUnitId) && !users.Contains(x.UserId)).ExecuteUpdateAsync(t => t.SetProperty(e => e.OrganizationUnitId, targetOrganizationId), GetCancellationToken(cancellationToken)); + await (await GetDbContextAsync()).Set().Where(x => allSourceOrganizationIds.Contains(x.OrganizationUnitId)).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); } else { diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs index 1af35eafcc..c0d664fbd4 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs @@ -208,24 +208,22 @@ public class EfCoreOrganizationUnitRepository int maxResultCount = int.MaxValue, int skipCount = 0, string filter = null, + bool includeChildren = false, bool includeDetails = false, CancellationToken cancellationToken = default) { - var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, includeChildren); return await query.IncludeDetails(includeDetails).OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityUser.UserName) : sorting) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> GetMemberIdsAsync(Guid id, CancellationToken cancellationToken = default) + public virtual async Task> GetMemberIdsAsync(Guid id, bool includeChildren = false, CancellationToken cancellationToken = default) { - var dbContext = await GetDbContextAsync(); - - return await (from userOu in dbContext.Set() - join user in dbContext.Users on userOu.UserId equals user.Id - where userOu.OrganizationUnitId == id - select user.Id).ToListAsync(cancellationToken); + var organizationUnit = await GetAsync(id, cancellationToken: cancellationToken); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, null, includeChildren); + return await query.Select(x => x.Id).ToListAsync(cancellationToken); } public virtual async Task GetMembersCountAsync( diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index 58486893ec..7cc594c126 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using MongoDB.Driver; using MongoDB.Driver.Linq; +using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; @@ -358,13 +359,30 @@ public class MongoIdentityUserRepository : MongoDbRepository(cancellationToken)) + .Where(x => x.Id == sourceOrganizationId) + .FirstOrDefaultAsync(cancellationToken: cancellationToken); + if (sourceOrganizationUnit == null) + { + throw new EntityNotFoundException(typeof(OrganizationUnit), sourceOrganizationId); + } + + var allSourceOrganizationIds = await (await GetMongoQueryableAsync(cancellationToken)) + .Where(x => x.Code.StartsWith(sourceOrganizationUnit.Code)) + .Select(x => x.Id) + .ToListAsync(cancellationToken: cancellationToken); + var users = await (await GetMongoQueryableAsync(cancellationToken)) - .Where(x => x.OrganizationUnits.Any(r => r.OrganizationUnitId == sourceOrganizationId)) + .Where(x => x.OrganizationUnits.Any(r => allSourceOrganizationIds.Contains(r.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)); foreach (var user in users) { - user.RemoveOrganizationUnit(sourceOrganizationId); + foreach (var organizationId in allSourceOrganizationIds) + { + user.RemoveOrganizationUnit(organizationId); + } + if (targetOrganizationId.HasValue) { user.AddOrganizationUnit(targetOrganizationId.Value); diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs index 5515015438..1b76f81713 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -189,11 +189,12 @@ public class MongoOrganizationUnitRepository int maxResultCount = int.MaxValue, int skipCount = 0, string filter = null, + bool includeChildren = false, bool includeDetails = false, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, false, cancellationToken); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, includeChildren, cancellationToken); return await query .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityUser.UserName) : sorting) .As>() @@ -201,12 +202,12 @@ public class MongoOrganizationUnitRepository .ToListAsync(cancellationToken); } - public virtual async Task> GetMemberIdsAsync(Guid id, CancellationToken cancellationToken = default) + public virtual async Task> GetMemberIdsAsync(Guid id, bool includeChildren = false, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - return await (await GetMongoQueryableAsync(cancellationToken)) - .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == id)).Select(x => x.Id) - .ToListAsync(cancellationToken); + var organizationUnit = await GetAsync(id, cancellationToken: cancellationToken); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, null, includeChildren, cancellationToken); + return await query.Select(x => x.Id).ToListAsync(cancellationToken); } public virtual async Task GetMembersCountAsync(