From 5918032d2d80133b2ed761d29c1afae0ffbc3240 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 24 Jul 2023 11:29:42 +0800 Subject: [PATCH 1/2] Add `UpdateRolesAsync` to `IIdentityUserRepository`. --- .../Abp/Identity/IIdentityUserRepository.cs | 6 ++++ .../EfCoreIdentityUserRepository.cs | 14 ++++++++ .../MongoDB/MongoIdentityUserRepository.cs | 18 ++++++++++ .../Identity/AbpIdentityTestDataBuilder.cs | 23 +++++++------ .../Identity/IdentityUserRepository_Tests.cs | 34 +++++++++++++++++++ 5 files changed, 84 insertions(+), 11 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs index d8b3543703..543bd112eb 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs @@ -131,4 +131,10 @@ public interface IIdentityUserRepository : IBasicRepository bool includeDetails = false, CancellationToken cancellationToken = default ); + + Task UpdateRolesAsync( + Guid sourceRoleId, + Guid? targetRoleId, + CancellationToken cancellationToken = default + ); } 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 2dc1963505..066a2711c3 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 @@ -356,4 +356,18 @@ public class EfCoreIdentityUserRepository : EfCoreRepository ids.Contains(x.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } + + public virtual async Task UpdateRolesAsync(Guid sourceRoleId, Guid? targetRoleId, CancellationToken cancellationToken = default) + { + if (targetRoleId != null) + { + var users = await (await GetDbContextAsync()).Set().Where(x => x.RoleId == targetRoleId).Select(x => x.UserId).ToArrayAsync(cancellationToken: cancellationToken); + await (await GetDbContextAsync()).Set().Where(x => x.RoleId == sourceRoleId && !users.Contains(x.UserId)).ExecuteUpdateAsync(t => t.SetProperty(e => e.RoleId, targetRoleId), GetCancellationToken(cancellationToken)); + await (await GetDbContextAsync()).Set().Where(x => x.RoleId == sourceRoleId).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); + } + else + { + await (await GetDbContextAsync()).Set().Where(x => x.RoleId == sourceRoleId).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); + } + } } 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 552e22afbe..8f6b00966e 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 @@ -324,4 +324,22 @@ public class MongoIdentityUserRepository : MongoDbRepository ids.Contains(x.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } + + public virtual async Task UpdateRolesAsync(Guid sourceRoleId, Guid? targetRoleId, CancellationToken cancellationToken = default) + { + var users = await (await GetMongoQueryableAsync(cancellationToken)) + .Where(x => x.Roles.Any(r => r.RoleId == sourceRoleId)) + .ToListAsync(GetCancellationToken(cancellationToken)); + + foreach (var user in users) + { + user.RemoveRole(sourceRoleId); + if (targetRoleId.HasValue) + { + user.AddRole(targetRoleId.Value); + } + } + + await UpdateManyAsync(users, cancellationToken: cancellationToken); + } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs index dc2b28690a..dbd2e89fbf 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs @@ -147,6 +147,7 @@ public class AbpIdentityTestDataBuilder : ITransientDependency var bob = new IdentityUser(_testData.UserBobId, "bob", "bob@abp.io"); bob.SetIsActive(false); + bob.AddRole(_managerRole.Id); await _userManager.CreateAsync(bob, "1q2w3E*"); } @@ -205,24 +206,24 @@ public class AbpIdentityTestDataBuilder : ITransientDependency private async Task AddUserDelegations() { await _identityUserDelegationRepository.InsertAsync( - new IdentityUserDelegation(_guidGenerator.Create(), + new IdentityUserDelegation(_guidGenerator.Create(), _testData.UserJohnId, - _testData.UserDavidId, - DateTime.Now.AddDays(-2), + _testData.UserDavidId, + DateTime.Now.AddDays(-2), DateTime.Now.AddDays(-1))); - + await _identityUserDelegationRepository.InsertAsync( - new IdentityUserDelegation(_guidGenerator.Create(), + new IdentityUserDelegation(_guidGenerator.Create(), _testData.UserJohnId, - _testData.UserDavidId, - DateTime.Now.AddDays(-1), + _testData.UserDavidId, + DateTime.Now.AddDays(-1), DateTime.Now.AddDays(1))); - + await _identityUserDelegationRepository.InsertAsync( - new IdentityUserDelegation(_guidGenerator.Create(), + new IdentityUserDelegation(_guidGenerator.Create(), _testData.UserNeoId, - _testData.UserDavidId, - DateTime.Now.AddDays(-1), + _testData.UserDavidId, + DateTime.Now.AddDays(-1), DateTime.Now.AddDays(1))); } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs index 3931ecbafe..92b75d6e4c 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs @@ -16,12 +16,14 @@ public abstract class IdentityUserRepository_Tests : AbpIdentity protected IIdentityUserRepository UserRepository { get; } protected ILookupNormalizer LookupNormalizer { get; } protected IOrganizationUnitRepository OrganizationUnitRepository { get; } + protected IdentityTestData TestData { get; } protected IdentityUserRepository_Tests() { UserRepository = ServiceProvider.GetRequiredService(); LookupNormalizer = ServiceProvider.GetRequiredService(); OrganizationUnitRepository = ServiceProvider.GetRequiredService(); + TestData = ServiceProvider.GetRequiredService(); } [Fact] @@ -175,4 +177,36 @@ public abstract class IdentityUserRepository_Tests : AbpIdentity organizationUnit.ShouldNotBeNull(); return organizationUnit; } + + [Fact] + public async Task UpdateRolesAsync() + { + var john = await UserRepository.FindByNormalizedUserNameAsync(LookupNormalizer.NormalizeName("john.nash")); + var roles = await UserRepository.GetRolesAsync(john.Id); + roles.Count.ShouldBe(3); + roles.ShouldContain(r => r.Name == "moderator"); + roles.ShouldContain(r => r.Name == "supporter"); + roles.ShouldContain(r => r.Name == "manager"); + + var supporter = roles.First(x => x.NormalizedName == LookupNormalizer.NormalizeName("supporter")); + var manager = roles.First(x => x.NormalizedName == LookupNormalizer.NormalizeName("manager")); + + await UserRepository.UpdateRolesAsync(supporter.Id, null); + + roles = await UserRepository.GetRolesAsync(john.Id); + roles.Count.ShouldBe(2); + roles.ShouldContain(r => r.Name == "moderator"); + roles.ShouldContain(r => r.Name == "manager"); + + var bob = await UserRepository.FindByNormalizedUserNameAsync(LookupNormalizer.NormalizeName("bob")); + roles = await UserRepository.GetRolesAsync(bob.Id); + roles.Count.ShouldBe(1); + roles.ShouldContain(r => r.Name == "manager"); + + await UserRepository.UpdateRolesAsync(manager.Id, supporter.Id); + + roles = await UserRepository.GetRolesAsync(bob.Id); + roles.Count.ShouldBe(1); + roles.ShouldContain(r => r.Name == "supporter"); + } } From ab8bc47546f9c053a69dda16f30ac63d832bd87e Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 25 Jul 2023 10:26:59 +0800 Subject: [PATCH 2/2] Add `UpdateOrganizationAsync ` to `IIdentityUserRepository`. --- .../Abp/Identity/IIdentityUserRepository.cs | 8 +++- .../EfCoreIdentityUserRepository.cs | 16 ++++++- .../MongoDB/MongoIdentityUserRepository.cs | 20 ++++++++- .../Identity/IdentityUserRepository_Tests.cs | 45 ++++++++++++++++--- 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs index 543bd112eb..29d6af4e3f 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs @@ -132,9 +132,15 @@ public interface IIdentityUserRepository : IBasicRepository CancellationToken cancellationToken = default ); - Task UpdateRolesAsync( + Task UpdateRoleAsync( Guid sourceRoleId, Guid? targetRoleId, CancellationToken cancellationToken = default ); + + Task UpdateOrganizationAsync( + Guid sourceOrganizationId, + Guid? targetOrganizationId, + CancellationToken cancellationToken = default + ); } 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 066a2711c3..8e6e9cba6c 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 @@ -357,7 +357,7 @@ public class EfCoreIdentityUserRepository : EfCoreRepository().Where(x => x.RoleId == sourceRoleId).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); } } + + public virtual async Task UpdateOrganizationAsync(Guid sourceOrganizationId, Guid? targetOrganizationId, CancellationToken cancellationToken = default) + { + if (targetOrganizationId != null) + { + 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)); + } + else + { + await (await GetDbContextAsync()).Set().Where(x => x.OrganizationUnitId == sourceOrganizationId).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); + } + } } 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 8f6b00966e..b37112c317 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 @@ -325,7 +325,7 @@ public class MongoIdentityUserRepository : MongoDbRepository x.Roles.Any(r => r.RoleId == sourceRoleId)) @@ -342,4 +342,22 @@ public class MongoIdentityUserRepository : MongoDbRepository x.OrganizationUnits.Any(r => r.OrganizationUnitId == sourceOrganizationId)) + .ToListAsync(GetCancellationToken(cancellationToken)); + + foreach (var user in users) + { + user.RemoveOrganizationUnit(sourceOrganizationId); + if (targetOrganizationId.HasValue) + { + user.AddOrganizationUnit(targetOrganizationId.Value); + } + } + + await UpdateManyAsync(users, cancellationToken: cancellationToken); + } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs index 92b75d6e4c..cb08fad60d 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityUserRepository_Tests.cs @@ -16,13 +16,15 @@ public abstract class IdentityUserRepository_Tests : AbpIdentity protected IIdentityUserRepository UserRepository { get; } protected ILookupNormalizer LookupNormalizer { get; } protected IOrganizationUnitRepository OrganizationUnitRepository { get; } + protected OrganizationUnitManager OrganizationUnitManager { get; } protected IdentityTestData TestData { get; } protected IdentityUserRepository_Tests() { - UserRepository = ServiceProvider.GetRequiredService(); - LookupNormalizer = ServiceProvider.GetRequiredService(); - OrganizationUnitRepository = ServiceProvider.GetRequiredService(); + UserRepository = GetRequiredService(); + LookupNormalizer = GetRequiredService(); + OrganizationUnitRepository = GetRequiredService(); + OrganizationUnitManager = GetRequiredService();; TestData = ServiceProvider.GetRequiredService(); } @@ -191,7 +193,7 @@ public abstract class IdentityUserRepository_Tests : AbpIdentity var supporter = roles.First(x => x.NormalizedName == LookupNormalizer.NormalizeName("supporter")); var manager = roles.First(x => x.NormalizedName == LookupNormalizer.NormalizeName("manager")); - await UserRepository.UpdateRolesAsync(supporter.Id, null); + await UserRepository.UpdateRoleAsync(supporter.Id, null); roles = await UserRepository.GetRolesAsync(john.Id); roles.Count.ShouldBe(2); @@ -203,10 +205,43 @@ public abstract class IdentityUserRepository_Tests : AbpIdentity roles.Count.ShouldBe(1); roles.ShouldContain(r => r.Name == "manager"); - await UserRepository.UpdateRolesAsync(manager.Id, supporter.Id); + await UserRepository.UpdateRoleAsync(manager.Id, supporter.Id); roles = await UserRepository.GetRolesAsync(bob.Id); roles.Count.ShouldBe(1); roles.ShouldContain(r => r.Name == "supporter"); } + + [Fact] + public async Task UpdateOrganizationAsync() + { + var david = await UserRepository.FindByNormalizedUserNameAsync(LookupNormalizer.NormalizeName("david")); + var organizationUnits = await UserRepository.GetOrganizationUnitsAsync(david.Id); + + var ou111 = await OrganizationUnitRepository.GetAsync("OU111"); + var ou112 = await OrganizationUnitRepository.GetAsync("OU112"); + + organizationUnits.Count.ShouldBe(1); + organizationUnits.ShouldContain(r => r.Id == ou112.Id); + + await UserRepository.UpdateOrganizationAsync(ou112.Id, null); + + organizationUnits = await UserRepository.GetOrganizationUnitsAsync(david.Id); + organizationUnits.Count.ShouldBe(0); + + var ou111Users = await UserRepository.GetUsersInOrganizationUnitAsync(ou111.Id); + ou111Users.Count.ShouldBe(2); + ou111Users.ShouldContain(x => x.UserName == "john.nash"); + ou111Users.ShouldContain(x => x.UserName == "neo"); + + var ou112Users = await UserRepository.GetUsersInOrganizationUnitAsync(ou112.Id); + ou112Users.Count.ShouldBe(0); + + await UserRepository.UpdateOrganizationAsync(ou111.Id, ou112.Id); + + ou112Users = await UserRepository.GetUsersInOrganizationUnitAsync(ou112.Id); + ou112Users.Count.ShouldBe(2); + ou112Users.ShouldContain(x => x.UserName == "john.nash"); + ou112Users.ShouldContain(x => x.UserName == "neo"); + } }