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 24d3f92774..69376958b7 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 @@ -43,15 +43,15 @@ namespace Volo.Abp.Identity IOrganizationUnitRepository organizationUnitRepository, ISettingProvider settingProvider) : base( - store, - optionsAccessor, - passwordHasher, - userValidators, - passwordValidators, - keyNormalizer, - errors, - services, - logger) + store, + optionsAccessor, + passwordHasher, + userValidators, + passwordValidators, + keyNormalizer, + errors, + services, + logger) { OrganizationUnitRepository = organizationUnitRepository; SettingProvider = settingProvider; @@ -71,7 +71,8 @@ namespace Volo.Abp.Identity return user; } - public virtual async Task SetRolesAsync([NotNull] IdentityUser user, [NotNull] IEnumerable roleNames) + public virtual async Task SetRolesAsync([NotNull] IdentityUser user, + [NotNull] IEnumerable roleNames) { Check.NotNull(user, nameof(user)); Check.NotNull(roleNames, nameof(roleNames)); @@ -101,7 +102,8 @@ namespace Volo.Abp.Identity public virtual async Task IsInOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); + await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, + CancellationTokenProvider.Token); return user.IsInOrganizationUnit(ou.Id); } @@ -110,12 +112,13 @@ namespace Volo.Abp.Identity await AddToOrganizationUnitAsync( await UserRepository.GetAsync(userId, cancellationToken: CancellationToken), await OrganizationUnitRepository.GetAsync(ouId, cancellationToken: CancellationToken) - ); + ); } public virtual async Task AddToOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); + await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, + CancellationTokenProvider.Token); if (user.OrganizationUnits.Any(cou => cou.OrganizationUnitId == ou.Id)) { @@ -125,19 +128,23 @@ namespace Volo.Abp.Identity await CheckMaxUserOrganizationUnitMembershipCountAsync(user.OrganizationUnits.Count + 1); user.AddOrganizationUnit(ou.Id); + await UserRepository.UpdateAsync(user, cancellationToken: CancellationToken); } public virtual async Task RemoveFromOrganizationUnitAsync(Guid userId, Guid ouId) { var user = await UserRepository.GetAsync(userId, cancellationToken: CancellationToken); user.RemoveOrganizationUnit(ouId); + await UserRepository.UpdateAsync(user, cancellationToken: CancellationToken); } public virtual async Task RemoveFromOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); + await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, + CancellationTokenProvider.Token); user.RemoveOrganizationUnit(ou.Id); + await UserRepository.UpdateAsync(user, cancellationToken: CancellationToken); } public virtual async Task SetOrganizationUnitsAsync(Guid userId, params Guid[] organizationUnitIds) @@ -155,7 +162,8 @@ namespace Volo.Abp.Identity await CheckMaxUserOrganizationUnitMembershipCountAsync(organizationUnitIds.Length); - await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); + await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, + CancellationTokenProvider.Token); //Remove from removed OUs foreach (var ouId in user.OrganizationUnits.Select(uou => uou.OrganizationUnitId).ToArray()) @@ -174,11 +182,14 @@ namespace Volo.Abp.Identity user.AddOrganizationUnit(organizationUnitId); } } + + await UserRepository.UpdateAsync(user, cancellationToken: CancellationToken); } private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(int requestedCount) { - var maxCount = await SettingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount); + var maxCount = + await SettingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount); if (requestedCount > maxCount) { throw new BusinessException(IdentityErrorCodes.MaxAllowedOuMembership) @@ -187,9 +198,11 @@ namespace Volo.Abp.Identity } [UnitOfWork] - public virtual async Task> GetOrganizationUnitsAsync(IdentityUser user, bool includeDetails = false) + public virtual async Task> GetOrganizationUnitsAsync(IdentityUser user, + bool includeDetails = false) { - await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); + await UserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, + CancellationTokenProvider.Token); return await OrganizationUnitRepository.GetListAsync( user.OrganizationUnits.Select(t => t.OrganizationUnitId), diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs index 9db3ff4581..4706f92428 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs @@ -54,8 +54,8 @@ namespace Volo.Abp.Identity return OrganizationUnit.CalculateNextCode(lastChild.Code); } - var parentCode = parentId != null - ? await GetCodeOrDefaultAsync(parentId.Value) + var parentCode = parentId != null + ? await GetCodeOrDefaultAsync(parentId.Value) : null; return OrganizationUnit.AppendCode( @@ -174,7 +174,7 @@ namespace Volo.Abp.Identity return Task.FromResult(0); } ou.AddRole(role.Id); - return Task.FromResult(0); + return OrganizationUnitRepository.UpdateAsync(ou); } public virtual async Task RemoveRoleFromOrganizationUnitAsync(Guid roleId, Guid ouId) @@ -188,7 +188,7 @@ namespace Volo.Abp.Identity public virtual Task RemoveRoleFromOrganizationUnitAsync(IdentityRole role, OrganizationUnit organizationUnit) { organizationUnit.RemoveRole(role.Id); - return Task.FromResult(0); + return OrganizationUnitRepository.UpdateAsync(organizationUnit); } } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs index 0e6717f29c..bb8300d449 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs @@ -16,22 +16,24 @@ namespace Volo.Abp.Identity where TStartupModule : IAbpModule { private readonly IOrganizationUnitRepository _organizationUnitRepository; + private readonly IIdentityRoleRepository _identityRoleRepository; private readonly ILookupNormalizer _lookupNormalizer; private readonly IdentityTestData _testData; private readonly IGuidGenerator _guidGenerator; private readonly OrganizationUnitManager _organizationUnitManager; - private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly IdentityUserManager _identityUserManager; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IIdentityUserRepository _identityUserRepository; public OrganizationUnitRepository_Tests() { _organizationUnitRepository = ServiceProvider.GetRequiredService(); + _identityRoleRepository = ServiceProvider.GetRequiredService(); _lookupNormalizer = ServiceProvider.GetRequiredService(); _testData = GetRequiredService(); _guidGenerator = GetRequiredService(); _organizationUnitManager = GetRequiredService(); - _identityRoleRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); _unitOfWorkManager = GetRequiredService(); _identityUserRepository = GetRequiredService(); } @@ -45,19 +47,102 @@ namespace Volo.Abp.Identity [Fact] public async Task GetAllChildrenWithParentCodeAsync() { - (await _organizationUnitRepository.GetAllChildrenWithParentCodeAsync(OrganizationUnit.CreateCode(0), _guidGenerator.Create())).ShouldNotBeNull(); + (await _organizationUnitRepository.GetAllChildrenWithParentCodeAsync(OrganizationUnit.CreateCode(0), + _guidGenerator.Create())).ShouldNotBeNull(); } [Fact] public async Task GetListAsync() { var ouIds = (await _organizationUnitRepository.GetListAsync(includeDetails: true)) - .Select(ou => ou.Id).Take(2); + .Select(ou => ou.Id).Take(2); var ous = await _organizationUnitRepository.GetListAsync(ouIds); ous.Count.ShouldBe(2); ous.ShouldContain(ou => ou.Id == ouIds.First()); } + [Fact] + public async Task AddMemberToOrganizationUnit() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var ou111 = await _organizationUnitRepository.GetAsync( + _lookupNormalizer.NormalizeName("OU111")); + var user = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.NormalizeName("david")); + user.ShouldNotBeNull(); + + user.OrganizationUnits.Count.ShouldBe(1); + await _identityUserManager.AddToOrganizationUnitAsync(user.Id, ou111.Id); + + await uow.CompleteAsync(); + } + + var updatedUser = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.NormalizeName("david")); + updatedUser.OrganizationUnits.Count.ShouldBe(2); + } + + [Fact] + public async Task AddRoleToOrganizationUnit() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var ou111 = await _organizationUnitRepository.GetAsync( + _lookupNormalizer.NormalizeName("OU111")); + ou111.Roles.Count.ShouldBe(2); + var roleSupporter = await _identityRoleRepository.FindByNormalizedNameAsync( + _lookupNormalizer.NormalizeName("supporter")); + + await _organizationUnitManager.AddRoleToOrganizationUnitAsync(roleSupporter.Id, ou111.Id); + await uow.CompleteAsync(); + } + + var ou111Updated = await _organizationUnitRepository.GetAsync( + _lookupNormalizer.NormalizeName("OU111")); + ou111Updated.Roles.Count.ShouldBeGreaterThan(2); + } + + [Fact] + public async Task RemoveRoleFromOrganizationUnit() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var ou111 = await _organizationUnitRepository.GetAsync( + _lookupNormalizer.NormalizeName("OU111")); + ou111.Roles.ShouldContain(q => q.RoleId == _testData.RoleModeratorId); + + await _organizationUnitManager.RemoveRoleFromOrganizationUnitAsync(_testData.RoleModeratorId, ou111.Id); + await uow.CompleteAsync(); + } + + var ou111Updated = await _organizationUnitRepository.GetAsync( + _lookupNormalizer.NormalizeName("OU111")); + ou111Updated.Roles.ShouldNotContain(q => q.RoleId == _testData.RoleModeratorId); + } + + [Fact] + public async Task RemoveOrganizationUnitFromUser() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var ou112 = await _organizationUnitRepository.GetAsync( + _lookupNormalizer.NormalizeName("OU112")); + var user = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.NormalizeName("david")); + + user.OrganizationUnits.Count.ShouldBe(1); + user.OrganizationUnits.ShouldContain(q => q.OrganizationUnitId == ou112.Id); + + await _identityUserManager.RemoveFromOrganizationUnitAsync(user.Id, ou112.Id); + await uow.CompleteAsync(); + } + + var updatedUser = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.NormalizeName("david")); + updatedUser.OrganizationUnits.Count.ShouldBe(0); + } + [Fact] public async Task GetOrganizationUnitAsync() { @@ -79,6 +164,7 @@ namespace Volo.Abp.Identity ou.Roles.ShouldNotBeNull(); ou.Roles.Any().ShouldBeTrue(); } + [Fact] public async Task GetOrganizationUnitRolesAsync() { @@ -95,7 +181,8 @@ namespace Volo.Abp.Identity { OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", includeDetails: true); - var ou111Roles = await _organizationUnitRepository.GetRolesAsync(ou, sorting: "name desc", maxResultCount: 1, includeDetails: true); + var ou111Roles = await _organizationUnitRepository.GetRolesAsync(ou, sorting: "name desc", + maxResultCount: 1, includeDetails: true); ou111Roles.Count.ShouldBe(1); ou111Roles.ShouldContain(n => n.Name == "moderator"); } @@ -105,9 +192,10 @@ namespace Volo.Abp.Identity { OrganizationUnit ou1 = await _organizationUnitRepository.GetAsync("OU111", true); OrganizationUnit ou2 = await _organizationUnitRepository.GetAsync("OU112", true); - var users = await _identityUserRepository.GetUsersInOrganizationsListAsync(new List { ou1.Id, ou2.Id }); + var users = await _identityUserRepository.GetUsersInOrganizationsListAsync(new List {ou1.Id, ou2.Id}); users.Count.ShouldBeGreaterThan(0); } + [Fact] public async Task GetMembersInOrganizationUnitWithParamsAsync() { @@ -147,12 +235,12 @@ namespace Volo.Abp.Identity public async Task GetMembersCountOfOrganizationUnitWithParamsAsync() { OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); - var usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou,"n"); + var usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou, "n"); usersCount.ShouldBeGreaterThan(1); usersCount.ShouldBeLessThanOrEqualTo(5); - usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou,"undefined-username"); + usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou, "undefined-username"); usersCount.ShouldBe(0); }