From a75459d480b55b34bb348608b40fbdaa8b45a4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 21:48:02 +0300 Subject: [PATCH] Add tests and fix mongodb repo. --- .../Abp/Identity/IdentityUserAppService.cs | 2 + .../Volo/Abp/Identity/IdentityUserStore.cs | 49 ++++++++++--------- .../MongoDB/MongoIdentityUserRepository.cs | 21 ++++++-- .../Identity/IdentityUserAppService_Tests.cs | 3 +- .../Identity/AbpIdentityTestDataBuilder.cs | 17 ++++--- 5 files changed, 57 insertions(+), 35 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs index 9d231b18d1..166d71fa5e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs @@ -45,6 +45,8 @@ namespace Volo.Abp.Identity [Authorize(IdentityPermissions.Users.Default)] public virtual async Task> GetRolesAsync(Guid id) { + //TODO: Should also include roles of the related OUs. + var roles = await UserRepository.GetRolesAsync(id); return new ListResultDto( diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs index eb07b0ed41..81269adf5a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs @@ -53,6 +53,7 @@ namespace Volo.Abp.Identity protected IIdentityRoleRepository RoleRepository { get; } protected IGuidGenerator GuidGenerator { get; } protected ILogger Logger { get; } + protected ILookupNormalizer LookupNormalizer { get; } protected IIdentityUserRepository UserRepository { get; } public IdentityUserStore( @@ -60,12 +61,14 @@ namespace Volo.Abp.Identity IIdentityRoleRepository roleRepository, IGuidGenerator guidGenerator, ILogger logger, + ILookupNormalizer lookupNormalizer, IdentityErrorDescriber describer = null) { UserRepository = userRepository; RoleRepository = roleRepository; GuidGenerator = guidGenerator; Logger = logger; + LookupNormalizer = lookupNormalizer; ErrorDescriber = describer ?? new IdentityErrorDescriber(); } @@ -313,13 +316,17 @@ namespace Volo.Abp.Identity Check.NotNull(user, nameof(user)); Check.NotNull(normalizedRoleName, nameof(normalizedRoleName)); - var role = await RoleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken); + if (await IsInRoleAsync(user, normalizedRoleName, cancellationToken)) + { + return; + } + var role = await RoleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken); if (role == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Role {0} does not exist!", normalizedRoleName)); } - + await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken); user.AddRole(role.Id); @@ -337,11 +344,7 @@ namespace Volo.Abp.Identity cancellationToken.ThrowIfCancellationRequested(); Check.NotNull(user, nameof(user)); - - if (string.IsNullOrWhiteSpace(normalizedRoleName)) - { - throw new ArgumentException(nameof(normalizedRoleName) + " can not be null or whitespace"); - } + Check.NotNullOrWhiteSpace(normalizedRoleName, nameof(normalizedRoleName)); var role = await RoleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken); if (role == null) @@ -366,8 +369,11 @@ namespace Volo.Abp.Identity Check.NotNull(user, nameof(user)); - var userRoles = await UserRepository.GetRoleNamesAsync(user.Id, cancellationToken: cancellationToken); - var userOrganizationUnitRoles = await UserRepository.GetRoleNamesInOrganizationUnitAsync(user.Id, cancellationToken: cancellationToken); + var userRoles = await UserRepository + .GetRoleNamesAsync(user.Id, cancellationToken: cancellationToken); + + var userOrganizationUnitRoles = await UserRepository + .GetRoleNamesInOrganizationUnitAsync(user.Id, cancellationToken: cancellationToken); return userRoles.Union(userOrganizationUnitRoles).ToList(); } @@ -380,26 +386,21 @@ namespace Volo.Abp.Identity /// The used to propagate notifications that the operation should be canceled. /// A containing a flag indicating if the specified user is a member of the given group. If the /// user is a member of the group the returned value with be true, otherwise it will be false. - public virtual async Task IsInRoleAsync([NotNull] IdentityUser user, [NotNull] string normalizedRoleName, CancellationToken cancellationToken = default) + public virtual async Task IsInRoleAsync( + [NotNull] IdentityUser user, + [NotNull] string normalizedRoleName, + CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); - + Check.NotNull(user, nameof(user)); + Check.NotNullOrWhiteSpace(normalizedRoleName, nameof(normalizedRoleName)); - if (string.IsNullOrWhiteSpace(normalizedRoleName)) - { - throw new ArgumentException(nameof(normalizedRoleName) + " can not be null or whitespace"); - } - - var role = await RoleRepository.FindByNormalizedNameAsync(normalizedRoleName, cancellationToken: cancellationToken); - if (role == null) - { - return false; - } - - await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, cancellationToken); + var roles = await GetRolesAsync(user, cancellationToken); - return user.IsInRole(role.Id); + return roles + .Select(r => LookupNormalizer.NormalizeName(r)) + .Contains(normalizedRoleName); } /// 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 6c23f2ad3b..077586572b 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 @@ -49,10 +49,23 @@ namespace Volo.Abp.Identity.MongoDB CancellationToken cancellationToken = default) { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); - var organizationUnitIds = user.OrganizationUnits.Select(r => r.OrganizationUnitId); - var organizationUnits = DbContext.OrganizationUnits.AsQueryable().Where(ou => organizationUnitIds.Contains(ou.Id)); - var roleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)); - return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)); + + var organizationUnitIds = user.OrganizationUnits + .Select(r => r.OrganizationUnitId) + .ToArray(); + + var organizationUnits = DbContext.OrganizationUnits + .AsQueryable() + .Where(ou => organizationUnitIds.Contains(ou.Id)) + .ToArray(); + + var roleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); + + return await DbContext.Roles //TODO: Such usage suppress filters! + .AsQueryable() + .Where(r => roleIds.Contains(r.Id)) + .Select(r => r.Name) + .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByLoginAsync( diff --git a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs index 6fbf23ed73..24807de7b7 100644 --- a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserAppService_Tests.cs @@ -189,9 +189,10 @@ namespace Volo.Abp.Identity //Assert - result.Items.Count.ShouldBe(2); + result.Items.Count.ShouldBe(3); result.Items.ShouldContain(r => r.Name == "moderator"); result.Items.ShouldContain(r => r.Name == "supporter"); + result.Items.ShouldContain(r => r.Name == "manager"); } [Fact] 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 bd06c55d6c..dec33c0bcd 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 @@ -20,8 +20,9 @@ namespace Volo.Abp.Identity private readonly OrganizationUnitManager _organizationUnitManager; private IdentityRole _adminRole; - private IdentityRole _moderator; + private IdentityRole _moderatorRole; private IdentityRole _supporterRole; + private IdentityRole _managerRole; private OrganizationUnit _ou111; private OrganizationUnit _ou112; @@ -57,12 +58,15 @@ namespace Volo.Abp.Identity { _adminRole = await _roleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")); - _moderator = new IdentityRole(_testData.RoleModeratorId, "moderator"); - _moderator.AddClaim(_guidGenerator, new Claim("test-claim", "test-value")); - await _roleRepository.InsertAsync(_moderator); + _moderatorRole = new IdentityRole(_testData.RoleModeratorId, "moderator"); + _moderatorRole.AddClaim(_guidGenerator, new Claim("test-claim", "test-value")); + await _roleRepository.InsertAsync(_moderatorRole); _supporterRole = new IdentityRole(_guidGenerator.Create(), "supporter"); await _roleRepository.InsertAsync(_supporterRole); + + _managerRole = new IdentityRole(_guidGenerator.Create(), "manager"); + await _roleRepository.InsertAsync(_managerRole); } /* Creates OU tree as shown below: @@ -86,7 +90,8 @@ namespace Volo.Abp.Identity _ou111 = new OrganizationUnit(null, "OU111", ou11.Id); _ou111.Code = OrganizationUnit.CreateCode(1, 1, 1); - _ou111.AddRole(_moderator.Id); + _ou111.AddRole(_moderatorRole.Id); + _ou111.AddRole(_managerRole.Id); await _organizationUnitRepository.InsertAsync(_ou111); } @@ -98,7 +103,7 @@ namespace Volo.Abp.Identity await _userRepository.InsertAsync(adminUser); var john = new IdentityUser(_testData.UserJohnId, "john.nash", "john.nash@abp.io"); - john.AddRole(_moderator.Id); + john.AddRole(_moderatorRole.Id); john.AddRole(_supporterRole.Id); john.AddOrganizationUnit(_ou111.Id); john.AddOrganizationUnit(_ou112.Id);