From 286d7909b7160cf752edd205d0b2c23b1dc89c80 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Thu, 2 Jan 2020 22:27:18 +0300 Subject: [PATCH 01/35] domain logic for organization unit --- .../Volo/Abp/Identity/Localization/en.json | 1 + .../Volo/Abp/Identity/Localization/pt-BR.json | 1 + .../Volo/Abp/Identity/Localization/tr.json | 1 + .../Abp/Identity/Localization/zh-Hans.json | 1 + .../Organizations/OrganizationUnitConsts.cs | 25 +++ .../IOrganizationUnitRepository.cs | 14 ++ .../Organizations/OrganizationUnit.cs | 178 ++++++++++++++++++ .../Organizations/OrganizationUnitManager.cs | 138 ++++++++++++++ .../Organizations/OrganizationUnitRole.cs | 54 ++++++ .../Organizations/OrganizationUnitUser.cs | 54 ++++++ ...lo.Abp.Identity.EntityFrameworkCore.csproj | 2 +- .../EfCoreOrganizationUnitRepository.cs | 32 ++++ .../EntityFrameworkCore/IIdentityDbContext.cs | 9 +- .../EntityFrameworkCore/IdentityDbContext.cs | 7 + 14 files changed, 515 insertions(+), 2 deletions(-) create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs create mode 100644 modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json index e7a038fd57..87c599ea4f 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json @@ -63,6 +63,7 @@ "Identity.PasswordConfirmationFailed": "Password does not match the confirm password.", "Identity.StaticRoleRenamingErrorMessage": "Static roles can not be renamed.", "Identity.StaticRoleDeletionErrorMessage": "Static roles can not be deleted.", + "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "There is already an organization unit with name {0}. Two units with same name can not be created in same level.", "Volo.Abp.Identity:010001": "You can not delete your own account!", "Permission:IdentityManagement": "Identity management", "Permission:RoleManagement": "Role management", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json index 4df719fffe..1dda38b2a5 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json @@ -63,6 +63,7 @@ "Identity.PasswordConfirmationFailed": "A senha não confere com a confirmação de senha.", "Identity.StaticRoleRenamingErrorMessage": "Perfis estáticos não podem ser renomeados.", "Identity.StaticRoleDeletionErrorMessage": "Perfis estáticos não podem ser excluídos.", + "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "Já existe uma unidade organizacional com o nome {0}. Duas unidades com o mesmo nome não pode ser criada no mesmo nível.", "Volo.Abp.Identity:010001": "Você não pode deletar sua própria conta!", "Permission:IdentityManagement": "Acessos", "Permission:RoleManagement": "Perfis", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json index 8b8b936c0a..cfc58d4dad 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json @@ -63,6 +63,7 @@ "Identity.UserNameNotFound": "{0} kullanıcısı bulunamadı.", "Identity.UserNotInRole": "Kullanıcı '{0}' rolünde değil.", "Identity.PasswordConfirmationFailed": "Yeni şifre ile onay şifresi uyuşmuyor.", + "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "{0} isminde bir birim zaten var. Aynı seviyede aynı isimli iki birim olamaz.", "Volo.Abp.Identity:010001": "Kendi hesabınızı silemezsiniz!", "Permission:IdentityManagement": "Kimlik yönetimi", "Permission:RoleManagement": "Rol yönetimi", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json index f57029eb9e..b80c820f98 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json @@ -63,6 +63,7 @@ "Identity.PasswordConfirmationFailed": "密码或确认密码不一致.", "Identity.StaticRoleRenamingErrorMessage": "无法重命名静态角色.", "Identity.StaticRoleDeletionErrorMessage": "无法删除静态角色.", + "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "已存在名为 {0} 的组织单位. 无法在同一级别创建相同名称的组织单位.", "Volo.Abp.Identity:010001": "您无法删除自己的帐户!", "Permission:IdentityManagement": "身份标识管理", "Permission:RoleManagement": "角色管理", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs new file mode 100644 index 0000000000..a704e6bb05 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs @@ -0,0 +1,25 @@ +namespace Volo.Abp.Identity.Organizations +{ + public class OrganizationUnitConsts + { + /// + /// Maximum length of the property. + /// + public const int MaxDisplayNameLength = 128; + + /// + /// Maximum depth of an OU hierarchy. + /// + public const int MaxDepth = 16; + + /// + /// Length of a code unit between dots. + /// + public const int CodeUnitLength = 5; + + /// + /// Maximum length of the property. + /// + public const int MaxCodeLength = MaxDepth * (CodeUnitLength + 1) - 1; + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs new file mode 100644 index 0000000000..0136d9ef4c --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace Volo.Abp.Identity.Organizations +{ + public interface IOrganizationUnitRepository : IBasicRepository + { + Task> GetChildrenAsync(Guid? parentId); + + Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId); + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs new file mode 100644 index 0000000000..0955aa248a --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Identity.Organizations +{ + /// + /// Represents an organization unit (OU). + /// + public class OrganizationUnit : FullAuditedAggregateRoot, IMultiTenant + { + public virtual Guid? TenantId { get; protected set; } + + /// + /// Parent Id. + /// Null, if this OU is root. + /// + public virtual Guid? ParentId { get; set; } + + /// + /// Hierarchical Code of this organization unit. + /// Example: "00001.00042.00005". + /// This is a unique code for a Tenant. + /// It's changeable if OU hierarch is changed. + /// + public virtual string Code { get; set; } + + /// + /// Display name of this role. + /// + public virtual string DisplayName { get; set; } + + /// + /// Children of this OU. + /// + public virtual ICollection Children { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public OrganizationUnit() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// Tenant's Id or null for host. + /// Display name. + /// Parent's Id or null if OU is a root. + public OrganizationUnit(Guid? tenantId, string displayName, Guid? parentId = null) + { + TenantId = tenantId; + DisplayName = displayName; + ParentId = parentId; + } + + /// + /// Creates code for given numbers. + /// Example: if numbers are 4,2 then returns "00004.00002"; + /// + /// Numbers + public static string CreateCode(params int[] numbers) + { + if (numbers.IsNullOrEmpty()) + { + return null; + } + + return numbers.Select(number => number.ToString(new string('0', OrganizationUnitConsts.CodeUnitLength))).JoinAsString("."); + } + + /// + /// Appends a child code to a parent code. + /// Example: if parentCode = "00001", childCode = "00042" then returns "00001.00042". + /// + /// Parent code. Can be null or empty if parent is a root. + /// Child code. + public static string AppendCode(string parentCode, string childCode) + { + if (childCode.IsNullOrEmpty()) + { + throw new ArgumentNullException(nameof(childCode), "childCode can not be null or empty."); + } + + if (parentCode.IsNullOrEmpty()) + { + return childCode; + } + + return parentCode + "." + childCode; + } + + /// + /// Gets relative code to the parent. + /// Example: if code = "00019.00055.00001" and parentCode = "00019" then returns "00055.00001". + /// + /// The code. + /// The parent code. + public static string GetRelativeCode(string code, string parentCode) + { + if (code.IsNullOrEmpty()) + { + throw new ArgumentNullException(nameof(code), "code can not be null or empty."); + } + + if (parentCode.IsNullOrEmpty()) + { + return code; + } + + if (code.Length == parentCode.Length) + { + return null; + } + + return code.Substring(parentCode.Length + 1); + } + + /// + /// Calculates next code for given code. + /// Example: if code = "00019.00055.00001" returns "00019.00055.00002". + /// + /// The code. + public static string CalculateNextCode(string code) + { + if (code.IsNullOrEmpty()) + { + throw new ArgumentNullException(nameof(code), "code can not be null or empty."); + } + + var parentCode = GetParentCode(code); + var lastUnitCode = GetLastUnitCode(code); + + return AppendCode(parentCode, CreateCode(Convert.ToInt32(lastUnitCode) + 1)); + } + + /// + /// Gets the last unit code. + /// Example: if code = "00019.00055.00001" returns "00001". + /// + /// The code. + public static string GetLastUnitCode(string code) + { + if (code.IsNullOrEmpty()) + { + throw new ArgumentNullException(nameof(code), "code can not be null or empty."); + } + + var splittedCode = code.Split('.'); + return splittedCode[splittedCode.Length - 1]; + } + + /// + /// Gets parent code. + /// Example: if code = "00019.00055.00001" returns "00019.00055". + /// + /// The code. + public static string GetParentCode(string code) + { + if (code.IsNullOrEmpty()) + { + throw new ArgumentNullException(nameof(code), "code can not be null or empty."); + } + + var splittedCode = code.Split('.'); + if (splittedCode.Length == 1) + { + return null; + } + + return splittedCode.Take(splittedCode.Length - 1).JoinAsString("."); + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs new file mode 100644 index 0000000000..88aad4d66a --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -0,0 +1,138 @@ +using Microsoft.Extensions.Localization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Domain.Services; +using Volo.Abp.Identity.Localization; +using Volo.Abp.Uow; + +namespace Volo.Abp.Identity.Organizations +{ + /// + /// Performs domain logic for Organization Units. + /// + public class OrganizationUnitManager : DomainService + { + protected IOrganizationUnitRepository _organizationUnitRepository { get; private set; } + + private readonly IStringLocalizer _localizer; + + public OrganizationUnitManager( + IOrganizationUnitRepository organizationUnitRepository, + IStringLocalizer localizer) + { + _organizationUnitRepository = organizationUnitRepository; + _localizer = localizer; + } + + [UnitOfWork] + public virtual async Task CreateAsync(OrganizationUnit organizationUnit) + { + organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId); + await ValidateOrganizationUnitAsync(organizationUnit); + await _organizationUnitRepository.InsertAsync(organizationUnit); + } + + public virtual async Task UpdateAsync(OrganizationUnit organizationUnit) + { + await ValidateOrganizationUnitAsync(organizationUnit); + await _organizationUnitRepository.UpdateAsync(organizationUnit); + } + + public virtual async Task GetNextChildCodeAsync(Guid? parentId) + { + var lastChild = await GetLastChildOrNullAsync(parentId); + if (lastChild == null) + { + var parentCode = parentId != null ? await GetCodeOrDefaultAsync(parentId.Value) : null; + return OrganizationUnit.AppendCode(parentCode, OrganizationUnit.CreateCode(1)); + } + + return OrganizationUnit.CalculateNextCode(lastChild.Code); + } + + public virtual async Task GetLastChildOrNullAsync(Guid? parentId) + { + var children = await _organizationUnitRepository.GetChildrenAsync(parentId); + return children.OrderBy(c => c.Code).LastOrDefault(); + } + + [UnitOfWork] + public virtual async Task DeleteAsync(Guid id) + { + var children = await FindChildrenAsync(id, true); + + foreach (var child in children) + { + await _organizationUnitRepository.DeleteAsync(child); + } + + await _organizationUnitRepository.DeleteAsync(id); + } + + [UnitOfWork] + public virtual async Task MoveAsync(Guid id, Guid? parentId) + { + var organizationUnit = await _organizationUnitRepository.GetAsync(id); + if (organizationUnit.ParentId == parentId) + { + return; + } + + //Should find children before Code change + var children = await FindChildrenAsync(id, true); + + //Store old code of OU + var oldCode = organizationUnit.Code; + + //Move OU + organizationUnit.Code = await GetNextChildCodeAsync(parentId); + organizationUnit.ParentId = parentId; + + await ValidateOrganizationUnitAsync(organizationUnit); + + //Update Children Codes + foreach (var child in children) + { + child.Code = OrganizationUnit.AppendCode(organizationUnit.Code, OrganizationUnit.GetRelativeCode(child.Code, oldCode)); + } + } + + public virtual async Task GetCodeOrDefaultAsync(Guid id) + { + var ou = await _organizationUnitRepository.GetAsync(id); + return ou?.Code; + } + + protected virtual async Task ValidateOrganizationUnitAsync(OrganizationUnit organizationUnit) + { + var siblings = (await FindChildrenAsync(organizationUnit.ParentId)) + .Where(ou => ou.Id != organizationUnit.Id) + .ToList(); + + if (siblings.Any(ou => ou.DisplayName == organizationUnit.DisplayName)) + { + throw new UserFriendlyException(_localizer["OrganizationUnitDuplicateDisplayNameWarning", organizationUnit.DisplayName]); + } + } + + public async Task> FindChildrenAsync(Guid? parentId, bool recursive = false) + { + if (!recursive) + { + return await _organizationUnitRepository.GetChildrenAsync(parentId); + } + + if (!parentId.HasValue) + { + return await _organizationUnitRepository.GetListAsync(); + } + + var code = await GetCodeOrDefaultAsync(parentId.Value); + + return await _organizationUnitRepository.GetAllChildrenWithParentCodeAsync(code, parentId); + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs new file mode 100644 index 0000000000..cd9d9d3ac4 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs @@ -0,0 +1,54 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Identity.Organizations +{ + /// + /// Represents membership of a User to an OU. + /// + public class OrganizationUnitRole : CreationAuditedEntity, IMultiTenant, ISoftDelete + { + /// + /// TenantId of this entity. + /// + public virtual Guid? TenantId { get; protected set; } + + /// + /// Id of the Role. + /// + public virtual Guid RoleId { get; set; } + + /// + /// Id of the . + /// + public virtual Guid OrganizationUnitId { get; set; } + + /// + /// Specifies if the organization is soft deleted or not. + /// + public virtual bool IsDeleted { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public OrganizationUnitRole() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// TenantId + /// Id of the User. + /// Id of the . + public OrganizationUnitRole(Guid? tenantId, Guid roleId, Guid organizationUnitId) + { + TenantId = tenantId; + RoleId = roleId; + OrganizationUnitId = organizationUnitId; + } + + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs new file mode 100644 index 0000000000..3ab7a1c711 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs @@ -0,0 +1,54 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Identity.Organizations +{ + /// + /// Represents membership of a User to an OU. + /// + public class OrganizationUnitUser : CreationAuditedEntity, IMultiTenant, ISoftDelete + { + + /// + /// TenantId of this entity. + /// + public virtual Guid? TenantId { get; set; } + + /// + /// Id of the User. + /// + public virtual Guid UserId { get; set; } + + /// + /// Id of the . + /// + public virtual Guid OrganizationUnitId { get; set; } + + /// + /// Specifies if the organization is soft deleted or not. + /// + public virtual bool IsDeleted { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public OrganizationUnitUser() + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// TenantId + /// Id of the User. + /// Id of the . + public OrganizationUnitUser(Guid? tenantId, Guid userId, Guid organizationUnitId) + { + TenantId = tenantId; + UserId = userId; + OrganizationUnitId = organizationUnitId; + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj index 945905d75f..994a3a3985 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj @@ -14,8 +14,8 @@ - + 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 new file mode 100644 index 0000000000..f24adad3f7 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Identity.Organizations; + +namespace Volo.Abp.Identity.EntityFrameworkCore +{ + public class EfCoreOrganizationUnitRepository : EfCoreRepository, IOrganizationUnitRepository + { + public EfCoreOrganizationUnitRepository(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task> GetChildrenAsync(Guid? parentId) + { + return await DbSet.Where(x => x.ParentId == parentId) + .ToListAsync(); + } + + public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId) + { + return await DbSet.Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) + .ToListAsync(); + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs index d3c560dca2..b5d7007767 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { @@ -12,5 +13,11 @@ namespace Volo.Abp.Identity.EntityFrameworkCore DbSet Roles { get; set; } DbSet ClaimTypes { get; set; } + + DbSet OrganizationUnits { get; set; } + + DbSet OrganizationUnitRoles { get; set; } + + DbSet OrganizationUnitUsers { get; set; } } -} \ No newline at end of file +} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs index 05050159bc..576a5d2347 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { @@ -16,6 +17,12 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public DbSet ClaimTypes { get; set; } + public DbSet OrganizationUnits { get; set; } + + public DbSet OrganizationUnitRoles { get; set; } + + public DbSet OrganizationUnitUsers { get; set; } + public IdentityDbContext(DbContextOptions options) : base(options) { From fbd0d067a0a30dca72fb9730bce176a5e01ad8bd Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Fri, 3 Jan 2020 00:02:36 +0300 Subject: [PATCH 02/35] efcore layer for organization unit --- .../Volo/Abp/Identity/IdentityUser.cs | 38 ++++++++++++++++++ .../AbpIdentityEntityFrameworkCoreModule.cs | 2 + .../EntityFrameworkCore/IIdentityDbContext.cs | 4 -- .../EntityFrameworkCore/IdentityDbContext.cs | 4 -- ...IdentityDbContextModelBuilderExtensions.cs | 40 +++++++++++++++++++ .../IdentityEfCoreQueryableExtensions.cs | 3 +- 6 files changed, 82 insertions(+), 9 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index c6ad077456..2afc246394 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Identity; using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Guids; +using Volo.Abp.Identity.Organizations; using Volo.Abp.ObjectMapping; using Volo.Abp.Users; @@ -125,6 +126,11 @@ namespace Volo.Abp.Identity /// public virtual ICollection Tokens { get; protected set; } + /// + /// Navigation property for this organization units. + /// + public virtual ICollection OrganizationUnits { get; protected set; } + protected IdentityUser() { ExtraProperties = new Dictionary(); @@ -148,6 +154,7 @@ namespace Volo.Abp.Identity Claims = new Collection(); Logins = new Collection(); Tokens = new Collection(); + OrganizationUnits = new Collection(); ExtraProperties = new Dictionary(); } @@ -277,6 +284,37 @@ namespace Volo.Abp.Identity Tokens.RemoveAll(t => t.LoginProvider == loginProvider && t.Name == name); } + public virtual void AddOrganizationUnit(Guid organizationUnitId) + { + Check.NotNull(organizationUnitId, nameof(organizationUnitId)); + + if (IsInOrganizationUnit(organizationUnitId)) + { + return; + } + + OrganizationUnits.Add(new OrganizationUnitUser(TenantId, Id, organizationUnitId)); + } + + public virtual void RemoveOrganizationUnit(Guid organizationUnitId) + { + Check.NotNull(organizationUnitId, nameof(organizationUnitId)); + + if (IsInOrganizationUnit(organizationUnitId)) + { + return; + } + + OrganizationUnits.RemoveAll(ou => ou.OrganizationUnitId == organizationUnitId); + } + + public virtual bool IsInOrganizationUnit(Guid organizationUnitId) + { + Check.NotNull(organizationUnitId, nameof(organizationUnitId)); + + return OrganizationUnits.Any(ou => ou.OrganizationUnitId == organizationUnitId); + } + public override string ToString() { return $"{base.ToString()}, UserName = {UserName}"; diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs index b3ff5c368b..ab8176a733 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Volo.Abp.Users.EntityFrameworkCore; @@ -16,6 +17,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore options.AddRepository(); options.AddRepository(); options.AddRepository(); + options.AddRepository(); }); } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs index b5d7007767..06cd9ac2c9 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs @@ -15,9 +15,5 @@ namespace Volo.Abp.Identity.EntityFrameworkCore DbSet ClaimTypes { get; set; } DbSet OrganizationUnits { get; set; } - - DbSet OrganizationUnitRoles { get; set; } - - DbSet OrganizationUnitUsers { get; set; } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs index 576a5d2347..0acf396912 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs @@ -19,10 +19,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public DbSet OrganizationUnits { get; set; } - public DbSet OrganizationUnitRoles { get; set; } - - public DbSet OrganizationUnitUsers { get; set; } - public IdentityDbContext(DbContextOptions options) : base(options) { diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 76ac038c05..759fe9a1b8 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -2,6 +2,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; +using Volo.Abp.Identity.Organizations; using Volo.Abp.Users.EntityFrameworkCore; namespace Volo.Abp.Identity.EntityFrameworkCore @@ -137,6 +138,45 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.Property(uc => uc.Description).HasMaxLength(IdentityClaimTypeConsts.MaxDescriptionLength); b.Property(uc => uc.ConcurrencyStamp).IsRequired().IsConcurrencyToken().HasMaxLength(IdentityClaimTypeConsts.MaxConcurrencyStampLength).HasColumnName(nameof(IdentityClaimType.ConcurrencyStamp)); }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "OrganizationUnits", options.Schema); + + b.ConfigureFullAuditedAggregateRoot(); + + b.Property(ou => ou.Code).IsRequired().HasMaxLength(OrganizationUnitConsts.MaxCodeLength).HasColumnName(nameof(OrganizationUnit.Code)); + b.Property(ou => ou.DisplayName).IsRequired().HasMaxLength(OrganizationUnitConsts.MaxDisplayNameLength).HasColumnName(nameof(OrganizationUnit.DisplayName)); + + b.HasMany(ou => ou.Children).WithOne().HasForeignKey(ou => ou.ParentId); + + b.HasIndex(ou => ou.ParentId); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "OrganizationUnitRoles", options.Schema); + + b.HasKey(ou => new { ou.OrganizationUnitId, ou.RoleId }); + + b.HasOne().WithMany().HasForeignKey(ou => ou.OrganizationUnitId).IsRequired(); + b.HasOne().WithMany().HasForeignKey(ou => ou.RoleId).IsRequired(); + + b.HasIndex(ou => new { ou.RoleId, ou.OrganizationUnitId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "OrganizationUnitUsers", options.Schema); + + b.HasKey(ou => new { ou.OrganizationUnitId, ou.UserId }); + + b.HasOne().WithMany().HasForeignKey(ou => ou.OrganizationUnitId).IsRequired(); + b.HasOne().WithMany().HasForeignKey(ou => ou.UserId).IsRequired(); + + b.HasIndex(ou => new { ou.UserId, ou.OrganizationUnitId }); + }); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs index 8cd598c673..b16f1e4234 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs @@ -16,7 +16,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .Include(x => x.Roles) .Include(x => x.Logins) .Include(x => x.Claims) - .Include(x => x.Tokens); + .Include(x => x.Tokens) + .Include(x => x.OrganizationUnits); } public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) From 1b56ed47bbae326dadc4e0762dddcf8abd71aeab Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Sat, 4 Jan 2020 17:39:55 +0300 Subject: [PATCH 03/35] update userManager logic for organization unit --- .../IdentityUserCreateOrUpdateDtoBase.cs | 5 +- .../Volo/Abp/Identity/Localization/en.json | 1 + .../Identity/Settings/IdentitySettingNames.cs | 7 + .../AbpIdentitySettingDefinitionProvider.cs | 92 +++++++------ .../Volo/Abp/Identity/IdentityUser.cs | 6 +- .../Volo/Abp/Identity/IdentityUserManager.cs | 128 +++++++++++++++++- ...ser.cs => IdentityUserOrganizationUnit.cs} | 8 +- .../IOrganizationUnitRepository.cs | 2 + .../EfCoreOrganizationUnitRepository.cs | 5 + ...IdentityDbContextModelBuilderExtensions.cs | 4 +- 10 files changed, 203 insertions(+), 55 deletions(-) rename modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/{Organizations/OrganizationUnitUser.cs => IdentityUserOrganizationUnit.cs} (83%) diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs index 0715d2512a..77b2ff89b7 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +using System; +using System.ComponentModel.DataAnnotations; using JetBrains.Annotations; namespace Volo.Abp.Identity @@ -29,5 +30,7 @@ namespace Volo.Abp.Identity [CanBeNull] public string[] RoleNames { get; set; } + + public Guid[] OrganizationUnits { get; set; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json index 87c599ea4f..c542f45ea3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json @@ -64,6 +64,7 @@ "Identity.StaticRoleRenamingErrorMessage": "Static roles can not be renamed.", "Identity.StaticRoleDeletionErrorMessage": "Static roles can not be deleted.", "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "There is already an organization unit with name {0}. Two units with same name can not be created in same level.", + "Identity.OrganizationUnit.MaxUserMembershipCount": "Maximum allowed organization unit membership count for a user", "Volo.Abp.Identity:010001": "You can not delete your own account!", "Permission:IdentityManagement": "Identity management", "Permission:RoleManagement": "Role management", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs index babeb4fb77..144f3c5603 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Settings/IdentitySettingNames.cs @@ -40,5 +40,12 @@ public const string IsUserNameUpdateEnabled = UserPrefix + ".IsUserNameUpdateEnabled"; public const string IsEmailUpdateEnabled = UserPrefix + ".IsEmailUpdateEnabled"; } + + public static class OrganizationUnit + { + private const string OrganizationUnitPrefix = Prefix + ".OrganizationUnit"; + + public const string MaxUserMembershipCount = OrganizationUnitPrefix + ".MaxUserMembershipCount"; + } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs index efae6e467a..1c569fb2e2 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs @@ -11,83 +11,89 @@ namespace Volo.Abp.Identity { context.Add( new SettingDefinition( - IdentitySettingNames.Password.RequiredLength, - 6.ToString(), - L("DisplayName:Abp.Identity.Password.RequiredLength"), - L("Description:Abp.Identity.Password.RequiredLength"), + IdentitySettingNames.Password.RequiredLength, + 6.ToString(), + L("DisplayName:Abp.Identity.Password.RequiredLength"), + L("Description:Abp.Identity.Password.RequiredLength"), true), new SettingDefinition( - IdentitySettingNames.Password.RequiredUniqueChars, - 1.ToString(), - L("DisplayName:Abp.Identity.Password.RequiredUniqueChars"), - L("Description:Abp.Identity.Password.RequiredUniqueChars"), + IdentitySettingNames.Password.RequiredUniqueChars, + 1.ToString(), + L("DisplayName:Abp.Identity.Password.RequiredUniqueChars"), + L("Description:Abp.Identity.Password.RequiredUniqueChars"), true), new SettingDefinition( - IdentitySettingNames.Password.RequireNonAlphanumeric, - true.ToString(), - L("DisplayName:Abp.Identity.Password.RequireNonAlphanumeric"), - L("Description:Abp.Identity.Password.RequireNonAlphanumeric"), + IdentitySettingNames.Password.RequireNonAlphanumeric, + true.ToString(), + L("DisplayName:Abp.Identity.Password.RequireNonAlphanumeric"), + L("Description:Abp.Identity.Password.RequireNonAlphanumeric"), true), new SettingDefinition( - IdentitySettingNames.Password.RequireLowercase, - true.ToString(), L("DisplayName:Abp.Identity.Password.RequireLowercase"), - L("Description:Abp.Identity.Password.RequireLowercase"), + IdentitySettingNames.Password.RequireLowercase, + true.ToString(), L("DisplayName:Abp.Identity.Password.RequireLowercase"), + L("Description:Abp.Identity.Password.RequireLowercase"), true), new SettingDefinition( - IdentitySettingNames.Password.RequireUppercase, - true.ToString(), L("DisplayName:Abp.Identity.Password.RequireUppercase"), - L("Description:Abp.Identity.Password.RequireUppercase"), + IdentitySettingNames.Password.RequireUppercase, + true.ToString(), L("DisplayName:Abp.Identity.Password.RequireUppercase"), + L("Description:Abp.Identity.Password.RequireUppercase"), true), new SettingDefinition( - IdentitySettingNames.Password.RequireDigit, - true.ToString(), L("DisplayName:Abp.Identity.Password.RequireDigit"), - L("Description:Abp.Identity.Password.RequireDigit"), + IdentitySettingNames.Password.RequireDigit, + true.ToString(), L("DisplayName:Abp.Identity.Password.RequireDigit"), + L("Description:Abp.Identity.Password.RequireDigit"), true), new SettingDefinition( - IdentitySettingNames.Lockout.AllowedForNewUsers, - true.ToString(), L("DisplayName:Abp.Identity.Lockout.AllowedForNewUsers"), - L("Description:Abp.Identity.Lockout.AllowedForNewUsers"), + IdentitySettingNames.Lockout.AllowedForNewUsers, + true.ToString(), L("DisplayName:Abp.Identity.Lockout.AllowedForNewUsers"), + L("Description:Abp.Identity.Lockout.AllowedForNewUsers"), true), - + new SettingDefinition( - IdentitySettingNames.Lockout.LockoutDuration, - (5*60).ToString(), L("DisplayName:Abp.Identity.Lockout.LockoutDuration"), - L("Description:Abp.Identity.Lockout.LockoutDuration"), + IdentitySettingNames.Lockout.LockoutDuration, + (5 * 60).ToString(), L("DisplayName:Abp.Identity.Lockout.LockoutDuration"), + L("Description:Abp.Identity.Lockout.LockoutDuration"), true), new SettingDefinition( - IdentitySettingNames.Lockout.MaxFailedAccessAttempts, - 5.ToString(), L("DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts"), - L("Description:Abp.Identity.Lockout.MaxFailedAccessAttempts"), + IdentitySettingNames.Lockout.MaxFailedAccessAttempts, + 5.ToString(), L("DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts"), + L("Description:Abp.Identity.Lockout.MaxFailedAccessAttempts"), true), new SettingDefinition( - IdentitySettingNames.SignIn.RequireConfirmedEmail, - false.ToString(), L("DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail"), - L("Description:Abp.Identity.SignIn.RequireConfirmedEmail"), + IdentitySettingNames.SignIn.RequireConfirmedEmail, + false.ToString(), L("DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail"), + L("Description:Abp.Identity.SignIn.RequireConfirmedEmail"), true), new SettingDefinition( - IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, - false.ToString(), L("DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber"), - L("Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber"), + IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, + false.ToString(), L("DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber"), + L("Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber"), true), new SettingDefinition( - IdentitySettingNames.User.IsUserNameUpdateEnabled, - true.ToString(), L("DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled"), - L("Description:Abp.Identity.User.IsUserNameUpdateEnabled"), + IdentitySettingNames.User.IsUserNameUpdateEnabled, + true.ToString(), L("DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled"), + L("Description:Abp.Identity.User.IsUserNameUpdateEnabled"), true), new SettingDefinition( - IdentitySettingNames.User.IsEmailUpdateEnabled, - true.ToString(), L("DisplayName:Abp.Identity.User.IsEmailUpdateEnabled"), - L("Description:Abp.Identity.User.IsEmailUpdateEnabled"), + IdentitySettingNames.User.IsEmailUpdateEnabled, + true.ToString(), L("DisplayName:Abp.Identity.User.IsEmailUpdateEnabled"), + L("Description:Abp.Identity.User.IsEmailUpdateEnabled"), + true), + + new SettingDefinition( + IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount, + int.MaxValue.ToString(), L("Identity.OrganizationUnit.MaxUserMembershipCount"), + L("Identity.OrganizationUnit.MaxUserMembershipCount"), true) ); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index 2afc246394..6b155aa574 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -129,7 +129,7 @@ namespace Volo.Abp.Identity /// /// Navigation property for this organization units. /// - public virtual ICollection OrganizationUnits { get; protected set; } + public virtual ICollection OrganizationUnits { get; protected set; } protected IdentityUser() { @@ -154,7 +154,7 @@ namespace Volo.Abp.Identity Claims = new Collection(); Logins = new Collection(); Tokens = new Collection(); - OrganizationUnits = new Collection(); + OrganizationUnits = new Collection(); ExtraProperties = new Dictionary(); } @@ -293,7 +293,7 @@ namespace Volo.Abp.Identity return; } - OrganizationUnits.Add(new OrganizationUnitUser(TenantId, Id, organizationUnitId)); + OrganizationUnits.Add(new IdentityUserOrganizationUnit(TenantId, Id, organizationUnitId)); } public virtual void RemoveOrganizationUnit(Guid organizationUnitId) 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 9e66b7b824..acb6b56dae 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 @@ -9,7 +9,12 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Services; +using Volo.Abp.Identity.Organizations; +using Volo.Abp.Domain.Repositories; using Volo.Abp.Threading; +using Volo.Abp.Uow; +using Volo.Abp.Settings; +using Volo.Abp.Identity.Settings; namespace Volo.Abp.Identity { @@ -18,6 +23,9 @@ namespace Volo.Abp.Identity protected override CancellationToken CancellationToken => _cancellationTokenProvider.Token; private readonly ICancellationTokenProvider _cancellationTokenProvider; + protected IOrganizationUnitRepository _organizationUnitRepository { get; private set; } + protected IIdentityUserRepository _identityUserRepository { get; private set; } + private readonly ISettingProvider _settingProvider; public IdentityUserManager( IdentityUserStore store, @@ -28,7 +36,10 @@ namespace Volo.Abp.Identity ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger logger, - ICancellationTokenProvider cancellationTokenProvider) + ICancellationTokenProvider cancellationTokenProvider, + IOrganizationUnitRepository organizationUnitRepository, + IIdentityUserRepository identityUserRepository, + ISettingProvider settingProvider) : base( store, optionsAccessor, @@ -41,6 +52,9 @@ namespace Volo.Abp.Identity logger) { _cancellationTokenProvider = cancellationTokenProvider; + _organizationUnitRepository = organizationUnitRepository; + _identityUserRepository = identityUserRepository; + _settingProvider = settingProvider; } public virtual async Task GetByIdAsync(Guid id) @@ -58,7 +72,7 @@ namespace Volo.Abp.Identity { Check.NotNull(user, nameof(user)); Check.NotNull(roleNames, nameof(roleNames)); - + var currentRoleNames = await GetRolesAsync(user).ConfigureAwait(false); var result = await RemoveFromRolesAsync(user, currentRoleNames.Except(roleNames).Distinct()).ConfigureAwait(false); @@ -75,5 +89,115 @@ namespace Volo.Abp.Identity return IdentityResult.Success; } + + public virtual async Task IsInOrganizationUnitAsync(Guid userId, Guid ouId) + { + return await IsInOrganizationUnitAsync( + await GetByIdAsync(userId), + await _organizationUnitRepository.GetAsync(ouId) + ); + } + + public virtual Task IsInOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) + { + return Task.FromResult(user.IsInOrganizationUnit(ou.Id)); + } + + public virtual async Task AddToOrganizationUnitAsync(Guid userId, Guid ouId) + { + await AddToOrganizationUnitAsync( + await GetByIdAsync(userId), + await _organizationUnitRepository.GetAsync(ouId) + ); + } + + public virtual async Task AddToOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) + { + await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, _cancellationTokenProvider.Token).ConfigureAwait(false); + + var currentOus = user.OrganizationUnits; + + if (currentOus.Any(cou => cou.Id == ou.Id)) + { + return; + } + + await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, currentOus.Count + 1); + + user.AddOrganizationUnit(ou.Id); + } + + public virtual async Task RemoveFromOrganizationUnitAsync(Guid userId, Guid ouId) + { + await RemoveFromOrganizationUnitAsync( + await GetByIdAsync(userId), + await _organizationUnitRepository.GetAsync(ouId) + ); + } + + public virtual async Task RemoveFromOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) + { + await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, _cancellationTokenProvider.Token).ConfigureAwait(false); + + user.RemoveOrganizationUnit(ou.Id); + } + + public virtual async Task SetOrganizationUnitsAsync(Guid userId, params Guid[] organizationUnitIds) + { + await SetOrganizationUnitsAsync( + await GetByIdAsync(userId), + organizationUnitIds + ); + } + + public virtual async Task SetOrganizationUnitsAsync(IdentityUser user, params Guid[] organizationUnitIds) + { + Check.NotNull(user, nameof(user)); + Check.NotNull(organizationUnitIds, nameof(organizationUnitIds)); + + await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, organizationUnitIds.Length); + + var currentOus = user.OrganizationUnits; + + //Remove from removed OUs + foreach (var currentOu in currentOus) + { + if (!organizationUnitIds.Contains(currentOu.Id)) + { + await RemoveFromOrganizationUnitAsync(user.Id, currentOu.Id); + } + } + + //Add to added OUs + foreach (var organizationUnitId in organizationUnitIds) + { + if (currentOus.All(ou => ou.Id != organizationUnitId)) + { + await AddToOrganizationUnitAsync( + user, + await _organizationUnitRepository.GetAsync(organizationUnitId) + ); + } + } + } + + private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(Guid? tenantId, int requestedCount) + { + var maxCount = await _settingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount).ConfigureAwait(false); + if (requestedCount > maxCount) + { + throw new AbpException(string.Format("Can not set more than {0} organization unit for a user!", maxCount)); + } + } + + [UnitOfWork] + public virtual async Task> GetOrganizationUnitsAsync(IdentityUser user) + { + await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, _cancellationTokenProvider.Token).ConfigureAwait(false); + + var ouOfUser = user.OrganizationUnits; + + return await _organizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs similarity index 83% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs index 3ab7a1c711..3721210bd6 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs @@ -2,12 +2,12 @@ using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.Identity.Organizations +namespace Volo.Abp.Identity { /// /// Represents membership of a User to an OU. /// - public class OrganizationUnitUser : CreationAuditedEntity, IMultiTenant, ISoftDelete + public class IdentityUserOrganizationUnit : CreationAuditedEntity, IMultiTenant, ISoftDelete { /// @@ -33,7 +33,7 @@ namespace Volo.Abp.Identity.Organizations /// /// Initializes a new instance of the class. /// - public OrganizationUnitUser() + public IdentityUserOrganizationUnit() { } @@ -44,7 +44,7 @@ namespace Volo.Abp.Identity.Organizations /// TenantId /// Id of the User. /// Id of the . - public OrganizationUnitUser(Guid? tenantId, Guid userId, Guid organizationUnitId) + public IdentityUserOrganizationUnit(Guid? tenantId, Guid userId, Guid organizationUnitId) { TenantId = tenantId; UserId = userId; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index 0136d9ef4c..2d0987a855 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -10,5 +10,7 @@ namespace Volo.Abp.Identity.Organizations Task> GetChildrenAsync(Guid? parentId); Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId); + + Task> GetListAsync(IEnumerable ids); } } 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 f24adad3f7..37648adef8 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 @@ -28,5 +28,10 @@ namespace Volo.Abp.Identity.EntityFrameworkCore return await DbSet.Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(); } + + public async Task> GetListAsync(IEnumerable ids) + { + return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 759fe9a1b8..20e15d1dff 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -165,9 +165,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasIndex(ou => new { ou.RoleId, ou.OrganizationUnitId }); }); - builder.Entity(b => + builder.Entity(b => { - b.ToTable(options.TablePrefix + "OrganizationUnitUsers", options.Schema); + b.ToTable(options.TablePrefix + "UserOrganizationUnits", options.Schema); b.HasKey(ou => new { ou.OrganizationUnitId, ou.UserId }); From c8e8232506f7bf807e7c66388ad1650c1060f319 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Sat, 4 Jan 2020 20:51:56 +0300 Subject: [PATCH 04/35] add, remove role to organization unit --- .../Volo/Abp/Identity/IdentityUserManager.cs | 6 +-- .../Organizations/OrganizationUnit.cs | 39 +++++++++++++++ .../Organizations/OrganizationUnitManager.cs | 50 ++++++++++++++++++- .../IdentityEfCoreQueryableExtensions.cs | 12 +++++ 4 files changed, 103 insertions(+), 4 deletions(-) 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 acb6b56dae..f5a54bf961 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 @@ -106,7 +106,7 @@ namespace Volo.Abp.Identity public virtual async Task AddToOrganizationUnitAsync(Guid userId, Guid ouId) { await AddToOrganizationUnitAsync( - await GetByIdAsync(userId), + await _identityUserRepository.GetAsync(userId, true), await _organizationUnitRepository.GetAsync(ouId) ); } @@ -130,7 +130,7 @@ namespace Volo.Abp.Identity public virtual async Task RemoveFromOrganizationUnitAsync(Guid userId, Guid ouId) { await RemoveFromOrganizationUnitAsync( - await GetByIdAsync(userId), + await _identityUserRepository.GetAsync(userId, true), await _organizationUnitRepository.GetAsync(ouId) ); } @@ -145,7 +145,7 @@ namespace Volo.Abp.Identity public virtual async Task SetOrganizationUnitsAsync(Guid userId, params Guid[] organizationUnitIds) { await SetOrganizationUnitsAsync( - await GetByIdAsync(userId), + await _identityUserRepository.GetAsync(userId, true), organizationUnitIds ); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs index 0955aa248a..2a48337e45 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.MultiTenancy; @@ -37,6 +38,11 @@ namespace Volo.Abp.Identity.Organizations /// public virtual ICollection Children { get; set; } + /// + /// Roles of this OU. + /// + public virtual ICollection Roles { get; protected set; } + /// /// Initializes a new instance of the class. /// @@ -56,6 +62,8 @@ namespace Volo.Abp.Identity.Organizations TenantId = tenantId; DisplayName = displayName; ParentId = parentId; + + Roles = new Collection(); } /// @@ -174,5 +182,36 @@ namespace Volo.Abp.Identity.Organizations return splittedCode.Take(splittedCode.Length - 1).JoinAsString("."); } + + public virtual void AddRole(Guid roleId) + { + Check.NotNull(roleId, nameof(roleId)); + + if (IsInRole(roleId)) + { + return; + } + + Roles.Add(new OrganizationUnitRole(TenantId, roleId, Id)); + } + + public virtual void RemoveRole(Guid roleId) + { + Check.NotNull(roleId, nameof(roleId)); + + if (!IsInRole(roleId)) + { + return; + } + + Roles.RemoveAll(r => r.RoleId == roleId); + } + + public virtual bool IsInRole(Guid roleId) + { + Check.NotNull(roleId, nameof(roleId)); + + return Roles.Any(r => r.RoleId == roleId); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs index 88aad4d66a..66861a9027 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; using Volo.Abp.Identity.Localization; +using Volo.Abp.Threading; using Volo.Abp.Uow; namespace Volo.Abp.Identity.Organizations @@ -18,13 +20,19 @@ namespace Volo.Abp.Identity.Organizations protected IOrganizationUnitRepository _organizationUnitRepository { get; private set; } private readonly IStringLocalizer _localizer; + private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly ICancellationTokenProvider _cancellationTokenProvider; public OrganizationUnitManager( IOrganizationUnitRepository organizationUnitRepository, - IStringLocalizer localizer) + IStringLocalizer localizer, + IIdentityRoleRepository identityRoleRepository, + ICancellationTokenProvider cancellationTokenProvider) { _organizationUnitRepository = organizationUnitRepository; _localizer = localizer; + _identityRoleRepository = identityRoleRepository; + _cancellationTokenProvider = cancellationTokenProvider; } [UnitOfWork] @@ -134,5 +142,45 @@ namespace Volo.Abp.Identity.Organizations return await _organizationUnitRepository.GetAllChildrenWithParentCodeAsync(code, parentId); } + + public virtual Task IsInOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) + { + return Task.FromResult(user.IsInOrganizationUnit(ou.Id)); + } + + public virtual async Task AddRoleToOrganizationUnitAsync(Guid roleId, Guid ouId) + { + await AddRoleToOrganizationUnitAsync( + await _identityRoleRepository.GetAsync(roleId), + await _organizationUnitRepository.GetAsync(ouId) + ); + } + + public virtual Task AddRoleToOrganizationUnitAsync(IdentityRole role, OrganizationUnit ou) + { + var currentRoles = ou.Roles; + + if (currentRoles.Any(r => r.Id == role.Id)) + { + return Task.FromResult(0); + } + ou.AddRole(role.Id); + return Task.FromResult(0); + } + + public virtual async Task RemoveRoleFromOrganizationUnitAsync(Guid roleId, Guid ouId) + { + await RemoveRoleFromOrganizationUnitAsync( + await _identityRoleRepository.GetAsync(roleId), + await _organizationUnitRepository.GetAsync(ouId, true) + ); + } + + public virtual async Task RemoveRoleFromOrganizationUnitAsync(IdentityRole role, OrganizationUnit organizationUnit) + { + await _organizationUnitRepository.EnsureCollectionLoadedAsync(organizationUnit, ou => ou.Roles, _cancellationTokenProvider.Token).ConfigureAwait(false); + + organizationUnit.RemoveRole(role.Id); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs index b16f1e4234..6203233dcc 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs @@ -1,5 +1,6 @@ using System.Linq; using Microsoft.EntityFrameworkCore; +using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { @@ -30,5 +31,16 @@ namespace Volo.Abp.Identity.EntityFrameworkCore return queryable .Include(x => x.Claims); } + + public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) + { + if (!include) + { + return queryable; + } + + return queryable + .Include(x => x.Roles); + } } } \ No newline at end of file From bdffd6d29afcf18772794c8e489f7de898c98157 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Sun, 5 Jan 2020 20:17:04 +0300 Subject: [PATCH 05/35] all test the organizations --- .../Abp/Identity/IIdentityUserRepository.cs | 6 + .../Volo/Abp/Identity/IdentityUser.cs | 2 +- .../Volo/Abp/Identity/IdentityUserManager.cs | 2 +- .../IOrganizationUnitRepository.cs | 9 ++ .../Organizations/OrganizationUnit.cs | 1 - .../Organizations/OrganizationUnitManager.cs | 25 ++-- .../EfCoreIdentityUserRepository.cs | 14 +++ .../EfCoreOrganizationUnitRepository.cs | 42 +++++++ ...IdentityDbContextModelBuilderExtensions.cs | 1 + .../Abp/Identity/IdentityUserManager_Tests.cs | 59 ++++++++++ .../Identity/OrganizationUnitManager_Tests.cs | 111 ++++++++++++++++++ .../OrganizationUnitRepository_Tests.cs | 10 ++ .../Identity/AbpIdentityTestDataBuilder.cs | 51 +++++++- .../Identity/IdentityUserRepository_Tests.cs | 3 + .../Identity_Repository_Resolve_Tests.cs | 5 + .../Volo/Abp/Identity/LazyLoading_Tests.cs | 19 +++ .../OrganizationUnitRepository_Tests.cs | 76 ++++++++++++ 17 files changed, 417 insertions(+), 19 deletions(-) create mode 100644 modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs create mode 100644 modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs create mode 100644 modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs 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 98269da005..f5e7c14d37 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 @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Volo.Abp.Domain.Repositories; +using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity { @@ -61,6 +62,11 @@ namespace Volo.Abp.Identity CancellationToken cancellationToken = default ); + Task> GetOrganizationUnitsAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default); + Task GetCountAsync( string filter = null, CancellationToken cancellationToken = default diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index 6b155aa574..78c7e629a4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -300,7 +300,7 @@ namespace Volo.Abp.Identity { Check.NotNull(organizationUnitId, nameof(organizationUnitId)); - if (IsInOrganizationUnit(organizationUnitId)) + if (!IsInOrganizationUnit(organizationUnitId)) { return; } 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 f5a54bf961..87faf866cb 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 @@ -157,7 +157,7 @@ namespace Volo.Abp.Identity await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, organizationUnitIds.Length); - var currentOus = user.OrganizationUnits; + var currentOus = await _identityUserRepository.GetOrganizationUnitsAsync(user.Id).ConfigureAwait(false); //Remove from removed OUs foreach (var currentOu in currentOus) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index 2d0987a855..9774534bfc 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; @@ -12,5 +13,13 @@ namespace Volo.Abp.Identity.Organizations Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId); Task> GetListAsync(IEnumerable ids); + + Task> GetListAsync(bool includeDetails = true); + + Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default); + + Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId); + + Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs index 2a48337e45..ca9e17267c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs @@ -62,7 +62,6 @@ namespace Volo.Abp.Identity.Organizations TenantId = tenantId; DisplayName = displayName; ParentId = parentId; - Roles = new Collection(); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs index 66861a9027..dbf6f44cef 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -40,13 +40,13 @@ namespace Volo.Abp.Identity.Organizations { organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId); await ValidateOrganizationUnitAsync(organizationUnit); - await _organizationUnitRepository.InsertAsync(organizationUnit); + await _organizationUnitRepository.InsertAsync(organizationUnit).ConfigureAwait(false); } public virtual async Task UpdateAsync(OrganizationUnit organizationUnit) { await ValidateOrganizationUnitAsync(organizationUnit); - await _organizationUnitRepository.UpdateAsync(organizationUnit); + await _organizationUnitRepository.UpdateAsync(organizationUnit).ConfigureAwait(false); } public virtual async Task GetNextChildCodeAsync(Guid? parentId) @@ -74,16 +74,16 @@ namespace Volo.Abp.Identity.Organizations foreach (var child in children) { - await _organizationUnitRepository.DeleteAsync(child); + await _organizationUnitRepository.DeleteAsync(child).ConfigureAwait(false); } - await _organizationUnitRepository.DeleteAsync(id); + await _organizationUnitRepository.DeleteAsync(id).ConfigureAwait(false); } [UnitOfWork] public virtual async Task MoveAsync(Guid id, Guid? parentId) { - var organizationUnit = await _organizationUnitRepository.GetAsync(id); + var organizationUnit = await _organizationUnitRepository.GetAsync(id).ConfigureAwait(false); if (organizationUnit.ParentId == parentId) { return; @@ -110,7 +110,7 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task GetCodeOrDefaultAsync(Guid id) { - var ou = await _organizationUnitRepository.GetAsync(id); + var ou = await _organizationUnitRepository.GetAsync(id).ConfigureAwait(false); return ou?.Code; } @@ -130,12 +130,12 @@ namespace Volo.Abp.Identity.Organizations { if (!recursive) { - return await _organizationUnitRepository.GetChildrenAsync(parentId); + return await _organizationUnitRepository.GetChildrenAsync(parentId).ConfigureAwait(false); } if (!parentId.HasValue) { - return await _organizationUnitRepository.GetListAsync(); + return await _organizationUnitRepository.GetListAsync().ConfigureAwait(false); } var code = await GetCodeOrDefaultAsync(parentId.Value); @@ -156,16 +156,16 @@ namespace Volo.Abp.Identity.Organizations ); } - public virtual Task AddRoleToOrganizationUnitAsync(IdentityRole role, OrganizationUnit ou) + public virtual async Task AddRoleToOrganizationUnitAsync(IdentityRole role, OrganizationUnit ou) { var currentRoles = ou.Roles; if (currentRoles.Any(r => r.Id == role.Id)) { - return Task.FromResult(0); + return; } ou.AddRole(role.Id); - return Task.FromResult(0); + await _organizationUnitRepository.AddRole(ou, role, ou.TenantId); } public virtual async Task RemoveRoleFromOrganizationUnitAsync(Guid roleId, Guid ouId) @@ -178,8 +178,7 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task RemoveRoleFromOrganizationUnitAsync(IdentityRole role, OrganizationUnit organizationUnit) { - await _organizationUnitRepository.EnsureCollectionLoadedAsync(organizationUnit, ou => ou.Roles, _cancellationTokenProvider.Token).ConfigureAwait(false); - + await _organizationUnitRepository.RemoveRole(organizationUnit, role, organizationUnit.TenantId); organizationUnit.RemoveRole(role.Id); } } 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 e3dfe6ee8c..f27ece7b25 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 @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { @@ -143,6 +144,19 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .LongCountAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + public virtual async Task> GetOrganizationUnitsAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var query = from userOU in DbContext.Set() + join ou in DbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOU.OrganizationUnitId equals ou.Id + where userOU.UserId == id + select ou; + + return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); 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 37648adef8..b90d600c94 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 @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -33,5 +34,46 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(); } + + public async Task> GetListAsync(bool includeDetails = true) + { + return await DbSet + .IncludeDetails(includeDetails) + .ToListAsync(); + } + + public async Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) + { + return await DbSet + .IncludeDetails(includeDetails) + .FirstOrDefaultAsync( + ou => ou.DisplayName == displayName, + GetCancellationToken(cancellationToken) + ).ConfigureAwait(false); + } + + public async Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId) + { + var our = new OrganizationUnitRole(tenantId, role.Id, ou.Id); + DbContext.Set().Add(our); + await DbContext.SaveChangesAsync(); + } + + public async Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId) + { + var context = DbContext.Set(); + var our = await context.FirstOrDefaultAsync(our => + our.OrganizationUnitId == ou.Id && + our.RoleId == role.Id && + our.TenantId == tenantId + ); + DbContext.Set().Remove(our); + await DbContext.SaveChangesAsync(); + } + + public override IQueryable WithDetails() + { + return GetQueryable().IncludeDetails(); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 20e15d1dff..78daa5217b 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -149,6 +149,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.Property(ou => ou.DisplayName).IsRequired().HasMaxLength(OrganizationUnitConsts.MaxDisplayNameLength).HasColumnName(nameof(OrganizationUnit.DisplayName)); b.HasMany(ou => ou.Children).WithOne().HasForeignKey(ou => ou.ParentId); + b.HasMany(ou => ou.Roles).WithOne().HasForeignKey(our => our.OrganizationUnitId).IsRequired(); b.HasIndex(ou => ou.ParentId); }); diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index bc03f35c49..b2749a2f4a 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -4,8 +4,10 @@ using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Shouldly; +using Volo.Abp.Identity.Organizations; using Volo.Abp.Uow; using Xunit; +using System.Linq; namespace Volo.Abp.Identity { @@ -14,6 +16,7 @@ namespace Volo.Abp.Identity private readonly IdentityUserManager _identityUserManager; private readonly IIdentityUserRepository _identityUserRepository; private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly IOrganizationUnitRepository _organizationUnitRepository; private readonly ILookupNormalizer _lookupNormalizer; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IdentityTestData _testData; @@ -23,6 +26,7 @@ namespace Volo.Abp.Identity _identityUserManager = GetRequiredService(); _identityUserRepository = GetRequiredService(); _identityRoleRepository = GetRequiredService(); + _organizationUnitRepository = GetRequiredService(); _lookupNormalizer = GetRequiredService(); _testData = GetRequiredService(); _unitOfWorkManager = GetRequiredService(); @@ -83,5 +87,60 @@ namespace Volo.Abp.Identity await uow.CompleteAsync().ConfigureAwait(false); } } + + [Fact] + public async Task SetOrganizationUnitsAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.NormalizeName("david")).ConfigureAwait(false); + user.ShouldNotBeNull(); + + var ou = await _organizationUnitRepository.GetOrganizationUnit( + _lookupNormalizer.NormalizeName("OU11")).ConfigureAwait(false); + ou.ShouldNotBeNull(); + + await _identityUserManager.SetOrganizationUnitsAsync(user, new Guid[] + { + ou.Id + }).ConfigureAwait(false); + + user = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.NormalizeName("david")).ConfigureAwait(false); + user.OrganizationUnits.Count.ShouldBeGreaterThan(0); + user.OrganizationUnits.FirstOrDefault(uou => uou.OrganizationUnitId == ou.Id).ShouldNotBeNull(); + + await uow.CompleteAsync().ConfigureAwait(false); + } + } + + [Fact] + public async Task SetOrganizationUnits_Should_Remove() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var ou = await _organizationUnitRepository.GetOrganizationUnit( + _lookupNormalizer.NormalizeName("OU111")).ConfigureAwait(false); + ou.ShouldNotBeNull(); + + var user = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.NormalizeName("john.nash")).ConfigureAwait(false); + user.ShouldNotBeNull(); + + var ouNew = await _organizationUnitRepository.GetOrganizationUnit( + _lookupNormalizer.NormalizeName("OU2")).ConfigureAwait(false); + ouNew.ShouldNotBeNull(); + + await _identityUserManager.SetOrganizationUnitsAsync(user, new Guid[] + { + ouNew.Id + }).ConfigureAwait(false); + + user.OrganizationUnits.ShouldNotContain(x => x.OrganizationUnitId == ou.Id); + + await uow.CompleteAsync().ConfigureAwait(false); + } + } } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs new file mode 100644 index 0000000000..f19716b8ee --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -0,0 +1,111 @@ +using Microsoft.AspNetCore.Identity; +using Shouldly; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Identity.Organizations; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class OrganizationUnitManager_Tests : AbpIdentityDomainTestBase + { + private readonly OrganizationUnitManager _organizationUnitManager; + private readonly IOrganizationUnitRepository _organizationUnitRepository; + private readonly IdentityTestData _testData; + private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly ILookupNormalizer _lookupNormalizer; + public OrganizationUnitManager_Tests() + { + _organizationUnitManager = GetRequiredService(); + _organizationUnitRepository = GetRequiredService(); + _identityRoleRepository = GetRequiredService(); + _lookupNormalizer = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task CreateAsnyc() + { + await _organizationUnitManager.CreateAsync(new OrganizationUnit(null, "Root 1")); + + var root1 = await _organizationUnitRepository.GetOrganizationUnit("Root 1").ConfigureAwait(false); + root1.ShouldNotBeNull(); + } + + [Fact] + public async Task UpdateAsync() + { + var ou = await _organizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + ou.Code = OrganizationUnit.CreateCode(123); + await _organizationUnitManager.UpdateAsync(ou); + + var ouAfterChange = await _organizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + ouAfterChange.Code.ShouldContain("123"); + } + + [Fact] + public async Task DeleteAsync() + { + var ou = await _organizationUnitRepository.GetOrganizationUnit("OU11").ConfigureAwait(false); + await _organizationUnitManager.DeleteAsync(ou.Id); + + (await _organizationUnitRepository.GetOrganizationUnit("OU11").ConfigureAwait(false)).ShouldBeNull(); + } + + [Fact] + public async Task MoveAsync() + { + var ou1 = await _organizationUnitRepository.GetOrganizationUnit("OU1").ConfigureAwait(false); + var ou2 = await _organizationUnitRepository.GetOrganizationUnit("OU2").ConfigureAwait(false); + + await _organizationUnitManager.MoveAsync(ou1.Id, ou2.Id); + + ou1 = await _organizationUnitRepository.GetOrganizationUnit("OU1").ConfigureAwait(false); + ou1.ParentId.ShouldBe(ou2.Id); + ou1.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2)); + + var ou11 = await _organizationUnitRepository.GetOrganizationUnit("OU11").ConfigureAwait(false); + ou11.ParentId.ShouldBe(ou1.Id); + ou11.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1)); + + var ou111 = await _organizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + ou111.ParentId.ShouldBe(ou11.Id); + ou111.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 1)); + + var ou112 = await _organizationUnitRepository.GetOrganizationUnit("OU112").ConfigureAwait(false); + ou112.ParentId.ShouldBe(ou11.Id); + ou112.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 2)); + + var ou12 = await _organizationUnitRepository.GetOrganizationUnit("OU12").ConfigureAwait(false); + ou12.ParentId.ShouldBe(ou1.Id); + ou12.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 2)); + } + + [Fact] + public async Task AddRoleToOrganizationUnitAsync() + { + var ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", true).ConfigureAwait(false); + var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); + await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole.Id, ou.Id); + + //TODO: This method has a bug: includeDetails not work + ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", includeDetails: true).ConfigureAwait(false); + ou.Roles.FirstOrDefault().Id.ShouldBe(adminRole.Id); + } + + [Fact] + public async Task RemoveRoleFromOrganizationUnitAsync() + { + var ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", true).ConfigureAwait(false); + var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); + await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole.Id, ou.Id); + + await _organizationUnitManager.RemoveRoleFromOrganizationUnitAsync(adminRole.Id, ou.Id); + ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", includeDetails: true).ConfigureAwait(false); + ou.Roles.FirstOrDefault(r => r.RoleId == adminRole.Id).ShouldBeNull(); + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs new file mode 100644 index 0000000000..8fa9a14dba --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.Identity.EntityFrameworkCore +{ + public class OrganizationUnitRepository_Tests : OrganizationUnitRepository_Tests + { + } +} 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 ad36fe69a7..979fcf940f 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 @@ -1,8 +1,10 @@ -using System.Security.Claims; +using System; +using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity { @@ -12,20 +14,26 @@ namespace Volo.Abp.Identity private readonly IIdentityUserRepository _userRepository; private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository; private readonly IIdentityRoleRepository _roleRepository; + private readonly IOrganizationUnitRepository _organizationUnitRepository; private readonly ILookupNormalizer _lookupNormalizer; private readonly IdentityTestData _testData; + private readonly OrganizationUnitManager _organizationUnitManager; private IdentityRole _adminRole; private IdentityRole _moderator; private IdentityRole _supporterRole; + private OrganizationUnit _ou111; + private OrganizationUnit _ou112; public AbpIdentityTestDataBuilder( IGuidGenerator guidGenerator, IIdentityUserRepository userRepository, IIdentityClaimTypeRepository identityClaimTypeRepository, IIdentityRoleRepository roleRepository, + IOrganizationUnitRepository organizationUnitRepository, ILookupNormalizer lookupNormalizer, - IdentityTestData testData) + IdentityTestData testData, + OrganizationUnitManager organizationUnitManager) { _guidGenerator = guidGenerator; _userRepository = userRepository; @@ -33,11 +41,14 @@ namespace Volo.Abp.Identity _roleRepository = roleRepository; _lookupNormalizer = lookupNormalizer; _testData = testData; + _organizationUnitRepository = organizationUnitRepository; + _organizationUnitManager = organizationUnitManager; } public async Task Build() { await AddRoles().ConfigureAwait(false); + await AddOrganizationUnits().ConfigureAwait(false); await AddUsers().ConfigureAwait(false); await AddClaimTypes().ConfigureAwait(false); } @@ -54,6 +65,31 @@ namespace Volo.Abp.Identity await _roleRepository.InsertAsync(_supporterRole).ConfigureAwait(false); } + /* Creates OU tree as shown below: + * + * - OU1 + * - OU11 + * - OU111 + * - OU112 + * - OU12 + * - OU2 + * - OU21 + */ + private async Task AddOrganizationUnits() + { + var ou1 = await CreateOU("OU1", OrganizationUnit.CreateCode(1)).ConfigureAwait(false); + var ou11 = await CreateOU("OU11", OrganizationUnit.CreateCode(1, 1), ou1.Id).ConfigureAwait(false); + _ou112 = await CreateOU("OU112", OrganizationUnit.CreateCode(1, 1, 2), ou11.Id).ConfigureAwait(false); + var ou12 = await CreateOU("OU12", OrganizationUnit.CreateCode(1, 2), ou1.Id).ConfigureAwait(false); + var ou2 = await CreateOU("OU2", OrganizationUnit.CreateCode(2)).ConfigureAwait(false); + var ou21 = await CreateOU("OU21", OrganizationUnit.CreateCode(2, 1), ou2.Id).ConfigureAwait(false); + + _ou111 = new OrganizationUnit(null, "OU111", ou11.Id); + _ou111.Code = OrganizationUnit.CreateCode(1, 1, 1); + _ou111.AddRole(_moderator.Id); + await _organizationUnitRepository.InsertAsync(_ou111).ConfigureAwait(false); + } + private async Task AddUsers() { var adminUser = new IdentityUser(_guidGenerator.Create(), "administrator", "admin@abp.io"); @@ -64,6 +100,8 @@ namespace Volo.Abp.Identity var john = new IdentityUser(_testData.UserJohnId, "john.nash", "john.nash@abp.io"); john.AddRole(_moderator.Id); john.AddRole(_supporterRole.Id); + john.AddOrganizationUnit(_ou111.Id); + john.AddOrganizationUnit(_ou112.Id); john.AddLogin(new UserLoginInfo("github", "john", "John Nash")); john.AddLogin(new UserLoginInfo("twitter", "johnx", "John Nash")); john.AddClaim(_guidGenerator, new Claim("TestClaimType", "42")); @@ -79,12 +117,19 @@ namespace Volo.Abp.Identity await _userRepository.InsertAsync(neo).ConfigureAwait(false); } + private async Task AddClaimTypes() { - var ageClaim = new IdentityClaimType(_testData.AgeClaimId, "Age", false, false, null, null, null,IdentityClaimValueType.Int); + var ageClaim = new IdentityClaimType(_testData.AgeClaimId, "Age", false, false, null, null, null, IdentityClaimValueType.Int); await _identityClaimTypeRepository.InsertAsync(ageClaim).ConfigureAwait(false); var educationClaim = new IdentityClaimType(_testData.EducationClaimId, "Education", true, false, null, null, null); await _identityClaimTypeRepository.InsertAsync(educationClaim).ConfigureAwait(false); } + + private async Task CreateOU(string displayName, string code, Guid? parentId = null) + { + var ou = await _organizationUnitRepository.InsertAsync(new OrganizationUnit(null, displayName, parentId) { Code = code }).ConfigureAwait(false); + return ou; + } } } \ No newline at end of file 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 98f25f6aee..f4719a63a7 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 @@ -144,6 +144,9 @@ namespace Volo.Abp.Identity john.Tokens.ShouldNotBeNull(); john.Tokens.Any().ShouldBeTrue(); + + john.OrganizationUnits.ShouldNotBeNull(); + john.OrganizationUnits.Any().ShouldBeTrue(); } } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs index 8b748f10b7..480e72f4cc 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Domain.Repositories; +using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Xunit; @@ -20,6 +21,10 @@ namespace Volo.Abp.Identity ServiceProvider.GetService>().ShouldNotBeNull(); ServiceProvider.GetService>().ShouldNotBeNull(); ServiceProvider.GetService().ShouldNotBeNull(); + + ServiceProvider.GetService>().ShouldNotBeNull(); + ServiceProvider.GetService>().ShouldNotBeNull(); + ServiceProvider.GetService().ShouldNotBeNull(); } } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs index 3313803436..cd09c1209e 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Volo.Abp.Uow; using Xunit; @@ -14,6 +15,7 @@ namespace Volo.Abp.Identity { protected IIdentityUserRepository UserRepository { get; } protected IIdentityRoleRepository RoleRepository { get; } + protected IOrganizationUnitRepository OrganizationUnitRepository { get; } protected ILookupNormalizer LookupNormalizer { get; } protected LazyLoading_Tests() @@ -21,6 +23,7 @@ namespace Volo.Abp.Identity UserRepository = ServiceProvider.GetRequiredService(); RoleRepository = ServiceProvider.GetRequiredService(); LookupNormalizer = ServiceProvider.GetRequiredService(); + OrganizationUnitRepository = ServiceProvider.GetRequiredService(); } [Fact] @@ -55,6 +58,22 @@ namespace Volo.Abp.Identity john.Tokens.ShouldNotBeNull(); john.Tokens.Any().ShouldBeTrue(); + john.OrganizationUnits.ShouldNotBeNull(); + john.OrganizationUnits.Any().ShouldBeTrue(); + + await uow.CompleteAsync().ConfigureAwait(false); + } + } + + [Fact] + public async Task Should_Lazy_Load_OrganizationUnit_Collections() + { + using (var uow = GetRequiredService().Begin()) + { + var ou = await OrganizationUnitRepository.GetOrganizationUnit(LookupNormalizer.NormalizeName("OU111"), includeDetails: false).ConfigureAwait(false); + ou.Roles.ShouldNotBeNull(); //? + ou.Roles.Any().ShouldBeTrue(); + await uow.CompleteAsync().ConfigureAwait(false); } } 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 new file mode 100644 index 0000000000..4d6e07f447 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs @@ -0,0 +1,76 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Guids; +using Volo.Abp.Identity.Organizations; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.Identity +{ + public abstract class OrganizationUnitRepository_Tests : AbpIdentityTestBase + where TStartupModule : IAbpModule + { + protected IOrganizationUnitRepository OrganizationUnitRepository { get; } + protected ILookupNormalizer LookupNormalizer { get; } + private readonly IdentityTestData _testData; + private readonly IGuidGenerator _guidGenerator; + + public OrganizationUnitRepository_Tests() + { + OrganizationUnitRepository = ServiceProvider.GetRequiredService(); + LookupNormalizer = ServiceProvider.GetRequiredService(); + _testData = GetRequiredService(); + _guidGenerator = GetRequiredService(); + } + + [Fact] + public async Task GetChildrenAsync() + { + (await OrganizationUnitRepository.GetChildrenAsync(_testData.RoleModeratorId).ConfigureAwait(false)).ShouldNotBeNull(); + } + + [Fact] + public async Task GetAllChildrenWithParentCodeAsync() + { + (await OrganizationUnitRepository.GetAllChildrenWithParentCodeAsync(OrganizationUnit.CreateCode(0), _guidGenerator.Create()).ConfigureAwait(false)).ShouldNotBeNull(); + } + + [Fact] + public async Task GetListAsync() + { + var ouIds = (await OrganizationUnitRepository.GetListAsync().ConfigureAwait(false)) + .Select(ou => ou.Id).Take(2); + var ous = await OrganizationUnitRepository.GetListAsync(ouIds).ConfigureAwait(false); + ous.Count.ShouldBe(2); + ous.ShouldContain(ou => ou.Id == ouIds.First()); + } + + [Fact] + public async Task GetOrganizationUnit() + { + var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + organizationUnit.ShouldNotBeNull(); + } + + [Fact] + public async Task GetCountAsync() + { + (await OrganizationUnitRepository.GetCountAsync().ConfigureAwait(false)).ShouldBeGreaterThan(0); + } + + [Fact] + public async Task Should_Eager_Load_OrganizationUnit_Collections() + { + var ou = (await OrganizationUnitRepository.GetListAsync(true).ConfigureAwait(false)) + .FirstOrDefault(ou => ou.DisplayName == "OU111"); + ou.Roles.ShouldNotBeNull(); + ou.Roles.Any().ShouldBeTrue(); + } + } +} From 4e7e04a7fe3980691353a92d229381d1d3180d64 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Mon, 6 Jan 2020 10:22:44 +0300 Subject: [PATCH 06/35] mongodb repo for organization units --- .../Abp/Identity/IIdentityUserRepository.cs | 4 ++ .../Volo/Abp/Identity/IdentityUserStore.cs | 6 +- .../IOrganizationUnitRepository.cs | 12 ++-- .../Organizations/OrganizationUnitManager.cs | 6 +- .../EfCoreIdentityUserRepository.cs | 13 ++++ .../EfCoreOrganizationUnitRepository.cs | 24 +++---- .../MongoDB/AbpIdentityMongoDbContext.cs | 3 + .../AbpIdentityMongoDbContextExtensions.cs | 6 ++ .../MongoDB/AbpIdentityMongoDbModule.cs | 2 + .../MongoDB/IAbpIdentityMongoDbContext.cs | 3 + .../MongoDB/MongoIdentityUserRepository.cs | 40 ++++++++--- .../MongoOrganizationUnitRepository.cs | 66 +++++++++++++++++++ .../Identity/OrganizationUnitManager_Tests.cs | 4 +- .../OrganizationUnitRepository_Tests.cs | 10 +++ 14 files changed, 166 insertions(+), 33 deletions(-) create mode 100644 modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs create mode 100644 modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/OrganizationUnitRepository_Tests.cs 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 f5e7c14d37..04ff5c2e5f 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 @@ -22,6 +22,10 @@ namespace Volo.Abp.Identity CancellationToken cancellationToken = default ); + Task> GetRoleNamesInOrganizationUnitAsync( + Guid id, + CancellationToken cancellationToken = default); + Task FindByLoginAsync( [NotNull] string loginProvider, [NotNull] string providerKey, 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 cb03869ae6..cbec7144d2 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 @@ -366,7 +366,11 @@ namespace Volo.Abp.Identity Check.NotNull(user, nameof(user)); - return await _userRepository.GetRoleNamesAsync(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(); } /// diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index 9774534bfc..fad8b044f8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -8,18 +8,18 @@ namespace Volo.Abp.Identity.Organizations { public interface IOrganizationUnitRepository : IBasicRepository { - Task> GetChildrenAsync(Guid? parentId); + Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default); - Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId); + Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default); - Task> GetListAsync(IEnumerable ids); + Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default); - Task> GetListAsync(bool includeDetails = true); + Task> GetListAsync(bool includeDetails = true, CancellationToken cancellationToken = default); Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default); - Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId); + Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default); - Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId); + Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs index dbf6f44cef..356201aef9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -151,8 +151,8 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task AddRoleToOrganizationUnitAsync(Guid roleId, Guid ouId) { await AddRoleToOrganizationUnitAsync( - await _identityRoleRepository.GetAsync(roleId), - await _organizationUnitRepository.GetAsync(ouId) + await _identityRoleRepository.GetAsync(roleId).ConfigureAwait(false), + await _organizationUnitRepository.GetAsync(ouId, true).ConfigureAwait(false) ); } @@ -162,7 +162,7 @@ namespace Volo.Abp.Identity.Organizations if (currentRoles.Any(r => r.Id == role.Id)) { - return; + return ; } ou.AddRole(role.Id); await _organizationUnitRepository.AddRole(ou, role, ou.TenantId); 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 f27ece7b25..587c2043ac 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 @@ -44,6 +44,19 @@ namespace Volo.Abp.Identity.EntityFrameworkCore return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + public virtual async Task> GetRoleNamesInOrganizationUnitAsync( + Guid id, + CancellationToken cancellationToken = default) + { + var query = from userOu in DbContext.Set() + join roleOu in DbContext.Set() on userOu.OrganizationUnitId equals roleOu.OrganizationUnitId + join userOuRoles in DbContext.Roles on roleOu.RoleId equals userOuRoles.Id + where userOu.UserId == id + select userOuRoles.Name; + + return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + public virtual async Task FindByLoginAsync( string loginProvider, string providerKey, 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 b90d600c94..2519efc617 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 @@ -18,28 +18,28 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { } - public async Task> GetChildrenAsync(Guid? parentId) + public async Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default) { return await DbSet.Where(x => x.ParentId == parentId) - .ToListAsync(); + .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } - public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId) + public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default) { return await DbSet.Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) - .ToListAsync(); + .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } - public async Task> GetListAsync(IEnumerable ids) + public async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(); + return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } - public async Task> GetListAsync(bool includeDetails = true) + public override async Task> GetListAsync(bool includeDetails = true, CancellationToken cancellationToken = default) { return await DbSet .IncludeDetails(includeDetails) - .ToListAsync(); + .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } public async Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -52,14 +52,14 @@ namespace Volo.Abp.Identity.EntityFrameworkCore ).ConfigureAwait(false); } - public async Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId) + public Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) { var our = new OrganizationUnitRole(tenantId, role.Id, ou.Id); DbContext.Set().Add(our); - await DbContext.SaveChangesAsync(); + return Task.FromResult(0); } - public async Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId) + public async Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) { var context = DbContext.Set(); var our = await context.FirstOrDefaultAsync(our => @@ -68,12 +68,12 @@ namespace Volo.Abp.Identity.EntityFrameworkCore our.TenantId == tenantId ); DbContext.Set().Remove(our); - await DbContext.SaveChangesAsync(); } public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); } + } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs index 3db35866f5..a78dca0d0f 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs @@ -1,5 +1,6 @@ using MongoDB.Driver; using Volo.Abp.Data; +using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB @@ -13,6 +14,8 @@ namespace Volo.Abp.Identity.MongoDB public IMongoCollection ClaimTypes => Collection(); + public IMongoCollection OrganizationUnits => Collection(); + protected override void CreateModel(IMongoModelBuilder modelBuilder) { base.CreateModel(modelBuilder); diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs index dd0cc8d42e..f6bf256576 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs @@ -1,4 +1,5 @@ using System; +using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB @@ -31,6 +32,11 @@ namespace Volo.Abp.Identity.MongoDB { b.CollectionName = options.CollectionPrefix + "ClaimTypes"; }); + + builder.Entity(b => + { + b.CollectionName = options.CollectionPrefix + "OrganizationUnit"; + }); } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs index cfbc10adba..16a400a772 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Volo.Abp.Users.MongoDB; @@ -17,6 +18,7 @@ namespace Volo.Abp.Identity.MongoDB options.AddRepository(); options.AddRepository(); options.AddRepository(); + options.AddRepository(); }); } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs index 36cdcbec3e..38a38cc828 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs @@ -1,5 +1,6 @@ using MongoDB.Driver; using Volo.Abp.Data; +using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB @@ -12,5 +13,7 @@ namespace Volo.Abp.Identity.MongoDB IMongoCollection Roles { get; } IMongoCollection ClaimTypes { get; } + + IMongoCollection OrganizationUnits { get; } } } \ No newline at end of file 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 9c3b8bcd0e..f309cdcf7d 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 @@ -9,6 +9,7 @@ using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Guids; +using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB @@ -17,14 +18,14 @@ namespace Volo.Abp.Identity.MongoDB { private readonly IGuidGenerator _guidGenerator; - public MongoIdentityUserRepository(IMongoDbContextProvider dbContextProvider, IGuidGenerator guidGenerator) + public MongoIdentityUserRepository(IMongoDbContextProvider dbContextProvider, IGuidGenerator guidGenerator) : base(dbContextProvider) { _guidGenerator = guidGenerator; } public async Task FindByNormalizedUserNameAsync( - string normalizedUserName, + string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -36,7 +37,7 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetRoleNamesAsync( - Guid id, + Guid id, CancellationToken cancellationToken = default) { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)).ConfigureAwait(false); @@ -44,9 +45,20 @@ namespace Volo.Abp.Identity.MongoDB return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + public async Task> GetRoleNamesInOrganizationUnitAsync( + Guid id, + CancellationToken cancellationToken = default) + { + var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)).ConfigureAwait(false); + 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.Id)); + return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + public async Task FindByLoginAsync( - string loginProvider, - string providerKey, + string loginProvider, + string providerKey, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -74,7 +86,7 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetListByNormalizedRoleNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -92,9 +104,9 @@ namespace Volo.Abp.Identity.MongoDB public async Task> GetListAsync( string sorting = null, - int maxResultCount = int.MaxValue, - int skipCount = 0, - string filter = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -121,6 +133,16 @@ namespace Volo.Abp.Identity.MongoDB return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + public async Task> GetOrganizationUnitsAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)).ConfigureAwait(false); + var organizationUnitIds = user.OrganizationUnits.Select(r => r.OrganizationUnitId); + return await DbContext.OrganizationUnits.AsQueryable().Where(ou => organizationUnitIds.Contains(ou.Id)).ToListAsync().ConfigureAwait(false); + } + public async Task GetCountAsync( string filter = null, CancellationToken cancellationToken = default) 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 new file mode 100644 index 0000000000..8e904b2c5b --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -0,0 +1,66 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories.MongoDB; +using Volo.Abp.Guids; +using Volo.Abp.Identity.Organizations; +using Volo.Abp.MongoDB; + +namespace Volo.Abp.Identity.MongoDB +{ + public class MongoOrganizationUnitRepository : MongoDbRepository, IOrganizationUnitRepository + { + private readonly IGuidGenerator _guidGenerator; + + public MongoOrganizationUnitRepository( + IMongoDbContextProvider dbContextProvider, + IGuidGenerator guidGenerator) + : base(dbContextProvider) + { + _guidGenerator = guidGenerator; + } + + public async Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default) + { + return await DbContext.OrganizationUnits.AsQueryable().Where(ou => ou.ParentId == parentId) + .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + + public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default) + { + return await DbContext.OrganizationUnits.AsQueryable() + .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) + .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + + public async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) + { + return await DbContext.OrganizationUnits.AsQueryable() + .Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + + public async Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) + { + return await DbContext.OrganizationUnits.AsQueryable() + .FirstOrDefaultAsync( + ou => ou.DisplayName == displayName, + GetCancellationToken(cancellationToken) + ).ConfigureAwait(false); + } + + public Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index f19716b8ee..5be4c7d517 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -89,9 +89,9 @@ namespace Volo.Abp.Identity { var ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", true).ConfigureAwait(false); var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); - await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole.Id, ou.Id); + await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole, ou); - //TODO: This method has a bug: includeDetails not work + //TODO: This method has a bug: includeDetails not work or add role not work ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", includeDetails: true).ConfigureAwait(false); ou.Roles.FirstOrDefault().Id.ShouldBe(adminRole.Id); } diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/OrganizationUnitRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/OrganizationUnitRepository_Tests.cs new file mode 100644 index 0000000000..d60611b2b6 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/OrganizationUnitRepository_Tests.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.Identity.MongoDB +{ + public class OrganizationUnitRepository_Tests : OrganizationUnitRepository_Tests + { + } +} From 8f1df3f2847a63b9170a3267beeb18aa72cce0a5 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Mon, 6 Jan 2020 11:43:29 +0300 Subject: [PATCH 07/35] remove organizationUnitRole add, remove --- .../IOrganizationUnitRepository.cs | 3 --- .../Organizations/OrganizationUnitManager.cs | 10 +++++----- .../EfCoreOrganizationUnitRepository.cs | 18 ------------------ .../MongoDB/MongoOrganizationUnitRepository.cs | 10 ---------- .../Identity_Repository_Resolve_Tests.cs | 2 -- 5 files changed, 5 insertions(+), 38 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index fad8b044f8..81bd90acea 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -18,8 +18,5 @@ namespace Volo.Abp.Identity.Organizations Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default); - Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default); - - Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs index 356201aef9..9ed2a54697 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -156,16 +156,16 @@ namespace Volo.Abp.Identity.Organizations ); } - public virtual async Task AddRoleToOrganizationUnitAsync(IdentityRole role, OrganizationUnit ou) + public virtual Task AddRoleToOrganizationUnitAsync(IdentityRole role, OrganizationUnit ou) { var currentRoles = ou.Roles; if (currentRoles.Any(r => r.Id == role.Id)) { - return ; + return Task.FromResult(0); } ou.AddRole(role.Id); - await _organizationUnitRepository.AddRole(ou, role, ou.TenantId); + return Task.FromResult(0); } public virtual async Task RemoveRoleFromOrganizationUnitAsync(Guid roleId, Guid ouId) @@ -176,10 +176,10 @@ namespace Volo.Abp.Identity.Organizations ); } - public virtual async Task RemoveRoleFromOrganizationUnitAsync(IdentityRole role, OrganizationUnit organizationUnit) + public virtual Task RemoveRoleFromOrganizationUnitAsync(IdentityRole role, OrganizationUnit organizationUnit) { - await _organizationUnitRepository.RemoveRole(organizationUnit, role, organizationUnit.TenantId); organizationUnit.RemoveRole(role.Id); + return Task.FromResult(0); } } } 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 2519efc617..7d4a8a1fa0 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 @@ -52,24 +52,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore ).ConfigureAwait(false); } - public Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) - { - var our = new OrganizationUnitRole(tenantId, role.Id, ou.Id); - DbContext.Set().Add(our); - return Task.FromResult(0); - } - - public async Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) - { - var context = DbContext.Set(); - var our = await context.FirstOrDefaultAsync(our => - our.OrganizationUnitId == ou.Id && - our.RoleId == role.Id && - our.TenantId == tenantId - ); - DbContext.Set().Remove(our); - } - public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); 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 8e904b2c5b..483daf31a7 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 @@ -52,15 +52,5 @@ namespace Volo.Abp.Identity.MongoDB GetCancellationToken(cancellationToken) ).ConfigureAwait(false); } - - public Task AddRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public Task RemoveRole(OrganizationUnit ou, IdentityRole role, Guid? tenantId, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs index 480e72f4cc..0b8821d363 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs @@ -22,8 +22,6 @@ namespace Volo.Abp.Identity ServiceProvider.GetService>().ShouldNotBeNull(); ServiceProvider.GetService().ShouldNotBeNull(); - ServiceProvider.GetService>().ShouldNotBeNull(); - ServiceProvider.GetService>().ShouldNotBeNull(); ServiceProvider.GetService().ShouldNotBeNull(); } } From 1fa0e2852c1c4977c2fe66fc32f68ea5686f4b24 Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Mon, 6 Jan 2020 13:00:56 +0300 Subject: [PATCH 08/35] add organizationUnits foreignKey to User --- .../IdentityDbContextModelBuilderExtensions.cs | 3 ++- .../Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs | 2 +- .../Volo/Abp/Identity/OrganizationUnitManager_Tests.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 78daa5217b..6ee5b52479 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -41,6 +41,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasMany(u => u.Logins).WithOne().HasForeignKey(ul => ul.UserId).IsRequired(); b.HasMany(u => u.Roles).WithOne().HasForeignKey(ur => ur.UserId).IsRequired(); b.HasMany(u => u.Tokens).WithOne().HasForeignKey(ur => ur.UserId).IsRequired(); + b.HasMany(u => u.OrganizationUnits).WithOne().HasForeignKey(ur => ur.UserId).IsRequired(); b.HasIndex(u => u.NormalizedUserName); b.HasIndex(u => u.NormalizedEmail); @@ -151,7 +152,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasMany(ou => ou.Children).WithOne().HasForeignKey(ou => ou.ParentId); b.HasMany(ou => ou.Roles).WithOne().HasForeignKey(our => our.OrganizationUnitId).IsRequired(); - b.HasIndex(ou => ou.ParentId); + b.HasIndex(ou => ou.Code); }); builder.Entity(b => diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs index f6bf256576..7f0d611d92 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs @@ -35,7 +35,7 @@ namespace Volo.Abp.Identity.MongoDB builder.Entity(b => { - b.CollectionName = options.CollectionPrefix + "OrganizationUnit"; + b.CollectionName = options.CollectionPrefix + "OrganizationUnits"; }); } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 5be4c7d517..0ed3618318 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -91,7 +91,7 @@ namespace Volo.Abp.Identity var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole, ou); - //TODO: This method has a bug: includeDetails not work or add role not work + //TODO: This method has a bug: add role not work ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", includeDetails: true).ConfigureAwait(false); ou.Roles.FirstOrDefault().Id.ShouldBe(adminRole.Id); } From 4db9a9a42ef73ac04aaf34670dad0ba6d2be25dd Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Tue, 14 Jan 2020 23:12:55 +0300 Subject: [PATCH 09/35] get users by organization unit --- .../Abp/Identity/IIdentityUserRepository.cs | 10 +++++ .../Volo/Abp/Identity/IdentityUserManager.cs | 37 +++++++++++++----- .../IOrganizationUnitRepository.cs | 2 +- .../EfCoreIdentityUserRepository.cs | 26 +++++++++++++ .../EfCoreOrganizationUnitRepository.cs | 2 +- .../MongoDB/MongoIdentityUserRepository.cs | 38 ++++++++++++++++++- .../MongoOrganizationUnitRepository.cs | 2 +- .../Abp/Identity/IdentityUserManager_Tests.cs | 6 +-- .../Identity/OrganizationUnitManager_Tests.cs | 32 ++++++++-------- .../Identity/IdentityUserRepository_Tests.cs | 26 +++++++++++++ .../Volo/Abp/Identity/LazyLoading_Tests.cs | 2 +- .../OrganizationUnitRepository_Tests.cs | 4 +- 12 files changed, 151 insertions(+), 36 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 04ff5c2e5f..ef03c86b7a 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 @@ -71,6 +71,16 @@ namespace Volo.Abp.Identity bool includeDetails = false, CancellationToken cancellationToken = default); + Task> GetUsersInOrganizationUnitAsync( + Guid organizationUnitId, + CancellationToken cancellationToken = default + ); + + Task> GetUsersInOrganizationUnitWithChildrenAsync( + string code, + CancellationToken cancellationToken = default + ); + Task GetCountAsync( string filter = null, 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 87faf866cb..644c21df5c 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 @@ -93,8 +93,8 @@ namespace Volo.Abp.Identity public virtual async Task IsInOrganizationUnitAsync(Guid userId, Guid ouId) { return await IsInOrganizationUnitAsync( - await GetByIdAsync(userId), - await _organizationUnitRepository.GetAsync(ouId) + await GetByIdAsync(userId).ConfigureAwait(false), + await _organizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) ); } @@ -106,8 +106,8 @@ namespace Volo.Abp.Identity public virtual async Task AddToOrganizationUnitAsync(Guid userId, Guid ouId) { await AddToOrganizationUnitAsync( - await _identityUserRepository.GetAsync(userId, true), - await _organizationUnitRepository.GetAsync(ouId) + await _identityUserRepository.GetAsync(userId, true).ConfigureAwait(false), + await _organizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) ); } @@ -130,8 +130,8 @@ namespace Volo.Abp.Identity public virtual async Task RemoveFromOrganizationUnitAsync(Guid userId, Guid ouId) { await RemoveFromOrganizationUnitAsync( - await _identityUserRepository.GetAsync(userId, true), - await _organizationUnitRepository.GetAsync(ouId) + await _identityUserRepository.GetAsync(userId, true).ConfigureAwait(false), + await _organizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) ); } @@ -145,7 +145,7 @@ namespace Volo.Abp.Identity public virtual async Task SetOrganizationUnitsAsync(Guid userId, params Guid[] organizationUnitIds) { await SetOrganizationUnitsAsync( - await _identityUserRepository.GetAsync(userId, true), + await _identityUserRepository.GetAsync(userId, true).ConfigureAwait(false), organizationUnitIds ); } @@ -164,7 +164,7 @@ namespace Volo.Abp.Identity { if (!organizationUnitIds.Contains(currentOu.Id)) { - await RemoveFromOrganizationUnitAsync(user.Id, currentOu.Id); + await RemoveFromOrganizationUnitAsync(user.Id, currentOu.Id).ConfigureAwait(false); } } @@ -175,7 +175,7 @@ namespace Volo.Abp.Identity { await AddToOrganizationUnitAsync( user, - await _organizationUnitRepository.GetAsync(organizationUnitId) + await _organizationUnitRepository.GetAsync(organizationUnitId).ConfigureAwait(false) ); } } @@ -197,7 +197,24 @@ namespace Volo.Abp.Identity var ouOfUser = user.OrganizationUnits; - return await _organizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)); + return await _organizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)).ConfigureAwait(false); + } + + [UnitOfWork] + public virtual async Task> GetUsersInOrganizationUnitAsync(OrganizationUnit organizationUnit, bool includeChildren = false) + { + if (includeChildren) + { + return await _identityUserRepository + .GetUsersInOrganizationUnitWithChildrenAsync(organizationUnit.Code) + .ConfigureAwait(false); + } + else + { + return await _identityUserRepository + .GetUsersInOrganizationUnitAsync(organizationUnit.Id) + .ConfigureAwait(false); + } } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index 81bd90acea..4d90ba3a1d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.Identity.Organizations Task> GetListAsync(bool includeDetails = true, CancellationToken cancellationToken = default); - Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default); + Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, 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 587c2043ac..0564668225 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 @@ -170,6 +170,32 @@ namespace Volo.Abp.Identity.EntityFrameworkCore return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + public virtual async Task> GetUsersInOrganizationUnitAsync( + Guid organizationUnitId, + CancellationToken cancellationToken = default + ) + { + var query = from userOu in DbContext.Set() + join user in DbSet on userOu.UserId equals user.Id + where userOu.OrganizationUnitId == organizationUnitId + select user; + return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + + + public virtual async Task> GetUsersInOrganizationUnitWithChildrenAsync( + string code, + CancellationToken cancellationToken = default + ) + { + var query = from userOu in DbContext.Set() + join user in DbSet on userOu.UserId equals user.Id + join ou in DbContext.Set() on userOu.OrganizationUnitId equals ou.Id + where ou.Code.StartsWith(code) + select user; + return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + } + public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); 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 7d4a8a1fa0..0c4a486481 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 @@ -42,7 +42,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } - public async Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) + public async Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet .IncludeDetails(includeDetails) 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 f309cdcf7d..8da8bd9cf0 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 @@ -140,7 +140,10 @@ namespace Volo.Abp.Identity.MongoDB { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)).ConfigureAwait(false); var organizationUnitIds = user.OrganizationUnits.Select(r => r.OrganizationUnitId); - return await DbContext.OrganizationUnits.AsQueryable().Where(ou => organizationUnitIds.Contains(ou.Id)).ToListAsync().ConfigureAwait(false); + return await DbContext.OrganizationUnits.AsQueryable() + .Where(ou => organizationUnitIds.Contains(ou.Id)) + .ToListAsync(GetCancellationToken(cancellationToken)) + .ConfigureAwait(false); } public async Task GetCountAsync( @@ -156,5 +159,38 @@ namespace Volo.Abp.Identity.MongoDB ) .LongCountAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + + public async Task> GetUsersInOrganizationUnitAsync( + Guid organizationUnitId, + CancellationToken cancellationToken = default) + { + var organizationUnitUserIds = await DbContext.Users.AsQueryable() + .SelectMany(u => u.OrganizationUnits) + .Where(ou => ou.OrganizationUnitId == organizationUnitId) + .Select(ouu => ouu.Id) + .ToListAsync(GetCancellationToken(cancellationToken)) + .ConfigureAwait(false); + + return await GetMongoQueryable() + .Where(u => u.OrganizationUnits.Any(uou => organizationUnitUserIds.Contains(uou.Id))) + .ToListAsync(GetCancellationToken(cancellationToken)) + .ConfigureAwait(false); + } + + public async Task> GetUsersInOrganizationUnitWithChildrenAsync( + string code, + CancellationToken cancellationToken = default) + { + var organizationUnitIds = await DbContext.OrganizationUnits.AsQueryable() + .Where(ou => ou.Code.StartsWith(code)) + .Select(ou => ou.Id) + .ToListAsync(GetCancellationToken(cancellationToken)) + .ConfigureAwait(false); + + return await GetMongoQueryable() + .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) + .ToListAsync(GetCancellationToken(cancellationToken)) + .ConfigureAwait(false); + } } } \ No newline at end of file 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 483daf31a7..cede5e46de 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 @@ -44,7 +44,7 @@ namespace Volo.Abp.Identity.MongoDB .Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } - public async Task GetOrganizationUnit(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) + public async Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbContext.OrganizationUnits.AsQueryable() .FirstOrDefaultAsync( diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index b2749a2f4a..444e6e26e1 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -97,7 +97,7 @@ namespace Volo.Abp.Identity _lookupNormalizer.NormalizeName("david")).ConfigureAwait(false); user.ShouldNotBeNull(); - var ou = await _organizationUnitRepository.GetOrganizationUnit( + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync( _lookupNormalizer.NormalizeName("OU11")).ConfigureAwait(false); ou.ShouldNotBeNull(); @@ -120,7 +120,7 @@ namespace Volo.Abp.Identity { using (var uow = _unitOfWorkManager.Begin()) { - var ou = await _organizationUnitRepository.GetOrganizationUnit( + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync( _lookupNormalizer.NormalizeName("OU111")).ConfigureAwait(false); ou.ShouldNotBeNull(); @@ -128,7 +128,7 @@ namespace Volo.Abp.Identity _lookupNormalizer.NormalizeName("john.nash")).ConfigureAwait(false); user.ShouldNotBeNull(); - var ouNew = await _organizationUnitRepository.GetOrganizationUnit( + var ouNew = await _organizationUnitRepository.GetOrganizationUnitAsync( _lookupNormalizer.NormalizeName("OU2")).ConfigureAwait(false); ouNew.ShouldNotBeNull(); diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 0ed3618318..539af5d1a1 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -31,55 +31,55 @@ namespace Volo.Abp.Identity { await _organizationUnitManager.CreateAsync(new OrganizationUnit(null, "Root 1")); - var root1 = await _organizationUnitRepository.GetOrganizationUnit("Root 1").ConfigureAwait(false); + var root1 = await _organizationUnitRepository.GetOrganizationUnitAsync("Root 1").ConfigureAwait(false); root1.ShouldNotBeNull(); } [Fact] public async Task UpdateAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); ou.Code = OrganizationUnit.CreateCode(123); await _organizationUnitManager.UpdateAsync(ou); - var ouAfterChange = await _organizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + var ouAfterChange = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); ouAfterChange.Code.ShouldContain("123"); } [Fact] public async Task DeleteAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnit("OU11").ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11").ConfigureAwait(false); await _organizationUnitManager.DeleteAsync(ou.Id); - (await _organizationUnitRepository.GetOrganizationUnit("OU11").ConfigureAwait(false)).ShouldBeNull(); + (await _organizationUnitRepository.GetOrganizationUnitAsync("OU11").ConfigureAwait(false)).ShouldBeNull(); } [Fact] public async Task MoveAsync() { - var ou1 = await _organizationUnitRepository.GetOrganizationUnit("OU1").ConfigureAwait(false); - var ou2 = await _organizationUnitRepository.GetOrganizationUnit("OU2").ConfigureAwait(false); + var ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1").ConfigureAwait(false); + var ou2 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU2").ConfigureAwait(false); await _organizationUnitManager.MoveAsync(ou1.Id, ou2.Id); - ou1 = await _organizationUnitRepository.GetOrganizationUnit("OU1").ConfigureAwait(false); + ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1").ConfigureAwait(false); ou1.ParentId.ShouldBe(ou2.Id); ou1.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2)); - var ou11 = await _organizationUnitRepository.GetOrganizationUnit("OU11").ConfigureAwait(false); + var ou11 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11").ConfigureAwait(false); ou11.ParentId.ShouldBe(ou1.Id); ou11.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1)); - var ou111 = await _organizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + var ou111 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); ou111.ParentId.ShouldBe(ou11.Id); ou111.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 1)); - var ou112 = await _organizationUnitRepository.GetOrganizationUnit("OU112").ConfigureAwait(false); + var ou112 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU112").ConfigureAwait(false); ou112.ParentId.ShouldBe(ou11.Id); ou112.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 2)); - var ou12 = await _organizationUnitRepository.GetOrganizationUnit("OU12").ConfigureAwait(false); + var ou12 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU12").ConfigureAwait(false); ou12.ParentId.ShouldBe(ou1.Id); ou12.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 2)); } @@ -87,24 +87,24 @@ namespace Volo.Abp.Identity [Fact] public async Task AddRoleToOrganizationUnitAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", true).ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true).ConfigureAwait(false); var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole, ou); //TODO: This method has a bug: add role not work - ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", includeDetails: true).ConfigureAwait(false); + ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true).ConfigureAwait(false); ou.Roles.FirstOrDefault().Id.ShouldBe(adminRole.Id); } [Fact] public async Task RemoveRoleFromOrganizationUnitAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", true).ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true).ConfigureAwait(false); var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole.Id, ou.Id); await _organizationUnitManager.RemoveRoleFromOrganizationUnitAsync(adminRole.Id, ou.Id); - ou = await _organizationUnitRepository.GetOrganizationUnit("OU1", includeDetails: true).ConfigureAwait(false); + ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true).ConfigureAwait(false); ou.Roles.FirstOrDefault(r => r.RoleId == adminRole.Id).ShouldBeNull(); } } 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 f4719a63a7..7433e4c202 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 @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Xunit; @@ -15,11 +16,13 @@ namespace Volo.Abp.Identity { protected IIdentityUserRepository UserRepository { get; } protected ILookupNormalizer LookupNormalizer { get; } + protected IOrganizationUnitRepository OrganizationUnitRepository { get; } protected IdentityUserRepository_Tests() { UserRepository = ServiceProvider.GetRequiredService(); LookupNormalizer = ServiceProvider.GetRequiredService(); + OrganizationUnitRepository = ServiceProvider.GetRequiredService(); } [Fact] @@ -128,6 +131,22 @@ namespace Volo.Abp.Identity (await UserRepository.GetCountAsync("undefined-username").ConfigureAwait(false)).ShouldBe(0); } + [Fact] + public async Task GetUsersInOrganizationUnitAsync() + { + var users = await UserRepository.GetUsersInOrganizationUnitAsync((await GetOU("OU111").ConfigureAwait(false)).Id).ConfigureAwait(false); + users.ShouldNotBeNull(); + users.Count.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task GetUsersInOrganizationUnitWithChildrenAsync() + { + var users = await UserRepository.GetUsersInOrganizationUnitWithChildrenAsync((await GetOU("OU111").ConfigureAwait(false)).Code).ConfigureAwait(false); + users.ShouldNotBeNull(); + users.Count.ShouldBeGreaterThan(0); + } + [Fact] public async Task Should_Eager_Load_User_Collections() { @@ -148,5 +167,12 @@ namespace Volo.Abp.Identity john.OrganizationUnits.ShouldNotBeNull(); john.OrganizationUnits.Any().ShouldBeTrue(); } + + private async Task GetOU(string diplayName) + { + var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync(diplayName).ConfigureAwait(false); + organizationUnit.ShouldNotBeNull(); + return organizationUnit; + } } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs index cd09c1209e..3db968232b 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs @@ -70,7 +70,7 @@ namespace Volo.Abp.Identity { using (var uow = GetRequiredService().Begin()) { - var ou = await OrganizationUnitRepository.GetOrganizationUnit(LookupNormalizer.NormalizeName("OU111"), includeDetails: false).ConfigureAwait(false); + var ou = await OrganizationUnitRepository.GetOrganizationUnitAsync(LookupNormalizer.NormalizeName("OU111"), includeDetails: false).ConfigureAwait(false); ou.Roles.ShouldNotBeNull(); //? ou.Roles.Any().ShouldBeTrue(); 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 4d6e07f447..20452a90f5 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 @@ -52,9 +52,9 @@ namespace Volo.Abp.Identity } [Fact] - public async Task GetOrganizationUnit() + public async Task GetOrganizationUnitAsync() { - var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnit("OU111").ConfigureAwait(false); + var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); organizationUnit.ShouldNotBeNull(); } From 876f441cce95ab807812b66fbdce4aee0ad4087a Mon Sep 17 00:00:00 2001 From: Mehmet Perk Date: Wed, 15 Jan 2020 20:44:15 +0300 Subject: [PATCH 10/35] IdentityUserOrganizationUnit and OrganizationUnitRole do not need a primary key --- .../Volo/Abp/Identity/IdentityUserManager.cs | 2 +- .../Identity/IdentityUserOrganizationUnit.cs | 7 ++++++- .../Organizations/OrganizationUnitManager.cs | 2 +- .../Organizations/OrganizationUnitRole.cs | 6 +++++- .../MongoDB/MongoIdentityUserRepository.cs | 18 ++++++------------ .../Identity/OrganizationUnitManager_Tests.cs | 2 +- 6 files changed, 20 insertions(+), 17 deletions(-) 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 644c21df5c..242ca6a908 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 @@ -117,7 +117,7 @@ namespace Volo.Abp.Identity var currentOus = user.OrganizationUnits; - if (currentOus.Any(cou => cou.Id == ou.Id)) + if (currentOus.Any(cou => cou.OrganizationUnitId == ou.Id && cou.UserId == user.Id)) { return; } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs index 3721210bd6..12bf8860c8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.Identity /// /// Represents membership of a User to an OU. /// - public class IdentityUserOrganizationUnit : CreationAuditedEntity, IMultiTenant, ISoftDelete + public class IdentityUserOrganizationUnit : CreationAuditedEntity, IMultiTenant, ISoftDelete { /// @@ -50,5 +50,10 @@ namespace Volo.Abp.Identity UserId = userId; OrganizationUnitId = organizationUnitId; } + + public override object[] GetKeys() + { + return new object[] { UserId, OrganizationUnitId }; + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs index 9ed2a54697..fac2ef743a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -160,7 +160,7 @@ namespace Volo.Abp.Identity.Organizations { var currentRoles = ou.Roles; - if (currentRoles.Any(r => r.Id == role.Id)) + if (currentRoles.Any(r => r.OrganizationUnitId == ou.Id && r.RoleId == role.Id)) { return Task.FromResult(0); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs index cd9d9d3ac4..de43e8bec4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.Identity.Organizations /// /// Represents membership of a User to an OU. /// - public class OrganizationUnitRole : CreationAuditedEntity, IMultiTenant, ISoftDelete + public class OrganizationUnitRole : CreationAuditedEntity, IMultiTenant, ISoftDelete { /// /// TenantId of this entity. @@ -50,5 +50,9 @@ namespace Volo.Abp.Identity.Organizations OrganizationUnitId = organizationUnitId; } + public override object[] GetKeys() + { + return new object[] { OrganizationUnitId, RoleId }; + } } } 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 8da8bd9cf0..fc198c7883 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 @@ -52,7 +52,7 @@ namespace Volo.Abp.Identity.MongoDB var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)).ConfigureAwait(false); 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.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)).ConfigureAwait(false); } @@ -164,17 +164,11 @@ namespace Volo.Abp.Identity.MongoDB Guid organizationUnitId, CancellationToken cancellationToken = default) { - var organizationUnitUserIds = await DbContext.Users.AsQueryable() - .SelectMany(u => u.OrganizationUnits) - .Where(ou => ou.OrganizationUnitId == organizationUnitId) - .Select(ouu => ouu.Id) - .ToListAsync(GetCancellationToken(cancellationToken)) - .ConfigureAwait(false); - - return await GetMongoQueryable() - .Where(u => u.OrganizationUnits.Any(uou => organizationUnitUserIds.Contains(uou.Id))) - .ToListAsync(GetCancellationToken(cancellationToken)) - .ConfigureAwait(false); + var result = await GetMongoQueryable() + .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnitId)) + .ToListAsync(GetCancellationToken(cancellationToken)) + .ConfigureAwait(false); + return result; } public async Task> GetUsersInOrganizationUnitWithChildrenAsync( diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 539af5d1a1..7c6c2582ad 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -93,7 +93,7 @@ namespace Volo.Abp.Identity //TODO: This method has a bug: add role not work ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true).ConfigureAwait(false); - ou.Roles.FirstOrDefault().Id.ShouldBe(adminRole.Id); + ou.Roles.FirstOrDefault().RoleId.ShouldBe(adminRole.Id); } [Fact] From f6ecf06f2533b1eefd590ffa94e503613fdb65ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 11:44:49 +0300 Subject: [PATCH 11/35] Fix build errors --- .../Volo/Abp/Identity/IdentityUserManager.cs | 11 ++++++----- .../Volo/Abp/Identity/IdentityUserStore.cs | 4 ++-- .../Volo/Abp/Identity/IdentityUserManager_Tests.cs | 12 +++++++----- 3 files changed, 15 insertions(+), 12 deletions(-) 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 b437d9fae9..1326626262 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 @@ -11,7 +11,6 @@ using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; using Volo.Abp.Identity.Organizations; -using Volo.Abp.Domain.Repositories; using Volo.Abp.Threading; using Volo.Abp.Uow; using Volo.Abp.Settings; @@ -123,7 +122,7 @@ namespace Volo.Abp.Identity public virtual async Task AddToOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, _cancellationTokenProvider.Token).ConfigureAwait(false); + await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); var currentOus = user.OrganizationUnits; @@ -147,7 +146,7 @@ namespace Volo.Abp.Identity public virtual async Task RemoveFromOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, _cancellationTokenProvider.Token).ConfigureAwait(false); + await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); user.RemoveOrganizationUnit(ou.Id); } @@ -203,7 +202,7 @@ namespace Volo.Abp.Identity [UnitOfWork] public virtual async Task> GetOrganizationUnitsAsync(IdentityUser user) { - await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, _cancellationTokenProvider.Token).ConfigureAwait(false); + await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); var ouOfUser = user.OrganizationUnits; @@ -211,7 +210,8 @@ namespace Volo.Abp.Identity } [UnitOfWork] - public virtual async Task> GetUsersInOrganizationUnitAsync(OrganizationUnit organizationUnit, bool includeChildren = false) + public virtual async Task> GetUsersInOrganizationUnitAsync(OrganizationUnit organizationUnit, + bool includeChildren = false) { if (includeChildren) { @@ -225,6 +225,7 @@ namespace Volo.Abp.Identity .GetUsersInOrganizationUnitAsync(organizationUnit.Id) .ConfigureAwait(false); } + } public virtual async Task AddDefaultRolesAsync([NotNull] IdentityUser user) { 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 cccf524031..c13d3f33bd 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 @@ -366,9 +366,9 @@ namespace Volo.Abp.Identity Check.NotNull(user, nameof(user)); - var userRoles = await _userRepository.GetRoleNamesAsync(user.Id, cancellationToken: cancellationToken); + var userRoles = await UserRepository.GetRoleNamesAsync(user.Id, cancellationToken: cancellationToken); - var userOrganizationUnitRoles = await _userRepository.GetRoleNamesInOrganizationUnitAsync(user.Id, cancellationToken: cancellationToken); + var userOrganizationUnitRoles = await UserRepository.GetRoleNamesInOrganizationUnitAsync(user.Id, cancellationToken: cancellationToken); return userRoles.Union(userOrganizationUnitRoles).ToList(); } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index ff880f0ecc..2d259b0859 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -118,10 +118,11 @@ namespace Volo.Abp.Identity await uow.CompleteAsync().ConfigureAwait(false); + } } - - [Fact] - public async Task AddDefaultRolesAsync_In_Same_Uow() + + [Fact] + public async Task AddDefaultRolesAsync_In_Same_Uow() { await CreateRandomDefaultRoleAsync(); @@ -146,6 +147,7 @@ namespace Volo.Abp.Identity await uow.CompleteAsync(); } + } [Fact] public async Task SetOrganizationUnits_Should_Remove() @@ -175,8 +177,8 @@ namespace Volo.Abp.Identity } } - [Fact] -public async Task AddDefaultRolesAsync_In_Different_Uow() + [Fact] + public async Task AddDefaultRolesAsync_In_Different_Uow() { await CreateRandomDefaultRoleAsync(); From fef2488e9dd1b15f5b43b89a8c71d5413aa18d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 14:24:14 +0300 Subject: [PATCH 12/35] Refactor --- .../IdentityUserCreateOrUpdateDtoBase.cs | 1 + .../AbpIdentitySettingDefinitionProvider.cs | 36 +++++++++----- .../Volo/Abp/Identity/IdentityUser.cs | 25 +++++----- .../Volo/Abp/Identity/IdentityUserManager.cs | 47 +++++++++---------- .../Identity/IdentityUserOrganizationUnit.cs | 14 ++---- 5 files changed, 64 insertions(+), 59 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs index c6cf2e18b3..f14dce6181 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs @@ -32,6 +32,7 @@ namespace Volo.Abp.Identity [CanBeNull] public string[] RoleNames { get; set; } + [CanBeNull] public Guid[] OrganizationUnits { get; set; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs index f6ba0fad3e..1fdd2dd451 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentitySettingDefinitionProvider.cs @@ -33,71 +33,83 @@ namespace Volo.Abp.Identity new SettingDefinition( IdentitySettingNames.Password.RequireLowercase, - true.ToString(), L("DisplayName:Abp.Identity.Password.RequireLowercase"), + true.ToString(), + L("DisplayName:Abp.Identity.Password.RequireLowercase"), L("Description:Abp.Identity.Password.RequireLowercase"), true), new SettingDefinition( IdentitySettingNames.Password.RequireUppercase, - true.ToString(), L("DisplayName:Abp.Identity.Password.RequireUppercase"), + true.ToString(), + L("DisplayName:Abp.Identity.Password.RequireUppercase"), L("Description:Abp.Identity.Password.RequireUppercase"), true), new SettingDefinition( IdentitySettingNames.Password.RequireDigit, - true.ToString(), L("DisplayName:Abp.Identity.Password.RequireDigit"), + true.ToString(), + L("DisplayName:Abp.Identity.Password.RequireDigit"), L("Description:Abp.Identity.Password.RequireDigit"), true), new SettingDefinition( IdentitySettingNames.Lockout.AllowedForNewUsers, - true.ToString(), L("DisplayName:Abp.Identity.Lockout.AllowedForNewUsers"), + true.ToString(), + L("DisplayName:Abp.Identity.Lockout.AllowedForNewUsers"), L("Description:Abp.Identity.Lockout.AllowedForNewUsers"), true), new SettingDefinition( IdentitySettingNames.Lockout.LockoutDuration, - (5 * 60).ToString(), L("DisplayName:Abp.Identity.Lockout.LockoutDuration"), + (5 * 60).ToString(), + L("DisplayName:Abp.Identity.Lockout.LockoutDuration"), L("Description:Abp.Identity.Lockout.LockoutDuration"), true), new SettingDefinition( IdentitySettingNames.Lockout.MaxFailedAccessAttempts, - 5.ToString(), L("DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts"), + 5.ToString(), + L("DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts"), L("Description:Abp.Identity.Lockout.MaxFailedAccessAttempts"), true), new SettingDefinition( IdentitySettingNames.SignIn.RequireConfirmedEmail, - false.ToString(), L("DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail"), + false.ToString(), + L("DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail"), L("Description:Abp.Identity.SignIn.RequireConfirmedEmail"), true), new SettingDefinition( IdentitySettingNames.SignIn.EnablePhoneNumberConfirmation, - true.ToString(), L("DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation"), + true.ToString(), + L("DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation"), L("Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation"), true), new SettingDefinition( IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, - false.ToString(), L("DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber"), + false.ToString(), + L("DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber"), L("Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber"), true), new SettingDefinition( IdentitySettingNames.User.IsUserNameUpdateEnabled, - true.ToString(), L("DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled"), + true.ToString(), + L("DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled"), L("Description:Abp.Identity.User.IsUserNameUpdateEnabled"), true), new SettingDefinition( IdentitySettingNames.User.IsEmailUpdateEnabled, - true.ToString(), L("DisplayName:Abp.Identity.User.IsEmailUpdateEnabled"), + true.ToString(), + L("DisplayName:Abp.Identity.User.IsEmailUpdateEnabled"), L("Description:Abp.Identity.User.IsEmailUpdateEnabled"), true), new SettingDefinition( IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount, - int.MaxValue.ToString(), L("Identity.OrganizationUnit.MaxUserMembershipCount"), + int.MaxValue.ToString(), + L("Identity.OrganizationUnit.MaxUserMembershipCount"), L("Identity.OrganizationUnit.MaxUserMembershipCount"), true) ); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index e85a248517..2b68bef6a8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -8,8 +8,6 @@ using Microsoft.AspNetCore.Identity; using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Guids; -using Volo.Abp.Identity.Organizations; -using Volo.Abp.ObjectMapping; using Volo.Abp.Users; namespace Volo.Abp.Identity @@ -133,7 +131,6 @@ namespace Volo.Abp.Identity protected IdentityUser() { - ExtraProperties = new Dictionary(); } public IdentityUser(Guid id, [NotNull] string userName, [NotNull] string email, Guid? tenantId = null) @@ -286,33 +283,37 @@ namespace Volo.Abp.Identity public virtual void AddOrganizationUnit(Guid organizationUnitId) { - Check.NotNull(organizationUnitId, nameof(organizationUnitId)); - if (IsInOrganizationUnit(organizationUnitId)) { return; } - OrganizationUnits.Add(new IdentityUserOrganizationUnit(TenantId, Id, organizationUnitId)); + OrganizationUnits.Add( + new IdentityUserOrganizationUnit( + TenantId, + Id, + organizationUnitId + ) + ); } public virtual void RemoveOrganizationUnit(Guid organizationUnitId) { - Check.NotNull(organizationUnitId, nameof(organizationUnitId)); - if (!IsInOrganizationUnit(organizationUnitId)) { return; } - OrganizationUnits.RemoveAll(ou => ou.OrganizationUnitId == organizationUnitId); + OrganizationUnits.RemoveAll( + ou => ou.OrganizationUnitId == organizationUnitId + ); } public virtual bool IsInOrganizationUnit(Guid organizationUnitId) { - Check.NotNull(organizationUnitId, nameof(organizationUnitId)); - - return OrganizationUnits.Any(ou => ou.OrganizationUnitId == organizationUnitId); + return OrganizationUnits.Any( + ou => ou.OrganizationUnitId == organizationUnitId + ); } public override string ToString() 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 1326626262..6bd6aae029 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 @@ -22,14 +22,13 @@ namespace Volo.Abp.Identity { protected IIdentityRoleRepository RoleRepository { get; } protected IIdentityUserRepository UserRepository { get; } + protected IOrganizationUnitRepository OrganizationUnitRepository { get; } + protected IIdentityUserRepository IdentityUserRepository { get; } + protected ISettingProvider SettingProvider { get; } + protected ICancellationTokenProvider CancellationTokenProvider { get; } - protected IOrganizationUnitRepository _organizationUnitRepository { get; private set; } - protected IIdentityUserRepository _identityUserRepository { get; private set; } - private readonly ISettingProvider _settingProvider; protected override CancellationToken CancellationToken => CancellationTokenProvider.Token; - protected ICancellationTokenProvider CancellationTokenProvider { get; } - public IdentityUserManager( IdentityUserStore store, IIdentityRoleRepository roleRepository, @@ -57,9 +56,9 @@ namespace Volo.Abp.Identity services, logger) { - _organizationUnitRepository = organizationUnitRepository; - _identityUserRepository = identityUserRepository; - _settingProvider = settingProvider; + OrganizationUnitRepository = organizationUnitRepository; + IdentityUserRepository = identityUserRepository; + SettingProvider = settingProvider; RoleRepository = roleRepository; UserRepository = userRepository; CancellationTokenProvider = cancellationTokenProvider; @@ -81,7 +80,7 @@ namespace Volo.Abp.Identity Check.NotNull(user, nameof(user)); Check.NotNull(roleNames, nameof(roleNames)); - var currentRoleNames = await GetRolesAsync(user).ConfigureAwait(false); + var currentRoleNames = await GetRolesAsync(user); var result = await RemoveFromRolesAsync(user, currentRoleNames.Except(roleNames).Distinct()); if (!result.Succeeded) @@ -103,7 +102,7 @@ namespace Volo.Abp.Identity { return await IsInOrganizationUnitAsync( await GetByIdAsync(userId).ConfigureAwait(false), - await _organizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) + await OrganizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) ); } @@ -115,14 +114,14 @@ namespace Volo.Abp.Identity public virtual async Task AddToOrganizationUnitAsync(Guid userId, Guid ouId) { await AddToOrganizationUnitAsync( - await _identityUserRepository.GetAsync(userId, true).ConfigureAwait(false), - await _organizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) + await IdentityUserRepository.GetAsync(userId, true).ConfigureAwait(false), + await OrganizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) ); } public virtual async Task AddToOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); var currentOus = user.OrganizationUnits; @@ -139,14 +138,14 @@ namespace Volo.Abp.Identity public virtual async Task RemoveFromOrganizationUnitAsync(Guid userId, Guid ouId) { await RemoveFromOrganizationUnitAsync( - await _identityUserRepository.GetAsync(userId, true).ConfigureAwait(false), - await _organizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) + await IdentityUserRepository.GetAsync(userId, true).ConfigureAwait(false), + await OrganizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) ); } public virtual async Task RemoveFromOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); user.RemoveOrganizationUnit(ou.Id); } @@ -154,7 +153,7 @@ namespace Volo.Abp.Identity public virtual async Task SetOrganizationUnitsAsync(Guid userId, params Guid[] organizationUnitIds) { await SetOrganizationUnitsAsync( - await _identityUserRepository.GetAsync(userId, true).ConfigureAwait(false), + await IdentityUserRepository.GetAsync(userId, true).ConfigureAwait(false), organizationUnitIds ); } @@ -166,7 +165,7 @@ namespace Volo.Abp.Identity await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, organizationUnitIds.Length); - var currentOus = await _identityUserRepository.GetOrganizationUnitsAsync(user.Id).ConfigureAwait(false); + var currentOus = await IdentityUserRepository.GetOrganizationUnitsAsync(user.Id).ConfigureAwait(false); //Remove from removed OUs foreach (var currentOu in currentOus) @@ -184,7 +183,7 @@ namespace Volo.Abp.Identity { await AddToOrganizationUnitAsync( user, - await _organizationUnitRepository.GetAsync(organizationUnitId).ConfigureAwait(false) + await OrganizationUnitRepository.GetAsync(organizationUnitId).ConfigureAwait(false) ); } } @@ -192,7 +191,7 @@ namespace Volo.Abp.Identity private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(Guid? tenantId, int requestedCount) { - var maxCount = await _settingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount).ConfigureAwait(false); + var maxCount = await SettingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount).ConfigureAwait(false); if (requestedCount > maxCount) { throw new AbpException(string.Format("Can not set more than {0} organization unit for a user!", maxCount)); @@ -202,11 +201,11 @@ namespace Volo.Abp.Identity [UnitOfWork] public virtual async Task> GetOrganizationUnitsAsync(IdentityUser user) { - await _identityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); var ouOfUser = user.OrganizationUnits; - return await _organizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)).ConfigureAwait(false); + return await OrganizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)).ConfigureAwait(false); } [UnitOfWork] @@ -215,13 +214,13 @@ namespace Volo.Abp.Identity { if (includeChildren) { - return await _identityUserRepository + return await IdentityUserRepository .GetUsersInOrganizationUnitWithChildrenAsync(organizationUnit.Code) .ConfigureAwait(false); } else { - return await _identityUserRepository + return await IdentityUserRepository .GetUsersInOrganizationUnitAsync(organizationUnit.Id) .ConfigureAwait(false); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs index 12bf8860c8..fd701c5f17 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs @@ -1,5 +1,6 @@ using System; using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.Identity.Organizations; using Volo.Abp.MultiTenancy; namespace Volo.Abp.Identity @@ -21,7 +22,7 @@ namespace Volo.Abp.Identity public virtual Guid UserId { get; set; } /// - /// Id of the . + /// Id of the related . /// public virtual Guid OrganizationUnitId { get; set; } @@ -30,20 +31,11 @@ namespace Volo.Abp.Identity /// public virtual bool IsDeleted { get; set; } - /// - /// Initializes a new instance of the class. - /// - public IdentityUserOrganizationUnit() + protected IdentityUserOrganizationUnit() { } - /// - /// Initializes a new instance of the class. - /// - /// TenantId - /// Id of the User. - /// Id of the . public IdentityUserOrganizationUnit(Guid? tenantId, Guid userId, Guid organizationUnitId) { TenantId = tenantId; From eb068bfff813cdcc08694a4341e5dfa2cdca72a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 14:25:16 +0300 Subject: [PATCH 13/35] Remove ConfigureAwait(false) usages. --- .../Volo/Abp/Identity/IdentityUserManager.cs | 34 +++++++++--------- .../Organizations/OrganizationUnitManager.cs | 20 +++++------ .../EfCoreIdentityUserRepository.cs | 8 ++--- .../EfCoreOrganizationUnitRepository.cs | 10 +++--- .../MongoDB/MongoIdentityUserRepository.cs | 14 ++++---- .../MongoOrganizationUnitRepository.cs | 8 ++--- .../Abp/Identity/IdentityUserManager_Tests.cs | 20 +++++------ .../Identity/OrganizationUnitManager_Tests.cs | 36 +++++++++---------- .../Identity/AbpIdentityTestDataBuilder.cs | 26 +++++++------- .../Identity/IdentityUserRepository_Tests.cs | 6 ++-- .../Volo/Abp/Identity/LazyLoading_Tests.cs | 6 ++-- .../OrganizationUnitRepository_Tests.cs | 14 ++++---- 12 files changed, 101 insertions(+), 101 deletions(-) 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 6bd6aae029..6e97c1ad76 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 @@ -101,8 +101,8 @@ namespace Volo.Abp.Identity public virtual async Task IsInOrganizationUnitAsync(Guid userId, Guid ouId) { return await IsInOrganizationUnitAsync( - await GetByIdAsync(userId).ConfigureAwait(false), - await OrganizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) + await GetByIdAsync(userId), + await OrganizationUnitRepository.GetAsync(ouId) ); } @@ -114,14 +114,14 @@ namespace Volo.Abp.Identity public virtual async Task AddToOrganizationUnitAsync(Guid userId, Guid ouId) { await AddToOrganizationUnitAsync( - await IdentityUserRepository.GetAsync(userId, true).ConfigureAwait(false), - await OrganizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) + await IdentityUserRepository.GetAsync(userId, true), + await OrganizationUnitRepository.GetAsync(ouId) ); } public virtual async Task AddToOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); var currentOus = user.OrganizationUnits; @@ -138,14 +138,14 @@ namespace Volo.Abp.Identity public virtual async Task RemoveFromOrganizationUnitAsync(Guid userId, Guid ouId) { await RemoveFromOrganizationUnitAsync( - await IdentityUserRepository.GetAsync(userId, true).ConfigureAwait(false), - await OrganizationUnitRepository.GetAsync(ouId).ConfigureAwait(false) + await IdentityUserRepository.GetAsync(userId, true), + await OrganizationUnitRepository.GetAsync(ouId) ); } public virtual async Task RemoveFromOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); user.RemoveOrganizationUnit(ou.Id); } @@ -153,7 +153,7 @@ namespace Volo.Abp.Identity public virtual async Task SetOrganizationUnitsAsync(Guid userId, params Guid[] organizationUnitIds) { await SetOrganizationUnitsAsync( - await IdentityUserRepository.GetAsync(userId, true).ConfigureAwait(false), + await IdentityUserRepository.GetAsync(userId, true), organizationUnitIds ); } @@ -165,14 +165,14 @@ namespace Volo.Abp.Identity await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, organizationUnitIds.Length); - var currentOus = await IdentityUserRepository.GetOrganizationUnitsAsync(user.Id).ConfigureAwait(false); + var currentOus = await IdentityUserRepository.GetOrganizationUnitsAsync(user.Id); //Remove from removed OUs foreach (var currentOu in currentOus) { if (!organizationUnitIds.Contains(currentOu.Id)) { - await RemoveFromOrganizationUnitAsync(user.Id, currentOu.Id).ConfigureAwait(false); + await RemoveFromOrganizationUnitAsync(user.Id, currentOu.Id); } } @@ -183,7 +183,7 @@ namespace Volo.Abp.Identity { await AddToOrganizationUnitAsync( user, - await OrganizationUnitRepository.GetAsync(organizationUnitId).ConfigureAwait(false) + await OrganizationUnitRepository.GetAsync(organizationUnitId) ); } } @@ -191,7 +191,7 @@ namespace Volo.Abp.Identity private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(Guid? tenantId, int requestedCount) { - var maxCount = await SettingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount).ConfigureAwait(false); + var maxCount = await SettingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount); if (requestedCount > maxCount) { throw new AbpException(string.Format("Can not set more than {0} organization unit for a user!", maxCount)); @@ -201,11 +201,11 @@ namespace Volo.Abp.Identity [UnitOfWork] public virtual async Task> GetOrganizationUnitsAsync(IdentityUser user) { - await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token).ConfigureAwait(false); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); var ouOfUser = user.OrganizationUnits; - return await OrganizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)).ConfigureAwait(false); + return await OrganizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)); } [UnitOfWork] @@ -216,13 +216,13 @@ namespace Volo.Abp.Identity { return await IdentityUserRepository .GetUsersInOrganizationUnitWithChildrenAsync(organizationUnit.Code) - .ConfigureAwait(false); + ; } else { return await IdentityUserRepository .GetUsersInOrganizationUnitAsync(organizationUnit.Id) - .ConfigureAwait(false); + ; } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs index fac2ef743a..f4062a4d6c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -40,13 +40,13 @@ namespace Volo.Abp.Identity.Organizations { organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId); await ValidateOrganizationUnitAsync(organizationUnit); - await _organizationUnitRepository.InsertAsync(organizationUnit).ConfigureAwait(false); + await _organizationUnitRepository.InsertAsync(organizationUnit); } public virtual async Task UpdateAsync(OrganizationUnit organizationUnit) { await ValidateOrganizationUnitAsync(organizationUnit); - await _organizationUnitRepository.UpdateAsync(organizationUnit).ConfigureAwait(false); + await _organizationUnitRepository.UpdateAsync(organizationUnit); } public virtual async Task GetNextChildCodeAsync(Guid? parentId) @@ -74,16 +74,16 @@ namespace Volo.Abp.Identity.Organizations foreach (var child in children) { - await _organizationUnitRepository.DeleteAsync(child).ConfigureAwait(false); + await _organizationUnitRepository.DeleteAsync(child); } - await _organizationUnitRepository.DeleteAsync(id).ConfigureAwait(false); + await _organizationUnitRepository.DeleteAsync(id); } [UnitOfWork] public virtual async Task MoveAsync(Guid id, Guid? parentId) { - var organizationUnit = await _organizationUnitRepository.GetAsync(id).ConfigureAwait(false); + var organizationUnit = await _organizationUnitRepository.GetAsync(id); if (organizationUnit.ParentId == parentId) { return; @@ -110,7 +110,7 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task GetCodeOrDefaultAsync(Guid id) { - var ou = await _organizationUnitRepository.GetAsync(id).ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetAsync(id); return ou?.Code; } @@ -130,12 +130,12 @@ namespace Volo.Abp.Identity.Organizations { if (!recursive) { - return await _organizationUnitRepository.GetChildrenAsync(parentId).ConfigureAwait(false); + return await _organizationUnitRepository.GetChildrenAsync(parentId); } if (!parentId.HasValue) { - return await _organizationUnitRepository.GetListAsync().ConfigureAwait(false); + return await _organizationUnitRepository.GetListAsync(); } var code = await GetCodeOrDefaultAsync(parentId.Value); @@ -151,8 +151,8 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task AddRoleToOrganizationUnitAsync(Guid roleId, Guid ouId) { await AddRoleToOrganizationUnitAsync( - await _identityRoleRepository.GetAsync(roleId).ConfigureAwait(false), - await _organizationUnitRepository.GetAsync(ouId, true).ConfigureAwait(false) + await _identityRoleRepository.GetAsync(roleId), + await _organizationUnitRepository.GetAsync(ouId, true) ); } 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 2b5f249e77..39386fc5bd 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 @@ -54,7 +54,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore where userOu.UserId == id select userOuRoles.Name; - return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByLoginAsync( @@ -167,7 +167,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore where userOU.UserId == id select ou; - return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetUsersInOrganizationUnitAsync( @@ -179,7 +179,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore join user in DbSet on userOu.UserId equals user.Id where userOu.OrganizationUnitId == organizationUnitId select user; - return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } @@ -193,7 +193,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore join ou in DbContext.Set() on userOu.OrganizationUnitId equals ou.Id where ou.Code.StartsWith(code) select user; - return await query.ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } public override IQueryable WithDetails() 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 0c4a486481..f3e0eac922 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 @@ -21,25 +21,25 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public async Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default) { return await DbSet.Where(x => x.ParentId == parentId) - .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default) { return await DbSet.Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) - .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); } public override async Task> GetListAsync(bool includeDetails = true, CancellationToken cancellationToken = default) { return await DbSet .IncludeDetails(includeDetails) - .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -49,7 +49,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .FirstOrDefaultAsync( ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) - ).ConfigureAwait(false); + ); } public override IQueryable WithDetails() 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 2171299e8f..6c23f2ad3b 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 @@ -48,11 +48,11 @@ namespace Volo.Abp.Identity.MongoDB Guid id, CancellationToken cancellationToken = default) { - var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)).ConfigureAwait(false); + 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)).ConfigureAwait(false); + return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task FindByLoginAsync( @@ -137,12 +137,12 @@ namespace Volo.Abp.Identity.MongoDB bool includeDetails = false, CancellationToken cancellationToken = default) { - var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)).ConfigureAwait(false); + var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); var organizationUnitIds = user.OrganizationUnits.Select(r => r.OrganizationUnitId); return await DbContext.OrganizationUnits.AsQueryable() .Where(ou => organizationUnitIds.Contains(ou.Id)) .ToListAsync(GetCancellationToken(cancellationToken)) - .ConfigureAwait(false); + ; } public virtual async Task GetCountAsync( @@ -166,7 +166,7 @@ namespace Volo.Abp.Identity.MongoDB var result = await GetMongoQueryable() .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnitId)) .ToListAsync(GetCancellationToken(cancellationToken)) - .ConfigureAwait(false); + ; return result; } @@ -178,12 +178,12 @@ namespace Volo.Abp.Identity.MongoDB .Where(ou => ou.Code.StartsWith(code)) .Select(ou => ou.Id) .ToListAsync(GetCancellationToken(cancellationToken)) - .ConfigureAwait(false); + ; return await GetMongoQueryable() .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)) - .ConfigureAwait(false); + ; } } } \ No newline at end of file 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 cede5e46de..d11a180c46 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 @@ -28,20 +28,20 @@ namespace Volo.Abp.Identity.MongoDB public async Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default) { return await DbContext.OrganizationUnits.AsQueryable().Where(ou => ou.ParentId == parentId) - .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default) { return await DbContext.OrganizationUnits.AsQueryable() .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) - .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { return await DbContext.OrganizationUnits.AsQueryable() - .Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); + .Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); } public async Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -50,7 +50,7 @@ namespace Volo.Abp.Identity.MongoDB .FirstOrDefaultAsync( ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) - ).ConfigureAwait(false); + ); } } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index 2d259b0859..467597ad65 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -98,24 +98,24 @@ namespace Volo.Abp.Identity using (var uow = _unitOfWorkManager.Begin()) { var user = await _identityUserRepository.FindByNormalizedUserNameAsync( - _lookupNormalizer.NormalizeName("david")).ConfigureAwait(false); + _lookupNormalizer.NormalizeName("david")); user.ShouldNotBeNull(); var ou = await _organizationUnitRepository.GetOrganizationUnitAsync( - _lookupNormalizer.NormalizeName("OU11")).ConfigureAwait(false); + _lookupNormalizer.NormalizeName("OU11")); ou.ShouldNotBeNull(); await _identityUserManager.SetOrganizationUnitsAsync(user, new Guid[] { ou.Id - }).ConfigureAwait(false); + }); user = await _identityUserRepository.FindByNormalizedUserNameAsync( - _lookupNormalizer.NormalizeName("david")).ConfigureAwait(false); + _lookupNormalizer.NormalizeName("david")); user.OrganizationUnits.Count.ShouldBeGreaterThan(0); user.OrganizationUnits.FirstOrDefault(uou => uou.OrganizationUnitId == ou.Id).ShouldNotBeNull(); - await uow.CompleteAsync().ConfigureAwait(false); + await uow.CompleteAsync(); } @@ -155,25 +155,25 @@ namespace Volo.Abp.Identity using (var uow = _unitOfWorkManager.Begin()) { var ou = await _organizationUnitRepository.GetOrganizationUnitAsync( - _lookupNormalizer.NormalizeName("OU111")).ConfigureAwait(false); + _lookupNormalizer.NormalizeName("OU111")); ou.ShouldNotBeNull(); var user = await _identityUserRepository.FindByNormalizedUserNameAsync( - _lookupNormalizer.NormalizeName("john.nash")).ConfigureAwait(false); + _lookupNormalizer.NormalizeName("john.nash")); user.ShouldNotBeNull(); var ouNew = await _organizationUnitRepository.GetOrganizationUnitAsync( - _lookupNormalizer.NormalizeName("OU2")).ConfigureAwait(false); + _lookupNormalizer.NormalizeName("OU2")); ouNew.ShouldNotBeNull(); await _identityUserManager.SetOrganizationUnitsAsync(user, new Guid[] { ouNew.Id - }).ConfigureAwait(false); + }); user.OrganizationUnits.ShouldNotContain(x => x.OrganizationUnitId == ou.Id); - await uow.CompleteAsync().ConfigureAwait(false); + await uow.CompleteAsync(); } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 7c6c2582ad..67795268ff 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -31,55 +31,55 @@ namespace Volo.Abp.Identity { await _organizationUnitManager.CreateAsync(new OrganizationUnit(null, "Root 1")); - var root1 = await _organizationUnitRepository.GetOrganizationUnitAsync("Root 1").ConfigureAwait(false); + var root1 = await _organizationUnitRepository.GetOrganizationUnitAsync("Root 1"); root1.ShouldNotBeNull(); } [Fact] public async Task UpdateAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); ou.Code = OrganizationUnit.CreateCode(123); await _organizationUnitManager.UpdateAsync(ou); - var ouAfterChange = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); + var ouAfterChange = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); ouAfterChange.Code.ShouldContain("123"); } [Fact] public async Task DeleteAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11").ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11"); await _organizationUnitManager.DeleteAsync(ou.Id); - (await _organizationUnitRepository.GetOrganizationUnitAsync("OU11").ConfigureAwait(false)).ShouldBeNull(); + (await _organizationUnitRepository.GetOrganizationUnitAsync("OU11")).ShouldBeNull(); } [Fact] public async Task MoveAsync() { - var ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1").ConfigureAwait(false); - var ou2 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU2").ConfigureAwait(false); + var ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1"); + var ou2 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU2"); await _organizationUnitManager.MoveAsync(ou1.Id, ou2.Id); - ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1").ConfigureAwait(false); + ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1"); ou1.ParentId.ShouldBe(ou2.Id); ou1.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2)); - var ou11 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11").ConfigureAwait(false); + var ou11 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11"); ou11.ParentId.ShouldBe(ou1.Id); ou11.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1)); - var ou111 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); + var ou111 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); ou111.ParentId.ShouldBe(ou11.Id); ou111.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 1)); - var ou112 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU112").ConfigureAwait(false); + var ou112 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU112"); ou112.ParentId.ShouldBe(ou11.Id); ou112.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 2)); - var ou12 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU12").ConfigureAwait(false); + var ou12 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU12"); ou12.ParentId.ShouldBe(ou1.Id); ou12.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 2)); } @@ -87,24 +87,24 @@ namespace Volo.Abp.Identity [Fact] public async Task AddRoleToOrganizationUnitAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true).ConfigureAwait(false); - var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true); + var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")); await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole, ou); //TODO: This method has a bug: add role not work - ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true).ConfigureAwait(false); + ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true); ou.Roles.FirstOrDefault().RoleId.ShouldBe(adminRole.Id); } [Fact] public async Task RemoveRoleFromOrganizationUnitAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true).ConfigureAwait(false); - var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")).ConfigureAwait(false); + var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true); + var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")); await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole.Id, ou.Id); await _organizationUnitManager.RemoveRoleFromOrganizationUnitAsync(adminRole.Id, ou.Id); - ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true).ConfigureAwait(false); + ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true); ou.Roles.FirstOrDefault(r => r.RoleId == adminRole.Id).ShouldBeNull(); } } 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 11c968de3f..bd06c55d6c 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 @@ -47,10 +47,10 @@ namespace Volo.Abp.Identity public async Task Build() { - await AddRoles().ConfigureAwait(false); - await AddOrganizationUnits().ConfigureAwait(false); - await AddUsers().ConfigureAwait(false); - await AddClaimTypes().ConfigureAwait(false); + await AddRoles(); + await AddOrganizationUnits(); + await AddUsers(); + await AddClaimTypes(); } private async Task AddRoles() @@ -77,17 +77,17 @@ namespace Volo.Abp.Identity */ private async Task AddOrganizationUnits() { - var ou1 = await CreateOU("OU1", OrganizationUnit.CreateCode(1)).ConfigureAwait(false); - var ou11 = await CreateOU("OU11", OrganizationUnit.CreateCode(1, 1), ou1.Id).ConfigureAwait(false); - _ou112 = await CreateOU("OU112", OrganizationUnit.CreateCode(1, 1, 2), ou11.Id).ConfigureAwait(false); - var ou12 = await CreateOU("OU12", OrganizationUnit.CreateCode(1, 2), ou1.Id).ConfigureAwait(false); - var ou2 = await CreateOU("OU2", OrganizationUnit.CreateCode(2)).ConfigureAwait(false); - var ou21 = await CreateOU("OU21", OrganizationUnit.CreateCode(2, 1), ou2.Id).ConfigureAwait(false); + var ou1 = await CreateOU("OU1", OrganizationUnit.CreateCode(1)); + var ou11 = await CreateOU("OU11", OrganizationUnit.CreateCode(1, 1), ou1.Id); + _ou112 = await CreateOU("OU112", OrganizationUnit.CreateCode(1, 1, 2), ou11.Id); + var ou12 = await CreateOU("OU12", OrganizationUnit.CreateCode(1, 2), ou1.Id); + var ou2 = await CreateOU("OU2", OrganizationUnit.CreateCode(2)); + var ou21 = await CreateOU("OU21", OrganizationUnit.CreateCode(2, 1), ou2.Id); _ou111 = new OrganizationUnit(null, "OU111", ou11.Id); _ou111.Code = OrganizationUnit.CreateCode(1, 1, 1); _ou111.AddRole(_moderator.Id); - await _organizationUnitRepository.InsertAsync(_ou111).ConfigureAwait(false); + await _organizationUnitRepository.InsertAsync(_ou111); } private async Task AddUsers() @@ -121,7 +121,7 @@ namespace Volo.Abp.Identity private async Task AddClaimTypes() { var ageClaim = new IdentityClaimType(_testData.AgeClaimId, "Age", false, false, null, null, null, IdentityClaimValueType.Int); - await _identityClaimTypeRepository.InsertAsync(ageClaim).ConfigureAwait(false); + await _identityClaimTypeRepository.InsertAsync(ageClaim); var educationClaim = new IdentityClaimType(_testData.EducationClaimId, "Education", true, false, null, null, null); await _identityClaimTypeRepository.InsertAsync(educationClaim); @@ -129,7 +129,7 @@ namespace Volo.Abp.Identity private async Task CreateOU(string displayName, string code, Guid? parentId = null) { - var ou = await _organizationUnitRepository.InsertAsync(new OrganizationUnit(null, displayName, parentId) { Code = code }).ConfigureAwait(false); + var ou = await _organizationUnitRepository.InsertAsync(new OrganizationUnit(null, displayName, parentId) { Code = code }); return ou; } } 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 114d7e37a2..f7fe17c2e7 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 @@ -134,7 +134,7 @@ namespace Volo.Abp.Identity [Fact] public async Task GetUsersInOrganizationUnitAsync() { - var users = await UserRepository.GetUsersInOrganizationUnitAsync((await GetOU("OU111").ConfigureAwait(false)).Id).ConfigureAwait(false); + var users = await UserRepository.GetUsersInOrganizationUnitAsync((await GetOU("OU111")).Id); users.ShouldNotBeNull(); users.Count.ShouldBeGreaterThan(0); } @@ -142,7 +142,7 @@ namespace Volo.Abp.Identity [Fact] public async Task GetUsersInOrganizationUnitWithChildrenAsync() { - var users = await UserRepository.GetUsersInOrganizationUnitWithChildrenAsync((await GetOU("OU111").ConfigureAwait(false)).Code).ConfigureAwait(false); + var users = await UserRepository.GetUsersInOrganizationUnitWithChildrenAsync((await GetOU("OU111")).Code); users.ShouldNotBeNull(); users.Count.ShouldBeGreaterThan(0); } @@ -170,7 +170,7 @@ namespace Volo.Abp.Identity private async Task GetOU(string diplayName) { - var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync(diplayName).ConfigureAwait(false); + var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync(diplayName); organizationUnit.ShouldNotBeNull(); return organizationUnit; } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs index a832b5024d..43a570ec16 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs @@ -61,7 +61,7 @@ namespace Volo.Abp.Identity john.OrganizationUnits.ShouldNotBeNull(); john.OrganizationUnits.Any().ShouldBeTrue(); - await uow.CompleteAsync().ConfigureAwait(false); + await uow.CompleteAsync(); } } @@ -70,11 +70,11 @@ namespace Volo.Abp.Identity { using (var uow = GetRequiredService().Begin()) { - var ou = await OrganizationUnitRepository.GetOrganizationUnitAsync(LookupNormalizer.NormalizeName("OU111"), includeDetails: false).ConfigureAwait(false); + var ou = await OrganizationUnitRepository.GetOrganizationUnitAsync(LookupNormalizer.NormalizeName("OU111"), includeDetails: false); ou.Roles.ShouldNotBeNull(); //? ou.Roles.Any().ShouldBeTrue(); - await uow.CompleteAsync().ConfigureAwait(false); + await uow.CompleteAsync(); } } } 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 20452a90f5..8dc81ceb5e 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 @@ -32,21 +32,21 @@ namespace Volo.Abp.Identity [Fact] public async Task GetChildrenAsync() { - (await OrganizationUnitRepository.GetChildrenAsync(_testData.RoleModeratorId).ConfigureAwait(false)).ShouldNotBeNull(); + (await OrganizationUnitRepository.GetChildrenAsync(_testData.RoleModeratorId)).ShouldNotBeNull(); } [Fact] public async Task GetAllChildrenWithParentCodeAsync() { - (await OrganizationUnitRepository.GetAllChildrenWithParentCodeAsync(OrganizationUnit.CreateCode(0), _guidGenerator.Create()).ConfigureAwait(false)).ShouldNotBeNull(); + (await OrganizationUnitRepository.GetAllChildrenWithParentCodeAsync(OrganizationUnit.CreateCode(0), _guidGenerator.Create())).ShouldNotBeNull(); } [Fact] public async Task GetListAsync() { - var ouIds = (await OrganizationUnitRepository.GetListAsync().ConfigureAwait(false)) + var ouIds = (await OrganizationUnitRepository.GetListAsync()) .Select(ou => ou.Id).Take(2); - var ous = await OrganizationUnitRepository.GetListAsync(ouIds).ConfigureAwait(false); + var ous = await OrganizationUnitRepository.GetListAsync(ouIds); ous.Count.ShouldBe(2); ous.ShouldContain(ou => ou.Id == ouIds.First()); } @@ -54,20 +54,20 @@ namespace Volo.Abp.Identity [Fact] public async Task GetOrganizationUnitAsync() { - var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync("OU111").ConfigureAwait(false); + var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync("OU111"); organizationUnit.ShouldNotBeNull(); } [Fact] public async Task GetCountAsync() { - (await OrganizationUnitRepository.GetCountAsync().ConfigureAwait(false)).ShouldBeGreaterThan(0); + (await OrganizationUnitRepository.GetCountAsync()).ShouldBeGreaterThan(0); } [Fact] public async Task Should_Eager_Load_OrganizationUnit_Collections() { - var ou = (await OrganizationUnitRepository.GetListAsync(true).ConfigureAwait(false)) + var ou = (await OrganizationUnitRepository.GetListAsync(true)) .FirstOrDefault(ou => ou.DisplayName == "OU111"); ou.Roles.ShouldNotBeNull(); ou.Roles.Any().ShouldBeTrue(); From 118cb5b5f73a5a8cf439a3032a14a75b8b09f050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 15:06:28 +0300 Subject: [PATCH 14/35] Refactor IdentityUserManager & fix unit tests. --- .../Volo/Abp/Identity/IdentityErrorCodes.cs | 7 +- .../Volo/Abp/Identity/Localization/en.json | 3 +- .../Volo/Abp/Identity/Localization/tr.json | 3 +- .../Volo/Abp/Identity/IdentityUserManager.cs | 74 +++++++++---------- .../IOrganizationUnitRepository.cs | 1 - .../Identity/OrganizationUnitManager_Tests.cs | 23 ++++-- 6 files changed, 56 insertions(+), 55 deletions(-) rename modules/identity/src/{Volo.Abp.Identity.Application.Contracts => Volo.Abp.Identity.Domain.Shared}/Volo/Abp/Identity/IdentityErrorCodes.cs (53%) diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityErrorCodes.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityErrorCodes.cs similarity index 53% rename from modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityErrorCodes.cs rename to modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityErrorCodes.cs index 4bdfc5d8e9..d77ee9f5a9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityErrorCodes.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityErrorCodes.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Volo.Abp.Identity +namespace Volo.Abp.Identity { public static class IdentityErrorCodes { public const string UserSelfDeletion = "Volo.Abp.Identity:010001"; + public const string MaxAllowedOuMembership = "Volo.Abp.Identity:010002"; } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json index 4615f97fd2..8305ca9589 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json @@ -101,6 +101,7 @@ "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Whether the phoneNumber can be confirmed by the user.", "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Whether a confirmed telephone number is required to sign in.", "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Whether the username can be updated by the user.", - "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Whether the email can be updated by the user." + "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Whether the email can be updated by the user.", + "Volo.Abp.Identity:010002": "Can not set more than {MaxUserMembershipCount} organization unit for a user!" } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json index cfc58d4dad..8d006d41c4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json @@ -72,6 +72,7 @@ "Permission:Delete": "Silme", "Permission:ChangePermissions": "İzinleri değiştirme", "Permission:UserManagement": "Kullanıcı yönetimi", - "Permission:UserLookup": "Kullanıcı sorgulama" + "Permission:UserLookup": "Kullanıcı sorgulama", + "Volo.Abp.Identity:010002": "Bir kullanıcı en fazla {MaxUserMembershipCount} organizasyon birimine üye olabilir!" } } 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 6e97c1ad76..b7228b05a1 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 @@ -100,47 +100,42 @@ namespace Volo.Abp.Identity public virtual async Task IsInOrganizationUnitAsync(Guid userId, Guid ouId) { - return await IsInOrganizationUnitAsync( - await GetByIdAsync(userId), - await OrganizationUnitRepository.GetAsync(ouId) - ); + var user = await IdentityUserRepository.GetAsync(userId, cancellationToken: CancellationToken); + return user.IsInOrganizationUnit(ouId); } - public virtual Task IsInOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) + public virtual async Task IsInOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { - return Task.FromResult(user.IsInOrganizationUnit(ou.Id)); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); + return user.IsInOrganizationUnit(ou.Id); } public virtual async Task AddToOrganizationUnitAsync(Guid userId, Guid ouId) { await AddToOrganizationUnitAsync( - await IdentityUserRepository.GetAsync(userId, true), - await OrganizationUnitRepository.GetAsync(ouId) + await IdentityUserRepository.GetAsync(userId, cancellationToken: CancellationToken), + await OrganizationUnitRepository.GetAsync(ouId, cancellationToken: CancellationToken) ); } public virtual async Task AddToOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) { await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); - - var currentOus = user.OrganizationUnits; - if (currentOus.Any(cou => cou.OrganizationUnitId == ou.Id && cou.UserId == user.Id)) + if (user.OrganizationUnits.Any(cou => cou.OrganizationUnitId == ou.Id)) { return; } - await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, currentOus.Count + 1); + await CheckMaxUserOrganizationUnitMembershipCountAsync(user.OrganizationUnits.Count + 1); user.AddOrganizationUnit(ou.Id); } public virtual async Task RemoveFromOrganizationUnitAsync(Guid userId, Guid ouId) { - await RemoveFromOrganizationUnitAsync( - await IdentityUserRepository.GetAsync(userId, true), - await OrganizationUnitRepository.GetAsync(ouId) - ); + var user = await IdentityUserRepository.GetAsync(userId, cancellationToken: CancellationToken); + user.RemoveOrganizationUnit(ouId); } public virtual async Task RemoveFromOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) @@ -153,9 +148,9 @@ namespace Volo.Abp.Identity public virtual async Task SetOrganizationUnitsAsync(Guid userId, params Guid[] organizationUnitIds) { await SetOrganizationUnitsAsync( - await IdentityUserRepository.GetAsync(userId, true), + await IdentityUserRepository.GetAsync(userId, cancellationToken: CancellationToken), organizationUnitIds - ); + ); } public virtual async Task SetOrganizationUnitsAsync(IdentityUser user, params Guid[] organizationUnitIds) @@ -163,38 +158,36 @@ namespace Volo.Abp.Identity Check.NotNull(user, nameof(user)); Check.NotNull(organizationUnitIds, nameof(organizationUnitIds)); - await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, organizationUnitIds.Length); + await CheckMaxUserOrganizationUnitMembershipCountAsync(organizationUnitIds.Length); - var currentOus = await IdentityUserRepository.GetOrganizationUnitsAsync(user.Id); + await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); //Remove from removed OUs - foreach (var currentOu in currentOus) + foreach (var ouId in user.OrganizationUnits.Select(uou => uou.OrganizationUnitId).ToArray()) { - if (!organizationUnitIds.Contains(currentOu.Id)) + if (!organizationUnitIds.Contains(ouId)) { - await RemoveFromOrganizationUnitAsync(user.Id, currentOu.Id); + user.RemoveOrganizationUnit(ouId); } } //Add to added OUs foreach (var organizationUnitId in organizationUnitIds) { - if (currentOus.All(ou => ou.Id != organizationUnitId)) + if (!user.IsInOrganizationUnit(organizationUnitId)) { - await AddToOrganizationUnitAsync( - user, - await OrganizationUnitRepository.GetAsync(organizationUnitId) - ); + user.AddOrganizationUnit(organizationUnitId); } } } - private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(Guid? tenantId, int requestedCount) + private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(int requestedCount) { var maxCount = await SettingProvider.GetAsync(IdentitySettingNames.OrganizationUnit.MaxUserMembershipCount); if (requestedCount > maxCount) { - throw new AbpException(string.Format("Can not set more than {0} organization unit for a user!", maxCount)); + throw new BusinessException(IdentityErrorCodes.MaxAllowedOuMembership) + .WithData("MaxUserMembershipCount", maxCount); } } @@ -203,33 +196,33 @@ namespace Volo.Abp.Identity { await IdentityUserRepository.EnsureCollectionLoadedAsync(user, u => u.OrganizationUnits, CancellationTokenProvider.Token); - var ouOfUser = user.OrganizationUnits; - - return await OrganizationUnitRepository.GetListAsync(ouOfUser.Select(t => t.OrganizationUnitId)); + return await OrganizationUnitRepository.GetListAsync( + user.OrganizationUnits.Select(t => t.OrganizationUnitId), + CancellationToken + ); } [UnitOfWork] - public virtual async Task> GetUsersInOrganizationUnitAsync(OrganizationUnit organizationUnit, + public virtual async Task> GetUsersInOrganizationUnitAsync( + OrganizationUnit organizationUnit, bool includeChildren = false) { if (includeChildren) { return await IdentityUserRepository - .GetUsersInOrganizationUnitWithChildrenAsync(organizationUnit.Code) - ; + .GetUsersInOrganizationUnitWithChildrenAsync(organizationUnit.Code, CancellationToken); } else { return await IdentityUserRepository - .GetUsersInOrganizationUnitAsync(organizationUnit.Id) - ; + .GetUsersInOrganizationUnitAsync(organizationUnit.Id, CancellationToken); } } public virtual async Task AddDefaultRolesAsync([NotNull] IdentityUser user) { await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles, CancellationToken); - + foreach (var role in await RoleRepository.GetDefaultOnesAsync(cancellationToken: CancellationToken)) { if (!user.IsInRole(role.Id)) @@ -237,9 +230,8 @@ namespace Volo.Abp.Identity user.AddRole(role.Id); } } - - return await UpdateUserAsync(user); + return await UpdateUserAsync(user); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index 4d90ba3a1d..f57425d84a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -17,6 +17,5 @@ namespace Volo.Abp.Identity.Organizations Task> GetListAsync(bool includeDetails = true, CancellationToken cancellationToken = default); Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default); - } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 67795268ff..9148888eac 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Volo.Abp.Identity.Organizations; +using Volo.Abp.Uow; using Xunit; namespace Volo.Abp.Identity @@ -17,6 +18,7 @@ namespace Volo.Abp.Identity private readonly IdentityTestData _testData; private readonly IIdentityRoleRepository _identityRoleRepository; private readonly ILookupNormalizer _lookupNormalizer; + private readonly IUnitOfWorkManager _unitOfWorkManager; public OrganizationUnitManager_Tests() { _organizationUnitManager = GetRequiredService(); @@ -24,6 +26,7 @@ namespace Volo.Abp.Identity _identityRoleRepository = GetRequiredService(); _lookupNormalizer = GetRequiredService(); _testData = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); } [Fact] @@ -87,13 +90,21 @@ namespace Volo.Abp.Identity [Fact] public async Task AddRoleToOrganizationUnitAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true); - var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")); - await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole, ou); - - //TODO: This method has a bug: add role not work + OrganizationUnit ou = null; + IdentityRole adminRole = null; + + using (var uow = _unitOfWorkManager.Begin()) + { + ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true); + adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")); + await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole, ou); + await _organizationUnitRepository.UpdateAsync(ou); + + await uow.CompleteAsync(); + } + ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true); - ou.Roles.FirstOrDefault().RoleId.ShouldBe(adminRole.Id); + ou.Roles.First().RoleId.ShouldBe(adminRole.Id); } [Fact] From f3ab38f1c22be1bf235775d6077c1ac93515f1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 15:31:55 +0300 Subject: [PATCH 15/35] Refactor OU --- .../Volo/Abp/Identity/IdentityUser.cs | 4 ++-- .../Identity/IdentityUserOrganizationUnit.cs | 18 ++++++------------ .../Volo/Abp/Identity/IdentityUserStore.cs | 1 - .../Identity/Organizations/OrganizationUnit.cs | 6 +++--- .../Organizations/OrganizationUnitRole.cs | 17 ++++++----------- 5 files changed, 17 insertions(+), 29 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index 2b68bef6a8..ea1f5ccf72 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -290,9 +290,9 @@ namespace Volo.Abp.Identity OrganizationUnits.Add( new IdentityUserOrganizationUnit( - TenantId, Id, - organizationUnitId + organizationUnitId, + TenantId ) ); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs index fd701c5f17..2d8eca0d16 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs @@ -8,39 +8,33 @@ namespace Volo.Abp.Identity /// /// Represents membership of a User to an OU. /// - public class IdentityUserOrganizationUnit : CreationAuditedEntity, IMultiTenant, ISoftDelete + public class IdentityUserOrganizationUnit : CreationAuditedEntity, IMultiTenant { - /// /// TenantId of this entity. /// - public virtual Guid? TenantId { get; set; } + public virtual Guid? TenantId { get; protected set; } /// /// Id of the User. /// - public virtual Guid UserId { get; set; } + public virtual Guid UserId { get; protected set; } /// /// Id of the related . /// - public virtual Guid OrganizationUnitId { get; set; } - - /// - /// Specifies if the organization is soft deleted or not. - /// - public virtual bool IsDeleted { get; set; } + public virtual Guid OrganizationUnitId { get; protected set; } protected IdentityUserOrganizationUnit() { } - public IdentityUserOrganizationUnit(Guid? tenantId, Guid userId, Guid organizationUnitId) + public IdentityUserOrganizationUnit(Guid userId, Guid organizationUnitId, Guid? tenantId = null) { - TenantId = tenantId; UserId = userId; OrganizationUnitId = organizationUnitId; + TenantId = tenantId; } public override object[] GetKeys() 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 c13d3f33bd..eb07b0ed41 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 @@ -367,7 +367,6 @@ 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); return userRoles.Union(userOrganizationUnitRoles).ToList(); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs index ca9e17267c..83ada55fb9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs @@ -16,7 +16,7 @@ namespace Volo.Abp.Identity.Organizations /// /// Parent Id. - /// Null, if this OU is root. + /// Null, if this OU is a root. /// public virtual Guid? ParentId { get; set; } @@ -24,7 +24,7 @@ namespace Volo.Abp.Identity.Organizations /// Hierarchical Code of this organization unit. /// Example: "00001.00042.00005". /// This is a unique code for a Tenant. - /// It's changeable if OU hierarch is changed. + /// It's changeable if OU hierarchy is changed. /// public virtual string Code { get; set; } @@ -191,7 +191,7 @@ namespace Volo.Abp.Identity.Organizations return; } - Roles.Add(new OrganizationUnitRole(TenantId, roleId, Id)); + Roles.Add(new OrganizationUnitRole(roleId, Id, TenantId)); } public virtual void RemoveRole(Guid roleId) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs index de43e8bec4..ddbc55589b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.Identity.Organizations /// /// Represents membership of a User to an OU. /// - public class OrganizationUnitRole : CreationAuditedEntity, IMultiTenant, ISoftDelete + public class OrganizationUnitRole : CreationAuditedEntity, IMultiTenant { /// /// TenantId of this entity. @@ -17,22 +17,17 @@ namespace Volo.Abp.Identity.Organizations /// /// Id of the Role. /// - public virtual Guid RoleId { get; set; } + public virtual Guid RoleId { get; protected set; } /// /// Id of the . /// - public virtual Guid OrganizationUnitId { get; set; } - - /// - /// Specifies if the organization is soft deleted or not. - /// - public virtual bool IsDeleted { get; set; } + public virtual Guid OrganizationUnitId { get; protected set; } /// /// Initializes a new instance of the class. /// - public OrganizationUnitRole() + protected OrganizationUnitRole() { } @@ -43,11 +38,11 @@ namespace Volo.Abp.Identity.Organizations /// TenantId /// Id of the User. /// Id of the . - public OrganizationUnitRole(Guid? tenantId, Guid roleId, Guid organizationUnitId) + public OrganizationUnitRole(Guid roleId, Guid organizationUnitId, Guid? tenantId = null) { - TenantId = tenantId; RoleId = roleId; OrganizationUnitId = organizationUnitId; + TenantId = tenantId; } public override object[] GetKeys() From 66040f983f2dad0a6c365e087f9623718f850e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 15:34:35 +0300 Subject: [PATCH 16/35] Remove OrganizationUnit.Children --- .../Volo/Abp/Identity/Organizations/OrganizationUnit.cs | 7 +------ .../IdentityDbContextModelBuilderExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs index 83ada55fb9..e3925c5748 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs @@ -32,12 +32,7 @@ namespace Volo.Abp.Identity.Organizations /// Display name of this role. /// public virtual string DisplayName { get; set; } - - /// - /// Children of this OU. - /// - public virtual ICollection Children { get; set; } - + /// /// Roles of this OU. /// diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index b2b9d185ce..6e6d02d324 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -158,7 +158,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.Property(ou => ou.Code).IsRequired().HasMaxLength(OrganizationUnitConsts.MaxCodeLength).HasColumnName(nameof(OrganizationUnit.Code)); b.Property(ou => ou.DisplayName).IsRequired().HasMaxLength(OrganizationUnitConsts.MaxDisplayNameLength).HasColumnName(nameof(OrganizationUnit.DisplayName)); - b.HasMany(ou => ou.Children).WithOne().HasForeignKey(ou => ou.ParentId); + b.HasMany().WithOne().HasForeignKey(ou => ou.ParentId); b.HasMany(ou => ou.Roles).WithOne().HasForeignKey(our => our.OrganizationUnitId).IsRequired(); b.HasIndex(ou => ou.Code); From f21144ab8f5cbfaa6aa7cb6f516eb1f847030f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 15:48:28 +0300 Subject: [PATCH 17/35] Refactor repositories. --- .../IOrganizationUnitRepository.cs | 2 - .../Organizations/OrganizationUnitManager.cs | 63 ++++++++++--------- .../EfCoreOrganizationUnitRepository.cs | 39 +++++++----- .../MongoOrganizationUnitRepository.cs | 44 +++++++------ .../OrganizationUnitRepository_Tests.cs | 4 +- 5 files changed, 83 insertions(+), 69 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index f57425d84a..03c34e3170 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -14,8 +14,6 @@ namespace Volo.Abp.Identity.Organizations Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default); - Task> GetListAsync(bool includeDetails = true, CancellationToken cancellationToken = default); - Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs index f4062a4d6c..e3fe4c5571 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs @@ -2,9 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; -using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; using Volo.Abp.Identity.Localization; using Volo.Abp.Threading; @@ -17,11 +15,10 @@ namespace Volo.Abp.Identity.Organizations /// public class OrganizationUnitManager : DomainService { - protected IOrganizationUnitRepository _organizationUnitRepository { get; private set; } - - private readonly IStringLocalizer _localizer; - private readonly IIdentityRoleRepository _identityRoleRepository; - private readonly ICancellationTokenProvider _cancellationTokenProvider; + protected IOrganizationUnitRepository OrganizationUnitRepository { get; } + protected IStringLocalizer Localizer { get; } + protected IIdentityRoleRepository IdentityRoleRepository { get; } + protected ICancellationTokenProvider CancellationTokenProvider { get; } public OrganizationUnitManager( IOrganizationUnitRepository organizationUnitRepository, @@ -29,10 +26,10 @@ namespace Volo.Abp.Identity.Organizations IIdentityRoleRepository identityRoleRepository, ICancellationTokenProvider cancellationTokenProvider) { - _organizationUnitRepository = organizationUnitRepository; - _localizer = localizer; - _identityRoleRepository = identityRoleRepository; - _cancellationTokenProvider = cancellationTokenProvider; + OrganizationUnitRepository = organizationUnitRepository; + Localizer = localizer; + IdentityRoleRepository = identityRoleRepository; + CancellationTokenProvider = cancellationTokenProvider; } [UnitOfWork] @@ -40,30 +37,36 @@ namespace Volo.Abp.Identity.Organizations { organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId); await ValidateOrganizationUnitAsync(organizationUnit); - await _organizationUnitRepository.InsertAsync(organizationUnit); + await OrganizationUnitRepository.InsertAsync(organizationUnit); } public virtual async Task UpdateAsync(OrganizationUnit organizationUnit) { await ValidateOrganizationUnitAsync(organizationUnit); - await _organizationUnitRepository.UpdateAsync(organizationUnit); + await OrganizationUnitRepository.UpdateAsync(organizationUnit); } public virtual async Task GetNextChildCodeAsync(Guid? parentId) { var lastChild = await GetLastChildOrNullAsync(parentId); - if (lastChild == null) + if (lastChild != null) { - var parentCode = parentId != null ? await GetCodeOrDefaultAsync(parentId.Value) : null; - return OrganizationUnit.AppendCode(parentCode, OrganizationUnit.CreateCode(1)); + return OrganizationUnit.CalculateNextCode(lastChild.Code); } - return OrganizationUnit.CalculateNextCode(lastChild.Code); + var parentCode = parentId != null + ? await GetCodeOrDefaultAsync(parentId.Value) + : null; + + return OrganizationUnit.AppendCode( + parentCode, + OrganizationUnit.CreateCode(1) + ); } public virtual async Task GetLastChildOrNullAsync(Guid? parentId) { - var children = await _organizationUnitRepository.GetChildrenAsync(parentId); + var children = await OrganizationUnitRepository.GetChildrenAsync(parentId); return children.OrderBy(c => c.Code).LastOrDefault(); } @@ -74,16 +77,16 @@ namespace Volo.Abp.Identity.Organizations foreach (var child in children) { - await _organizationUnitRepository.DeleteAsync(child); + await OrganizationUnitRepository.DeleteAsync(child); } - await _organizationUnitRepository.DeleteAsync(id); + await OrganizationUnitRepository.DeleteAsync(id); } [UnitOfWork] public virtual async Task MoveAsync(Guid id, Guid? parentId) { - var organizationUnit = await _organizationUnitRepository.GetAsync(id); + var organizationUnit = await OrganizationUnitRepository.GetAsync(id); if (organizationUnit.ParentId == parentId) { return; @@ -110,7 +113,7 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task GetCodeOrDefaultAsync(Guid id) { - var ou = await _organizationUnitRepository.GetAsync(id); + var ou = await OrganizationUnitRepository.GetAsync(id); return ou?.Code; } @@ -122,7 +125,7 @@ namespace Volo.Abp.Identity.Organizations if (siblings.Any(ou => ou.DisplayName == organizationUnit.DisplayName)) { - throw new UserFriendlyException(_localizer["OrganizationUnitDuplicateDisplayNameWarning", organizationUnit.DisplayName]); + throw new UserFriendlyException(Localizer["OrganizationUnitDuplicateDisplayNameWarning", organizationUnit.DisplayName]); } } @@ -130,17 +133,17 @@ namespace Volo.Abp.Identity.Organizations { if (!recursive) { - return await _organizationUnitRepository.GetChildrenAsync(parentId); + return await OrganizationUnitRepository.GetChildrenAsync(parentId); } if (!parentId.HasValue) { - return await _organizationUnitRepository.GetListAsync(); + return await OrganizationUnitRepository.GetListAsync(includeDetails: true); } var code = await GetCodeOrDefaultAsync(parentId.Value); - return await _organizationUnitRepository.GetAllChildrenWithParentCodeAsync(code, parentId); + return await OrganizationUnitRepository.GetAllChildrenWithParentCodeAsync(code, parentId); } public virtual Task IsInOrganizationUnitAsync(IdentityUser user, OrganizationUnit ou) @@ -151,8 +154,8 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task AddRoleToOrganizationUnitAsync(Guid roleId, Guid ouId) { await AddRoleToOrganizationUnitAsync( - await _identityRoleRepository.GetAsync(roleId), - await _organizationUnitRepository.GetAsync(ouId, true) + await IdentityRoleRepository.GetAsync(roleId), + await OrganizationUnitRepository.GetAsync(ouId, true) ); } @@ -171,8 +174,8 @@ namespace Volo.Abp.Identity.Organizations public virtual async Task RemoveRoleFromOrganizationUnitAsync(Guid roleId, Guid ouId) { await RemoveRoleFromOrganizationUnitAsync( - await _identityRoleRepository.GetAsync(roleId), - await _organizationUnitRepository.GetAsync(ouId, true) + await IdentityRoleRepository.GetAsync(roleId), + await OrganizationUnitRepository.GetAsync(ouId, true) ); } 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 f3e0eac922..0aa90df8ac 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 @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; @@ -11,38 +10,48 @@ using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { - public class EfCoreOrganizationUnitRepository : EfCoreRepository, IOrganizationUnitRepository + public class EfCoreOrganizationUnitRepository + : EfCoreRepository, + IOrganizationUnitRepository { - public EfCoreOrganizationUnitRepository(IDbContextProvider dbContextProvider) + public EfCoreOrganizationUnitRepository( + IDbContextProvider dbContextProvider) : base(dbContextProvider) { } - public async Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default) + public async Task> GetChildrenAsync( + Guid? parentId, + CancellationToken cancellationToken = default) { - return await DbSet.Where(x => x.ParentId == parentId) + return await DbSet + .Where(x => x.ParentId == parentId) .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default) + public async Task> GetAllChildrenWithParentCodeAsync( + string code, + Guid? parentId, + CancellationToken cancellationToken = default) { - return await DbSet.Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) + return await DbSet + .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) - { - return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); - } - - public override async Task> GetListAsync(bool includeDetails = true, CancellationToken cancellationToken = default) + public async Task> GetListAsync( + IEnumerable ids, + CancellationToken cancellationToken = default) { return await DbSet - .IncludeDetails(includeDetails) + .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) + public async Task GetOrganizationUnitAsync( + string displayName, + bool includeDetails = false, + CancellationToken cancellationToken = default) { return await DbSet .IncludeDetails(includeDetails) 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 d11a180c46..879bd0acb5 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 @@ -3,11 +3,9 @@ using MongoDB.Driver.Linq; using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.MongoDB; -using Volo.Abp.Guids; using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; @@ -15,42 +13,48 @@ namespace Volo.Abp.Identity.MongoDB { public class MongoOrganizationUnitRepository : MongoDbRepository, IOrganizationUnitRepository { - private readonly IGuidGenerator _guidGenerator; - public MongoOrganizationUnitRepository( - IMongoDbContextProvider dbContextProvider, - IGuidGenerator guidGenerator) + IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) { - _guidGenerator = guidGenerator; } - public async Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default) + public async Task> GetChildrenAsync( + Guid? parentId, + CancellationToken cancellationToken = default) { - return await DbContext.OrganizationUnits.AsQueryable().Where(ou => ou.ParentId == parentId) - .ToListAsync(GetCancellationToken(cancellationToken)); + return await GetMongoQueryable() + .Where(ou => ou.ParentId == parentId) + .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default) + public async Task> GetAllChildrenWithParentCodeAsync( + string code, + Guid? parentId, + CancellationToken cancellationToken = default) { - return await DbContext.OrganizationUnits.AsQueryable() + return await GetMongoQueryable() .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await DbContext.OrganizationUnits.AsQueryable() - .Where(t => ids.Contains(t.Id)).ToListAsync(GetCancellationToken(cancellationToken)); + return await GetMongoQueryable() + .Where(t => ids.Contains(t.Id)) + .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default) + public async Task GetOrganizationUnitAsync( + string displayName, + bool includeDetails = false, + CancellationToken cancellationToken = default) { - return await DbContext.OrganizationUnits.AsQueryable() - .FirstOrDefaultAsync( - ou => ou.DisplayName == displayName, - GetCancellationToken(cancellationToken) - ); + return await GetMongoQueryable() + .FirstOrDefaultAsync( + ou => ou.DisplayName == displayName, + GetCancellationToken(cancellationToken) + ); } } } 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 8dc81ceb5e..5d09eace23 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 @@ -44,7 +44,7 @@ namespace Volo.Abp.Identity [Fact] public async Task GetListAsync() { - var ouIds = (await OrganizationUnitRepository.GetListAsync()) + var ouIds = (await OrganizationUnitRepository.GetListAsync(includeDetails: true)) .Select(ou => ou.Id).Take(2); var ous = await OrganizationUnitRepository.GetListAsync(ouIds); ous.Count.ShouldBe(2); @@ -67,7 +67,7 @@ namespace Volo.Abp.Identity [Fact] public async Task Should_Eager_Load_OrganizationUnit_Collections() { - var ou = (await OrganizationUnitRepository.GetListAsync(true)) + var ou = (await OrganizationUnitRepository.GetListAsync(includeDetails: true)) .FirstOrDefault(ou => ou.DisplayName == "OU111"); ou.Roles.ShouldNotBeNull(); ou.Roles.Any().ShouldBeTrue(); From 926df0b985190ffd6d2fdb76e7c8467fcc3b5dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 15:52:24 +0300 Subject: [PATCH 18/35] Update IdentityDbContextModelBuilderExtensions.cs --- .../IdentityDbContextModelBuilderExtensions.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 6e6d02d324..8c16912f69 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -153,7 +153,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { b.ToTable(options.TablePrefix + "OrganizationUnits", options.Schema); - b.ConfigureFullAuditedAggregateRoot(); + b.ConfigureByConvention(); b.Property(ou => ou.Code).IsRequired().HasMaxLength(OrganizationUnitConsts.MaxCodeLength).HasColumnName(nameof(OrganizationUnit.Code)); b.Property(ou => ou.DisplayName).IsRequired().HasMaxLength(OrganizationUnitConsts.MaxDisplayNameLength).HasColumnName(nameof(OrganizationUnit.DisplayName)); @@ -168,6 +168,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { b.ToTable(options.TablePrefix + "OrganizationUnitRoles", options.Schema); + b.ConfigureByConvention(); + b.HasKey(ou => new { ou.OrganizationUnitId, ou.RoleId }); b.HasOne().WithMany().HasForeignKey(ou => ou.OrganizationUnitId).IsRequired(); @@ -180,6 +182,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { b.ToTable(options.TablePrefix + "UserOrganizationUnits", options.Schema); + b.ConfigureByConvention(); + b.HasKey(ou => new { ou.OrganizationUnitId, ou.UserId }); b.HasOne().WithMany().HasForeignKey(ou => ou.OrganizationUnitId).IsRequired(); @@ -187,7 +191,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasIndex(ou => new { ou.UserId, ou.OrganizationUnitId }); }); - } } } From 32012c3b715cbd33370adae6b0c2411f7cdfc5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 16:22:23 +0300 Subject: [PATCH 19/35] Improve OU repo. --- .../IdentityUserCreateOrUpdateDtoBase.cs | 3 --- .../Volo/Abp/Identity/IdentityUserManager.cs | 2 +- .../IOrganizationUnitRepository.cs | 25 ++++++++++++++++--- .../EfCoreOrganizationUnitRepository.cs | 6 +++++ .../MongoOrganizationUnitRepository.cs | 7 +++++- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs index f14dce6181..c18f2c16b5 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs @@ -31,8 +31,5 @@ namespace Volo.Abp.Identity [CanBeNull] public string[] RoleNames { get; set; } - - [CanBeNull] - public Guid[] OrganizationUnits { get; set; } } } \ No newline at end of file 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 b7228b05a1..76eda9378f 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 @@ -198,7 +198,7 @@ namespace Volo.Abp.Identity return await OrganizationUnitRepository.GetListAsync( user.OrganizationUnits.Select(t => t.OrganizationUnitId), - CancellationToken + cancellationToken: CancellationToken ); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs index 03c34e3170..b914e859ef 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs @@ -8,12 +8,29 @@ namespace Volo.Abp.Identity.Organizations { public interface IOrganizationUnitRepository : IBasicRepository { - Task> GetChildrenAsync(Guid? parentId, CancellationToken cancellationToken = default); + Task> GetChildrenAsync( + Guid? parentId, + bool includeDetails = false, + CancellationToken cancellationToken = default + ); - Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId, CancellationToken cancellationToken = default); + Task> GetAllChildrenWithParentCodeAsync( + string code, + Guid? parentId, + bool includeDetails = false, + CancellationToken cancellationToken = default + ); - Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default); + Task> GetListAsync( + IEnumerable ids, + bool includeDetails = false, + CancellationToken cancellationToken = default + ); - Task GetOrganizationUnitAsync(string displayName, bool includeDetails = false, CancellationToken cancellationToken = default); + Task GetOrganizationUnitAsync( + string displayName, + bool includeDetails = false, + CancellationToken cancellationToken = default + ); } } 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 0aa90df8ac..38cac16b3e 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 @@ -22,9 +22,11 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public async Task> GetChildrenAsync( Guid? parentId, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet + .IncludeDetails(includeDetails) .Where(x => x.ParentId == parentId) .ToListAsync(GetCancellationToken(cancellationToken)); } @@ -32,18 +34,22 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public async Task> GetAllChildrenWithParentCodeAsync( string code, Guid? parentId, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet + .IncludeDetails(includeDetails) .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetListAsync( IEnumerable ids, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet + .IncludeDetails(includeDetails) .Where(t => ids.Contains(t.Id)) .ToListAsync(GetCancellationToken(cancellationToken)); } 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 879bd0acb5..5f11fa8477 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 @@ -21,6 +21,7 @@ namespace Volo.Abp.Identity.MongoDB public async Task> GetChildrenAsync( Guid? parentId, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable() @@ -31,6 +32,7 @@ namespace Volo.Abp.Identity.MongoDB public async Task> GetAllChildrenWithParentCodeAsync( string code, Guid? parentId, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable() @@ -38,7 +40,10 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetListAsync(IEnumerable ids, CancellationToken cancellationToken = default) + public async Task> GetListAsync( + IEnumerable ids, + bool includeDetails = false, + CancellationToken cancellationToken = default) { return await GetMongoQueryable() .Where(t => ids.Contains(t.Id)) From 771e39414eff53f3664d15bf7a690524ee34403b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 16:30:27 +0300 Subject: [PATCH 20/35] Update IdentityDbContextModelBuilderExtensions.cs --- .../IdentityDbContextModelBuilderExtensions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 8c16912f69..5e5d315caf 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -172,7 +172,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasKey(ou => new { ou.OrganizationUnitId, ou.RoleId }); - b.HasOne().WithMany().HasForeignKey(ou => ou.OrganizationUnitId).IsRequired(); b.HasOne().WithMany().HasForeignKey(ou => ou.RoleId).IsRequired(); b.HasIndex(ou => new { ou.RoleId, ou.OrganizationUnitId }); From 921f8ba6bd5961bcffb44e9856624cb5f7788486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Wed, 8 Apr 2020 16:42:54 +0300 Subject: [PATCH 21/35] Update IdentityDbContextModelBuilderExtensions.cs --- .../IdentityDbContextModelBuilderExtensions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 5e5d315caf..89d53616c2 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -186,7 +186,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasKey(ou => new { ou.OrganizationUnitId, ou.UserId }); b.HasOne().WithMany().HasForeignKey(ou => ou.OrganizationUnitId).IsRequired(); - b.HasOne().WithMany().HasForeignKey(ou => ou.UserId).IsRequired(); b.HasIndex(ou => new { ou.UserId, ou.OrganizationUnitId }); }); 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 22/35] 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); From cdf8cf99075446f66c82a2ad189326a4aa596309 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Mon, 13 Apr 2020 13:18:08 +0300 Subject: [PATCH 23/35] renaming organizationUnit namepsace --- .../{Organizations => }/OrganizationUnitConsts.cs | 4 ++-- .../Volo.Abp.Identity.Domain.csproj | 4 ++++ .../Volo/Abp/Identity/IIdentityUserRepository.cs | 1 - .../IOrganizationUnitRepository.cs | 2 +- .../Volo/Abp/Identity/IdentityUserManager.cs | 1 - .../Abp/Identity/IdentityUserOrganizationUnit.cs | 1 - .../{Organizations => }/OrganizationUnit.cs | 5 +++-- .../{Organizations => }/OrganizationUnitManager.cs | 2 +- .../{Organizations => }/OrganizationUnitRole.cs | 2 +- .../AbpIdentityEntityFrameworkCoreModule.cs | 1 - .../EfCoreIdentityUserRepository.cs | 10 +++++++++- .../EfCoreOrganizationUnitRepository.cs | 1 - .../EntityFrameworkCore/IIdentityDbContext.cs | 1 - .../EntityFrameworkCore/IdentityDbContext.cs | 1 - .../IdentityDbContextModelBuilderExtensions.cs | 1 - .../IdentityEfCoreQueryableExtensions.cs | 1 - .../Identity/MongoDB/AbpIdentityMongoDbContext.cs | 1 - .../MongoDB/AbpIdentityMongoDbContextExtensions.cs | 1 - .../Identity/MongoDB/AbpIdentityMongoDbModule.cs | 1 - .../Identity/MongoDB/IAbpIdentityMongoDbContext.cs | 1 - .../Identity/MongoDB/MongoIdentityUserRepository.cs | 1 - .../MongoDB/MongoOrganizationUnitRepository.cs | 13 ++++++------- .../Volo/Abp/Identity/IdentityUserManager_Tests.cs | 4 ---- .../Abp/Identity/OrganizationUnitManager_Tests.cs | 9 ++++----- .../Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs | 5 ++--- .../Abp/Identity/IdentityUserRepository_Tests.cs | 1 - .../Identity/Identity_Repository_Resolve_Tests.cs | 1 - .../Volo/Abp/Identity/LazyLoading_Tests.cs | 1 - .../Identity/OrganizationUnitRepository_Tests.cs | 4 ---- 29 files changed, 33 insertions(+), 48 deletions(-) rename modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/{Organizations => }/OrganizationUnitConsts.cs (88%) rename modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/{Organizations => }/IOrganizationUnitRepository.cs (96%) rename modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/{Organizations => }/OrganizationUnit.cs (97%) rename modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/{Organizations => }/OrganizationUnitManager.cs (99%) rename modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/{Organizations => }/OrganizationUnitRole.cs (97%) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/OrganizationUnitConsts.cs similarity index 88% rename from modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs rename to modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/OrganizationUnitConsts.cs index a704e6bb05..ad6091a44e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/OrganizationUnitConsts.cs @@ -1,6 +1,6 @@ -namespace Volo.Abp.Identity.Organizations +namespace Volo.Abp.Identity { - public class OrganizationUnitConsts + public static class OrganizationUnitConsts { /// /// Maximum length of the property. diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj index fa22210db0..4e0e27f17c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj @@ -33,4 +33,8 @@ + + + + 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 ef03c86b7a..652dfe23c6 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 @@ -5,7 +5,6 @@ using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity { diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs similarity index 96% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs index b914e859ef..6c2b6d9a3c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs @@ -4,7 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; -namespace Volo.Abp.Identity.Organizations +namespace Volo.Abp.Identity { public interface IOrganizationUnitRepository : IBasicRepository { 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 76eda9378f..f90694349a 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 @@ -10,7 +10,6 @@ using Microsoft.Extensions.Options; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Threading; using Volo.Abp.Uow; using Volo.Abp.Settings; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs index 2d8eca0d16..5bb0ed790d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserOrganizationUnit.cs @@ -1,6 +1,5 @@ using System; using Volo.Abp.Domain.Entities.Auditing; -using Volo.Abp.Identity.Organizations; using Volo.Abp.MultiTenancy; namespace Volo.Abp.Identity diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs similarity index 97% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs index e3925c5748..4f49e6935d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs @@ -5,7 +5,7 @@ using System.Linq; using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.Identity.Organizations +namespace Volo.Abp.Identity { /// /// Represents an organization unit (OU). @@ -52,8 +52,9 @@ namespace Volo.Abp.Identity.Organizations /// Tenant's Id or null for host. /// Display name. /// Parent's Id or null if OU is a root. - public OrganizationUnit(Guid? tenantId, string displayName, Guid? parentId = null) + public OrganizationUnit(Guid id, string displayName, Guid? parentId = null, Guid? tenantId = null) { + Id = id; TenantId = tenantId; DisplayName = displayName; ParentId = parentId; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs similarity index 99% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs index e3fe4c5571..bfaa522dd0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs @@ -8,7 +8,7 @@ using Volo.Abp.Identity.Localization; using Volo.Abp.Threading; using Volo.Abp.Uow; -namespace Volo.Abp.Identity.Organizations +namespace Volo.Abp.Identity { /// /// Performs domain logic for Organization Units. diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitRole.cs similarity index 97% rename from modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs rename to modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitRole.cs index ddbc55589b..43aca1e272 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitRole.cs @@ -2,7 +2,7 @@ using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.MultiTenancy; -namespace Volo.Abp.Identity.Organizations +namespace Volo.Abp.Identity { /// /// Represents membership of a User to an OU. diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs index ab8176a733..f46d3b6e0b 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Volo.Abp.Users.EntityFrameworkCore; 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 39386fc5bd..aeb41a57dd 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 @@ -8,7 +8,6 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { @@ -140,6 +139,15 @@ namespace Volo.Abp.Identity.EntityFrameworkCore join role in DbContext.Roles.IncludeDetails(includeDetails) on userRole.RoleId equals role.Id where userRole.UserId == id select role; + //TODO + //var q2 = from userOrganization in DbContext.Set() + // join userOrg in DbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOrganization.UserId equals id + // select userOrg.Roles; + //var q3 = from ouRole in DbContext.Set() + // join role in DbContext.Roles.IncludeDetails(includeDetails) on ouRole.RoleId equals role.Id + // where ouRole.RoleId == id + // select role; + //query = q2.Union(query); return await query.ToListAsync(GetCancellationToken(cancellationToken)); } 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 38cac16b3e..1f8ecdb045 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 @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs index 06cd9ac2c9..f27c9b534a 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs index 0acf396912..811280de7b 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index 89d53616c2..7dfe662884 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -2,7 +2,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.Modeling; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Users.EntityFrameworkCore; namespace Volo.Abp.Identity.EntityFrameworkCore diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs index 6203233dcc..5e4a0a2876 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs @@ -1,6 +1,5 @@ using System.Linq; using Microsoft.EntityFrameworkCore; -using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity.EntityFrameworkCore { diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs index a78dca0d0f..3240ce1454 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs @@ -1,6 +1,5 @@ using MongoDB.Driver; using Volo.Abp.Data; -using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs index 7f0d611d92..bc303e0eb5 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs @@ -1,5 +1,4 @@ using System; -using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs index 16a400a772..268c718b12 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Volo.Abp.Users.MongoDB; diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs index 38a38cc828..c903c5d96d 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs @@ -1,6 +1,5 @@ using MongoDB.Driver; using Volo.Abp.Data; -using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB 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 077586572b..68a57962d9 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 @@ -9,7 +9,6 @@ using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Guids; -using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB 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 5f11fa8477..b9d3151017 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 @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.MongoDB; -using Volo.Abp.Identity.Organizations; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB @@ -20,7 +19,7 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetChildrenAsync( - Guid? parentId, + Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -30,8 +29,8 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetAllChildrenWithParentCodeAsync( - string code, - Guid? parentId, + string code, + Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -41,7 +40,7 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetListAsync( - IEnumerable ids, + IEnumerable ids, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -51,8 +50,8 @@ namespace Volo.Abp.Identity.MongoDB } public async Task GetOrganizationUnitAsync( - string displayName, - bool includeDetails = false, + string displayName, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable() diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index 467597ad65..d4bc45f2b6 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -1,15 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Shouldly; -using Volo.Abp.Identity.Organizations; -using Volo.Abp.Castle.DynamicProxy; using Volo.Abp.Uow; using Xunit; -using System.Linq; namespace Volo.Abp.Identity { diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 9148888eac..95bad2fd22 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -1,11 +1,8 @@ using Microsoft.AspNetCore.Identity; using Shouldly; -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; -using Volo.Abp.Identity.Organizations; +using Volo.Abp.Guids; using Volo.Abp.Uow; using Xunit; @@ -19,6 +16,7 @@ namespace Volo.Abp.Identity private readonly IIdentityRoleRepository _identityRoleRepository; private readonly ILookupNormalizer _lookupNormalizer; private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly IGuidGenerator _guidGenerator; public OrganizationUnitManager_Tests() { _organizationUnitManager = GetRequiredService(); @@ -27,12 +25,13 @@ namespace Volo.Abp.Identity _lookupNormalizer = GetRequiredService(); _testData = GetRequiredService(); _unitOfWorkManager = GetRequiredService(); + _guidGenerator = GetService(); } [Fact] public async Task CreateAsnyc() { - await _organizationUnitManager.CreateAsync(new OrganizationUnit(null, "Root 1")); + await _organizationUnitManager.CreateAsync(new OrganizationUnit(_guidGenerator.Create(), "Root 1")); var root1 = await _organizationUnitRepository.GetOrganizationUnitAsync("Root 1"); root1.ShouldNotBeNull(); 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 dec33c0bcd..c59d8eea0a 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 @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; -using Volo.Abp.Identity.Organizations; namespace Volo.Abp.Identity { @@ -88,7 +87,7 @@ namespace Volo.Abp.Identity var ou2 = await CreateOU("OU2", OrganizationUnit.CreateCode(2)); var ou21 = await CreateOU("OU21", OrganizationUnit.CreateCode(2, 1), ou2.Id); - _ou111 = new OrganizationUnit(null, "OU111", ou11.Id); + _ou111 = new OrganizationUnit(_guidGenerator.Create(), "OU111", ou11.Id); _ou111.Code = OrganizationUnit.CreateCode(1, 1, 1); _ou111.AddRole(_moderatorRole.Id); _ou111.AddRole(_managerRole.Id); @@ -134,7 +133,7 @@ namespace Volo.Abp.Identity private async Task CreateOU(string displayName, string code, Guid? parentId = null) { - var ou = await _organizationUnitRepository.InsertAsync(new OrganizationUnit(null, displayName, parentId) { Code = code }); + var ou = await _organizationUnitRepository.InsertAsync(new OrganizationUnit(_guidGenerator.Create(), displayName, parentId) { Code = code }); return ou; } } 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 f7fe17c2e7..59964ba28e 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 @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Shouldly; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Xunit; diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs index 0b8821d363..6d541d5987 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/Identity_Repository_Resolve_Tests.cs @@ -2,7 +2,6 @@ using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Xunit; diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs index 43a570ec16..e49655829a 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs @@ -3,7 +3,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Shouldly; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Volo.Abp.Uow; using Xunit; 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 5d09eace23..b6b4cf746b 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 @@ -1,13 +1,9 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Shouldly; -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using Volo.Abp.Guids; -using Volo.Abp.Identity.Organizations; using Volo.Abp.Modularity; using Xunit; From 29dbcb08abb18da424792a5a6eda4e55f0e049f9 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Fri, 17 Apr 2020 21:03:09 +0300 Subject: [PATCH 24/35] fixed unit roles not getting when all roles are requested from EfCoreIdentityUserRepository --- .../Volo.Abp.Identity.Domain.csproj | 4 -- .../EfCoreIdentityUserRepository.cs | 48 +++++++++++-------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj index 4e0e27f17c..fa22210db0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.csproj @@ -33,8 +33,4 @@ - - - - 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 aeb41a57dd..5ddf1213df 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 @@ -6,6 +6,7 @@ using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Internal; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -19,7 +20,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task FindByNormalizedUserNameAsync( - string normalizedUserName, + string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -32,7 +33,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task> GetRoleNamesAsync( - Guid id, + Guid id, CancellationToken cancellationToken = default) { var query = from userRole in DbContext.Set() @@ -57,8 +58,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task FindByLoginAsync( - string loginProvider, - string providerKey, + string loginProvider, + string providerKey, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -90,7 +91,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task> GetListByNormalizedRoleNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -110,10 +111,10 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task> GetListAsync( - string sorting = null, + string sorting = null, int maxResultCount = int.MaxValue, - int skipCount = 0, - string filter = null, + int skipCount = 0, + string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -138,22 +139,27 @@ namespace Volo.Abp.Identity.EntityFrameworkCore var query = from userRole in DbContext.Set() join role in DbContext.Roles.IncludeDetails(includeDetails) on userRole.RoleId equals role.Id where userRole.UserId == id - select role; - //TODO - //var q2 = from userOrganization in DbContext.Set() - // join userOrg in DbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOrganization.UserId equals id - // select userOrg.Roles; - //var q3 = from ouRole in DbContext.Set() - // join role in DbContext.Roles.IncludeDetails(includeDetails) on ouRole.RoleId equals role.Id - // where ouRole.RoleId == id - // select role; - //query = q2.Union(query); - - return await query.ToListAsync(GetCancellationToken(cancellationToken)); + select role; + + //TODO: Needs improvement + var userOrganizationsQuery = from userOrg in DbContext.Set() + join ou in DbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOrg.OrganizationUnitId equals ou.Id + where userOrg.UserId == id + select ou; + + var orgUserRoleQuery = DbContext.Set().Where(q => userOrganizationsQuery.Select(t => t.Id).Contains(q.OrganizationUnitId)) + .Select(t => t.RoleId); + + var orgRoles = DbContext.Roles.Where(q => orgUserRoleQuery.Contains(q.Id)); + var resultQuery = query.Union(orgRoles); + + return await resultQuery.ToListAsync(GetCancellationToken(cancellationToken)); + + //return await query.ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync( - string filter = null, + string filter = null, CancellationToken cancellationToken = default) { return await this.WhereIf( From cc7921ebe711ee214c0cf3d09d70c2b0d69ec25e Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sat, 18 Apr 2020 01:47:44 +0300 Subject: [PATCH 25/35] fixed error with not counting organizationUnitRoles when roles are requested --- .../Identity/IOrganizationUnitRepository.cs | 5 +++ .../EfCoreIdentityUserRepository.cs | 9 ++-- .../EfCoreOrganizationUnitRepository.cs | 15 ++++++- .../MongoDB/MongoIdentityUserRepository.cs | 22 +++++++++- .../MongoOrganizationUnitRepository.cs | 12 +++++- .../Identity/IdentityUserAppService_Tests.cs | 3 +- .../OrganizationUnitRepository_Tests.cs | 6 +-- .../Identity/IdentityUserRepository_Tests.cs | 6 ++- .../OrganizationUnitRepository_Tests.cs | 41 +++++++++++++------ 9 files changed, 91 insertions(+), 28 deletions(-) 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 6c2b6d9a3c..c7783cb949 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 @@ -32,5 +32,10 @@ namespace Volo.Abp.Identity bool includeDetails = false, CancellationToken cancellationToken = default ); + Task> GetOrganizationUnitRoles( + Guid organizationUnitId, + bool includeDetails = false, + 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 5ddf1213df..46a5ef341a 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 @@ -39,9 +39,12 @@ namespace Volo.Abp.Identity.EntityFrameworkCore var query = from userRole in DbContext.Set() join role in DbContext.Roles on userRole.RoleId equals role.Id where userRole.UserId == id - select role.Name; - - return await query.ToListAsync(GetCancellationToken(cancellationToken)); + select role.Name; + var organizationUnitIds = DbContext.Set().Where(q => q.UserId == id).Select(q => q.OrganizationUnitId).ToArray(); + var organizationRoleIds = DbContext.Set().Where(our => organizationUnitIds.Contains(our.OrganizationUnitId)).Select(r => r.RoleId).ToArray(); + var orgUnitRoleNameQuery = DbContext.Roles.Where(r => organizationRoleIds.Contains(r.Id)).Select(n => n.Name); + var resultQuery = query.Union(orgUnitRoleNameQuery); + return await resultQuery.ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetRoleNamesInOrganizationUnitAsync( 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 1f8ecdb045..2de8cb3f52 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 @@ -54,8 +54,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public async Task GetOrganizationUnitAsync( - string displayName, - bool includeDetails = false, + string displayName, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet @@ -64,6 +64,17 @@ namespace Volo.Abp.Identity.EntityFrameworkCore ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) ); + } + public async Task> GetOrganizationUnitRoles( + Guid organizationUnitId, bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var query = from organizationRole in DbContext.Set() + join role in DbContext.Roles.IncludeDetails(includeDetails) on organizationRole.RoleId equals role.Id + where organizationRole.OrganizationUnitId == organizationUnitId + select role; + + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } public override IQueryable WithDetails() 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 68a57962d9..e6469238ae 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 @@ -39,8 +39,17 @@ namespace Volo.Abp.Identity.MongoDB CancellationToken cancellationToken = default) { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); + var organizationUnitIds = user.OrganizationUnits + .Select(r => r.OrganizationUnitId) + .ToArray(); + var organizationUnits = DbContext.OrganizationUnits + .AsQueryable() + .Where(ou => organizationUnitIds.Contains(ou.Id)) + .ToArray(); + var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); - return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)); + var allRoleIds = orgUnitRoleIds.Union(roleIds); + return await DbContext.Roles.AsQueryable().Where(r => allRoleIds.Contains(r.Id)).Select(r => r.Name).ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetRoleNamesInOrganizationUnitAsync( @@ -140,8 +149,17 @@ namespace Volo.Abp.Identity.MongoDB CancellationToken cancellationToken = default) { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); + var organizationUnitIds = user.OrganizationUnits + .Select(r => r.OrganizationUnitId) + .ToArray(); + var organizationUnits = DbContext.OrganizationUnits + .AsQueryable() + .Where(ou => organizationUnitIds.Contains(ou.Id)) + .ToArray(); + var orgUnitRoleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); var roleIds = user.Roles.Select(r => r.RoleId).ToArray(); - return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(GetCancellationToken(cancellationToken)); + var allRoleIds = orgUnitRoleIds.Union(roleIds); + return await DbContext.Roles.AsQueryable().Where(r => allRoleIds.Contains(r.Id)).ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetOrganizationUnitsAsync( 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 b9d3151017..a86bbc1194 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 @@ -59,6 +59,16 @@ namespace Volo.Abp.Identity.MongoDB ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) ); - } + } + + public async Task> GetOrganizationUnitRoles( + Guid organizationUnitId, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var organizationUnit = await GetAsync(organizationUnitId, includeDetails, cancellationToken); + var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); + return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(cancellationToken); + } } } 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 24807de7b7..a56631b2ae 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 @@ -215,9 +215,10 @@ namespace Volo.Abp.Identity //Assert var roleNames = await _userRepository.GetRoleNamesAsync(johnNash.Id); - roleNames.Count.ShouldBe(2); + roleNames.Count.ShouldBe(3); roleNames.ShouldContain("admin"); roleNames.ShouldContain("moderator"); + roleNames.ShouldContain("manager"); } private static string CreateRandomEmail() diff --git a/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs index 8fa9a14dba..3e8de4f511 100644 --- a/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/OrganizationUnitRepository_Tests.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Volo.Abp.Identity.EntityFrameworkCore +namespace Volo.Abp.Identity.EntityFrameworkCore { public class OrganizationUnitRepository_Tests : OrganizationUnitRepository_Tests { 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 59964ba28e..7aef8f6c87 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 @@ -44,9 +44,10 @@ namespace Volo.Abp.Identity { var john = await UserRepository.FindByNormalizedUserNameAsync(LookupNormalizer.NormalizeName("john.nash")); var roles = await UserRepository.GetRoleNamesAsync(john.Id); - roles.Count.ShouldBe(2); + roles.Count.ShouldBe(3); roles.ShouldContain("moderator"); roles.ShouldContain("supporter"); + roles.ShouldContain("manager"); } [Fact] @@ -118,9 +119,10 @@ namespace Volo.Abp.Identity { var john = await UserRepository.FindByNormalizedUserNameAsync(LookupNormalizer.NormalizeName("john.nash")); var roles = await UserRepository.GetRolesAsync(john.Id); - roles.Count.ShouldBe(2); + roles.Count.ShouldBe(3); roles.ShouldContain(r => r.Name == "moderator"); roles.ShouldContain(r => r.Name == "supporter"); + roles.ShouldContain(r => r.Name == "manager"); } [Fact] 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 b6b4cf746b..4e35a606b3 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 @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using Volo.Abp.Guids; using Volo.Abp.Modularity; +using Volo.Abp.Uow; using Xunit; namespace Volo.Abp.Identity @@ -12,37 +13,43 @@ namespace Volo.Abp.Identity public abstract class OrganizationUnitRepository_Tests : AbpIdentityTestBase where TStartupModule : IAbpModule { - protected IOrganizationUnitRepository OrganizationUnitRepository { get; } - protected ILookupNormalizer LookupNormalizer { get; } + private readonly IOrganizationUnitRepository _organizationUnitRepository; + private readonly ILookupNormalizer _lookupNormalizer; private readonly IdentityTestData _testData; - private readonly IGuidGenerator _guidGenerator; + private readonly IGuidGenerator _guidGenerator; + private readonly OrganizationUnitManager _organizationUnitManager; + private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly IUnitOfWorkManager _unitOfWorkManager; public OrganizationUnitRepository_Tests() { - OrganizationUnitRepository = ServiceProvider.GetRequiredService(); - LookupNormalizer = ServiceProvider.GetRequiredService(); + _organizationUnitRepository = ServiceProvider.GetRequiredService(); + _lookupNormalizer = ServiceProvider.GetRequiredService(); _testData = GetRequiredService(); _guidGenerator = GetRequiredService(); + _organizationUnitManager = GetRequiredService(); + _identityRoleRepository = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); } [Fact] public async Task GetChildrenAsync() { - (await OrganizationUnitRepository.GetChildrenAsync(_testData.RoleModeratorId)).ShouldNotBeNull(); + (await _organizationUnitRepository.GetChildrenAsync(_testData.RoleModeratorId)).ShouldNotBeNull(); } [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)) + var ouIds = (await _organizationUnitRepository.GetListAsync(includeDetails: true)) .Select(ou => ou.Id).Take(2); - var ous = await OrganizationUnitRepository.GetListAsync(ouIds); + var ous = await _organizationUnitRepository.GetListAsync(ouIds); ous.Count.ShouldBe(2); ous.ShouldContain(ou => ou.Id == ouIds.First()); } @@ -50,23 +57,33 @@ namespace Volo.Abp.Identity [Fact] public async Task GetOrganizationUnitAsync() { - var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync("OU111"); + var organizationUnit = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); organizationUnit.ShouldNotBeNull(); } [Fact] public async Task GetCountAsync() { - (await OrganizationUnitRepository.GetCountAsync()).ShouldBeGreaterThan(0); + (await _organizationUnitRepository.GetCountAsync()).ShouldBeGreaterThan(0); } [Fact] public async Task Should_Eager_Load_OrganizationUnit_Collections() { - var ou = (await OrganizationUnitRepository.GetListAsync(includeDetails: true)) + var ou = (await _organizationUnitRepository.GetListAsync(includeDetails: true)) .FirstOrDefault(ou => ou.DisplayName == "OU111"); ou.Roles.ShouldNotBeNull(); ou.Roles.Any().ShouldBeTrue(); + } + [Fact] + public async Task GetOrganizationUnitRolesAsync() + { + OrganizationUnit ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111", true); + + var ou111Roles = await _organizationUnitRepository.GetOrganizationUnitRoles(ou.Id, true); + ou111Roles.Count.ShouldBe(2); + ou111Roles.ShouldContain(n => n.Name == "manager"); + ou111Roles.ShouldContain(n => n.Name == "moderator"); } } } From 58f1959cb3365f610ae4f8c6db365aba3a62f5f5 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Tue, 21 Apr 2020 22:21:06 +0300 Subject: [PATCH 26/35] added GetList method for sorting and filtering --- .../Identity/IOrganizationUnitRepository.cs | 12 +++-- .../EfCoreIdentityUserRepository.cs | 36 ++++++------- .../EfCoreOrganizationUnitRepository.cs | 29 +++++++++-- .../MongoDB/MongoIdentityRoleRepository.cs | 11 ++-- .../MongoOrganizationUnitRepository.cs | 51 ++++++++++++------- 5 files changed, 89 insertions(+), 50 deletions(-) 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 c7783cb949..891f4a7519 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 @@ -19,11 +19,17 @@ namespace Volo.Abp.Identity Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default + ); + Task> GetListAsync( + IEnumerable ids, + bool includeDetails = false, + CancellationToken cancellationToken = default ); - Task> GetListAsync( - IEnumerable ids, - bool includeDetails = false, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + bool includeDetails = true, 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 46a5ef341a..e52ebf7b49 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 @@ -6,7 +6,7 @@ using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Internal; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -20,7 +20,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task FindByNormalizedUserNameAsync( - string normalizedUserName, + string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -33,15 +33,15 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task> GetRoleNamesAsync( - Guid id, + Guid id, CancellationToken cancellationToken = default) { var query = from userRole in DbContext.Set() join role in DbContext.Roles on userRole.RoleId equals role.Id where userRole.UserId == id - select role.Name; - var organizationUnitIds = DbContext.Set().Where(q => q.UserId == id).Select(q => q.OrganizationUnitId).ToArray(); - var organizationRoleIds = DbContext.Set().Where(our => organizationUnitIds.Contains(our.OrganizationUnitId)).Select(r => r.RoleId).ToArray(); + select role.Name; + var organizationUnitIds = DbContext.Set().Where(q => q.UserId == id).Select(q => q.OrganizationUnitId).ToArray(); + var organizationRoleIds = DbContext.Set().Where(our => organizationUnitIds.Contains(our.OrganizationUnitId)).Select(r => r.RoleId).ToArray(); var orgUnitRoleNameQuery = DbContext.Roles.Where(r => organizationRoleIds.Contains(r.Id)).Select(n => n.Name); var resultQuery = query.Union(orgUnitRoleNameQuery); return await resultQuery.ToListAsync(GetCancellationToken(cancellationToken)); @@ -61,8 +61,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task FindByLoginAsync( - string loginProvider, - string providerKey, + string loginProvider, + string providerKey, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -94,7 +94,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task> GetListByNormalizedRoleNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -114,10 +114,10 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task> GetListAsync( - string sorting = null, + string sorting = null, int maxResultCount = int.MaxValue, - int skipCount = 0, - string filter = null, + int skipCount = 0, + string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -142,9 +142,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore var query = from userRole in DbContext.Set() join role in DbContext.Roles.IncludeDetails(includeDetails) on userRole.RoleId equals role.Id where userRole.UserId == id - select role; - - //TODO: Needs improvement + select role; + + //TODO: Needs improvement var userOrganizationsQuery = from userOrg in DbContext.Set() join ou in DbContext.OrganizationUnits.IncludeDetails(includeDetails) on userOrg.OrganizationUnitId equals ou.Id where userOrg.UserId == id @@ -156,13 +156,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore var orgRoles = DbContext.Roles.Where(q => orgUserRoleQuery.Contains(q.Id)); var resultQuery = query.Union(orgRoles); - return await resultQuery.ToListAsync(GetCancellationToken(cancellationToken)); - + return await resultQuery.ToListAsync(GetCancellationToken(cancellationToken)); + //return await query.ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task GetCountAsync( - string filter = null, + string filter = null, CancellationToken cancellationToken = default) { return await this.WhereIf( 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 2de8cb3f52..4796e409f9 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 @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; +using System.Linq.Dynamic.Core; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -43,8 +44,21 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public async Task> GetListAsync( + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + bool includeDetails = true, + CancellationToken cancellationToken = default) + { + return await DbSet + .IncludeDetails(includeDetails) + .OrderBy(sorting ?? nameof(OrganizationUnit.DisplayName)) + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + public async Task> GetListAsync( IEnumerable ids, - bool includeDetails = false, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet @@ -54,8 +68,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public async Task GetOrganizationUnitAsync( - string displayName, - bool includeDetails = false, + string displayName, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet @@ -64,9 +78,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) ); - } + } public async Task> GetOrganizationUnitRoles( - Guid organizationUnitId, bool includeDetails = false, + Guid organizationUnitId, bool includeDetails = false, CancellationToken cancellationToken = default) { var query = from organizationRole in DbContext.Set() @@ -81,6 +95,11 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { return GetQueryable().IncludeDetails(); } + } + public class OrganizationUnitRoleWithIdentityRole + { + public IdentityRole IdentityRole { get; set; } + public OrganizationUnitRole OrganizationUnitRole { get; set; } } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs index 7acb9b4e4b..b38a3433d9 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs @@ -7,20 +7,19 @@ using System.Linq.Dynamic.Core; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; -using Volo.Abp.Guids; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB { public class MongoIdentityRoleRepository : MongoDbRepository, IIdentityRoleRepository { - public MongoIdentityRoleRepository(IMongoDbContextProvider dbContextProvider) + public MongoIdentityRoleRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) { } public async Task FindByNormalizedNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -28,9 +27,9 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetListAsync( - string sorting = null, - int maxResultCount = int.MaxValue, - int skipCount = 0, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, bool includeDetails = false, CancellationToken cancellationToken = default) { 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 a86bbc1194..ef689df45d 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 @@ -3,6 +3,7 @@ using MongoDB.Driver.Linq; using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Dynamic.Core; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories.MongoDB; @@ -19,7 +20,7 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetChildrenAsync( - Guid? parentId, + Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -29,29 +30,43 @@ namespace Volo.Abp.Identity.MongoDB } public async Task> GetAllChildrenWithParentCodeAsync( - string code, - Guid? parentId, + string code, + Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable() .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public async Task> GetListAsync( + IEnumerable ids, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + return await GetMongoQueryable() + .Where(t => ids.Contains(t.Id)) + .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task> GetListAsync( - IEnumerable ids, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable() - .Where(t => ids.Contains(t.Id)) + .OrderBy(sorting ?? nameof(OrganizationUnit.DisplayName)) + .As>() + .PageBy>(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } public async Task GetOrganizationUnitAsync( - string displayName, - bool includeDetails = false, + string displayName, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable() @@ -59,16 +74,16 @@ namespace Volo.Abp.Identity.MongoDB ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) ); - } - - public async Task> GetOrganizationUnitRoles( - Guid organizationUnitId, - bool includeDetails = false, - CancellationToken cancellationToken = default) - { - var organizationUnit = await GetAsync(organizationUnitId, includeDetails, cancellationToken); - var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(cancellationToken); - } + } + + public async Task> GetOrganizationUnitRoles( + Guid organizationUnitId, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var organizationUnit = await GetAsync(organizationUnitId, includeDetails, cancellationToken); + var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); + return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(cancellationToken); + } } } From 3705c627b3b40c6b025dda51a0a0389aa87ce1fc Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Fri, 24 Apr 2020 03:44:29 +0300 Subject: [PATCH 27/35] refactored and renamed --- .../Abp/Identity/IIdentityRoleRepository.cs | 4 +++ .../Abp/Identity/IIdentityUserRepository.cs | 10 ++++-- .../Identity/IOrganizationUnitRepository.cs | 23 +++++++------ .../EfCoreIdentityRoleRepository.cs | 19 ++++++++--- .../EfCoreIdentityUserRepository.cs | 19 +++++++++-- .../EfCoreOrganizationUnitRepository.cs | 12 ++----- .../MongoDB/MongoIdentityRoleRepository.cs | 13 ++++++-- .../MongoDB/MongoIdentityUserRepository.cs | 31 ++++++++++++------ .../MongoOrganizationUnitRepository.cs | 6 ++-- .../Abp/Identity/IdentityUserManager_Tests.cs | 6 ++-- .../Identity/OrganizationUnitManager_Tests.cs | 32 +++++++++---------- .../Identity/AbpIdentityTestDataBuilder.cs | 1 + .../Identity/IdentityUserRepository_Tests.cs | 2 +- .../Volo/Abp/Identity/LazyLoading_Tests.cs | 2 +- .../OrganizationUnitRepository_Tests.cs | 22 ++++++++++--- 15 files changed, 133 insertions(+), 69 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs index 3a344b3140..9596d34cfb 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs @@ -20,6 +20,10 @@ namespace Volo.Abp.Identity int skipCount = 0, bool includeDetails = false, CancellationToken cancellationToken = default + ); + Task> GetListAsync( + IEnumerable ids, + CancellationToken cancellationToken = default ); Task> GetDefaultOnesAsync( 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 652dfe23c6..3814ab96e3 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 @@ -33,19 +33,19 @@ namespace Volo.Abp.Identity ); Task FindByNormalizedEmailAsync( - [NotNull] string normalizedEmail, + [NotNull] string normalizedEmail, bool includeDetails = true, CancellationToken cancellationToken = default ); Task> GetListByClaimAsync( - Claim claim, + Claim claim, bool includeDetails = false, CancellationToken cancellationToken = default ); Task> GetListByNormalizedRoleNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = false, CancellationToken cancellationToken = default ); @@ -73,6 +73,10 @@ namespace Volo.Abp.Identity Task> GetUsersInOrganizationUnitAsync( Guid organizationUnitId, CancellationToken cancellationToken = default + ); + Task> GetUsersInOrganizationsListAsync( + List organizationUnitIds, + CancellationToken cancellationToken = default ); Task> GetUsersInOrganizationUnitWithChildrenAsync( 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 891f4a7519..a0ef631d2b 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 @@ -20,25 +20,28 @@ namespace Volo.Abp.Identity bool includeDetails = false, CancellationToken cancellationToken = default ); - Task> GetListAsync( - IEnumerable ids, - bool includeDetails = false, + + Task GetAsync( + string displayName, + bool includeDetails = true, CancellationToken cancellationToken = default ); + Task> GetListAsync( string sorting = null, int maxResultCount = int.MaxValue, int skipCount = 0, - bool includeDetails = true, - CancellationToken cancellationToken = default - ); - - Task GetOrganizationUnitAsync( - string displayName, bool includeDetails = false, CancellationToken cancellationToken = default + ); + + Task> GetListAsync( + IEnumerable ids, + bool includeDetails = false, + CancellationToken cancellationToken = default ); - Task> GetOrganizationUnitRoles( + + Task> GetRolesAsync( Guid organizationUnitId, bool includeDetails = false, CancellationToken cancellationToken = default diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs index dfaaf51d91..d2a83f276d 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs @@ -19,7 +19,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task FindByNormalizedNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -29,9 +29,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore } public virtual async Task> GetListAsync( - string sorting = null, - int maxResultCount = int.MaxValue, - int skipCount = 0, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -40,6 +40,15 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .OrderBy(sorting ?? nameof(IdentityRole.Name)) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task> GetListAsync( + IEnumerable ids, + CancellationToken cancellationToken = default) + { + return await DbSet + .Where(t => ids.Contains(t.Id)) + .ToListAsync(GetCancellationToken(cancellationToken)); } public virtual async Task> GetDefaultOnesAsync( @@ -51,6 +60,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); - } + } } } \ No newline at end of file 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 e52ebf7b49..d2b0b73ce2 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 @@ -197,9 +197,24 @@ namespace Volo.Abp.Identity.EntityFrameworkCore where userOu.OrganizationUnitId == organizationUnitId select user; return await query.ToListAsync(GetCancellationToken(cancellationToken)); + } + + public async Task> GetUsersInOrganizationsListAsync( + List organizationUnitIds, + CancellationToken cancellationToken = default + ) + { + //var userIds = DbContext.Set() + // .Where(q => organizationUnitIds.Contains(q.OrganizationUnitId)) + // .Select(u => u.UserId); + //var query = DbContext.Users.Where(u => userIds.Contains(u.Id)); + var query = from userOu in DbContext.Set() + join user in DbSet on userOu.UserId equals user.Id + where organizationUnitIds.Contains(userOu.OrganizationUnitId) + select user; + return await query.ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task> GetUsersInOrganizationUnitWithChildrenAsync( string code, CancellationToken cancellationToken = default @@ -216,6 +231,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); - } + } } } 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 4796e409f9..dbb0304438 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 @@ -67,9 +67,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task GetOrganizationUnitAsync( + public async Task GetAsync( string displayName, - bool includeDetails = false, + bool includeDetails = true, CancellationToken cancellationToken = default) { return await DbSet @@ -79,7 +79,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore GetCancellationToken(cancellationToken) ); } - public async Task> GetOrganizationUnitRoles( + public async Task> GetRolesAsync( Guid organizationUnitId, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -96,10 +96,4 @@ namespace Volo.Abp.Identity.EntityFrameworkCore return GetQueryable().IncludeDetails(); } } - - public class OrganizationUnitRoleWithIdentityRole - { - public IdentityRole IdentityRole { get; set; } - public OrganizationUnitRole OrganizationUnitRole { get; set; } - } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs index b38a3433d9..5311ffe094 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs @@ -26,7 +26,7 @@ namespace Volo.Abp.Identity.MongoDB return await GetMongoQueryable().FirstOrDefaultAsync(r => r.NormalizedName == normalizedRoleName, GetCancellationToken(cancellationToken)); } - public async Task> GetListAsync( + public virtual async Task> GetListAsync( string sorting = null, int maxResultCount = int.MaxValue, int skipCount = 0, @@ -40,10 +40,19 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } + public virtual async Task> GetListAsync( + IEnumerable ids, + CancellationToken cancellationToken = default) + { + return await GetMongoQueryable() + .Where(t => ids.Contains(t.Id)) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + public virtual async Task> GetDefaultOnesAsync( bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable().Where(r => r.IsDefault).ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); - } + } } } \ No newline at end of file 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 e6469238ae..4b90caa9f5 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 @@ -23,7 +23,7 @@ namespace Volo.Abp.Identity.MongoDB } public virtual async Task FindByNormalizedUserNameAsync( - string normalizedUserName, + string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -35,7 +35,7 @@ namespace Volo.Abp.Identity.MongoDB } public virtual async Task> GetRoleNamesAsync( - Guid id, + Guid id, CancellationToken cancellationToken = default) { var user = await GetAsync(id, cancellationToken: GetCancellationToken(cancellationToken)); @@ -60,13 +60,13 @@ namespace Volo.Abp.Identity.MongoDB var organizationUnitIds = user.OrganizationUnits .Select(r => r.OrganizationUnitId) - .ToArray(); - + .ToArray(); + var organizationUnits = DbContext.OrganizationUnits .AsQueryable() .Where(ou => organizationUnitIds.Contains(ou.Id)) - .ToArray(); - + .ToArray(); + var roleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); return await DbContext.Roles //TODO: Such usage suppress filters! @@ -77,8 +77,8 @@ namespace Volo.Abp.Identity.MongoDB } public virtual async Task FindByLoginAsync( - string loginProvider, - string providerKey, + string loginProvider, + string providerKey, bool includeDetails = true, CancellationToken cancellationToken = default) { @@ -106,7 +106,7 @@ namespace Volo.Abp.Identity.MongoDB } public virtual async Task> GetListByNormalizedRoleNameAsync( - string normalizedRoleName, + string normalizedRoleName, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -200,6 +200,17 @@ namespace Volo.Abp.Identity.MongoDB return result; } + public async Task> GetUsersInOrganizationsListAsync( + List organizationUnitIds, + CancellationToken cancellationToken = default) + { + var result = await GetMongoQueryable() + .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) + .ToListAsync(GetCancellationToken(cancellationToken)) + ; + return result; + } + public async Task> GetUsersInOrganizationUnitWithChildrenAsync( string code, CancellationToken cancellationToken = default) @@ -214,6 +225,6 @@ namespace Volo.Abp.Identity.MongoDB .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)) ; - } + } } } \ No newline at end of file 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 ef689df45d..bc7cdcda91 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 @@ -64,9 +64,9 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task GetOrganizationUnitAsync( + public async Task GetAsync( string displayName, - bool includeDetails = false, + bool includeDetails = true, CancellationToken cancellationToken = default) { return await GetMongoQueryable() @@ -76,7 +76,7 @@ namespace Volo.Abp.Identity.MongoDB ); } - public async Task> GetOrganizationUnitRoles( + public async Task> GetRolesAsync( Guid organizationUnitId, bool includeDetails = false, CancellationToken cancellationToken = default) diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index d4bc45f2b6..04f08ed266 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -97,7 +97,7 @@ namespace Volo.Abp.Identity _lookupNormalizer.NormalizeName("david")); user.ShouldNotBeNull(); - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync( + var ou = await _organizationUnitRepository.GetAsync( _lookupNormalizer.NormalizeName("OU11")); ou.ShouldNotBeNull(); @@ -150,7 +150,7 @@ namespace Volo.Abp.Identity { using (var uow = _unitOfWorkManager.Begin()) { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync( + var ou = await _organizationUnitRepository.GetAsync( _lookupNormalizer.NormalizeName("OU111")); ou.ShouldNotBeNull(); @@ -158,7 +158,7 @@ namespace Volo.Abp.Identity _lookupNormalizer.NormalizeName("john.nash")); user.ShouldNotBeNull(); - var ouNew = await _organizationUnitRepository.GetOrganizationUnitAsync( + var ouNew = await _organizationUnitRepository.GetAsync( _lookupNormalizer.NormalizeName("OU2")); ouNew.ShouldNotBeNull(); diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 95bad2fd22..65c1068bb4 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -33,55 +33,55 @@ namespace Volo.Abp.Identity { await _organizationUnitManager.CreateAsync(new OrganizationUnit(_guidGenerator.Create(), "Root 1")); - var root1 = await _organizationUnitRepository.GetOrganizationUnitAsync("Root 1"); + var root1 = await _organizationUnitRepository.GetAsync("Root 1"); root1.ShouldNotBeNull(); } [Fact] public async Task UpdateAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); + var ou = await _organizationUnitRepository.GetAsync("OU111"); ou.Code = OrganizationUnit.CreateCode(123); await _organizationUnitManager.UpdateAsync(ou); - var ouAfterChange = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); + var ouAfterChange = await _organizationUnitRepository.GetAsync("OU111"); ouAfterChange.Code.ShouldContain("123"); } [Fact] public async Task DeleteAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11"); + var ou = await _organizationUnitRepository.GetAsync("OU11"); await _organizationUnitManager.DeleteAsync(ou.Id); - (await _organizationUnitRepository.GetOrganizationUnitAsync("OU11")).ShouldBeNull(); + (await _organizationUnitRepository.GetAsync("OU11")).ShouldBeNull(); } [Fact] public async Task MoveAsync() { - var ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1"); - var ou2 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU2"); + var ou1 = await _organizationUnitRepository.GetAsync("OU1"); + var ou2 = await _organizationUnitRepository.GetAsync("OU2"); await _organizationUnitManager.MoveAsync(ou1.Id, ou2.Id); - ou1 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1"); + ou1 = await _organizationUnitRepository.GetAsync("OU1"); ou1.ParentId.ShouldBe(ou2.Id); ou1.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2)); - var ou11 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU11"); + var ou11 = await _organizationUnitRepository.GetAsync("OU11"); ou11.ParentId.ShouldBe(ou1.Id); ou11.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1)); - var ou111 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); + var ou111 = await _organizationUnitRepository.GetAsync("OU111"); ou111.ParentId.ShouldBe(ou11.Id); ou111.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 1)); - var ou112 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU112"); + var ou112 = await _organizationUnitRepository.GetAsync("OU112"); ou112.ParentId.ShouldBe(ou11.Id); ou112.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 1, 2)); - var ou12 = await _organizationUnitRepository.GetOrganizationUnitAsync("OU12"); + var ou12 = await _organizationUnitRepository.GetAsync("OU12"); ou12.ParentId.ShouldBe(ou1.Id); ou12.Code.ShouldBe(OrganizationUnit.CreateCode(2, 2, 2)); } @@ -94,7 +94,7 @@ namespace Volo.Abp.Identity using (var uow = _unitOfWorkManager.Begin()) { - ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true); + ou = await _organizationUnitRepository.GetAsync("OU1", true); adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")); await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole, ou); await _organizationUnitRepository.UpdateAsync(ou); @@ -102,19 +102,19 @@ namespace Volo.Abp.Identity await uow.CompleteAsync(); } - ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true); + ou = await _organizationUnitRepository.GetAsync("OU1", includeDetails: true); ou.Roles.First().RoleId.ShouldBe(adminRole.Id); } [Fact] public async Task RemoveRoleFromOrganizationUnitAsync() { - var ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", true); + var ou = await _organizationUnitRepository.GetAsync("OU1", true); var adminRole = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.NormalizeName("admin")); await _organizationUnitManager.AddRoleToOrganizationUnitAsync(adminRole.Id, ou.Id); await _organizationUnitManager.RemoveRoleFromOrganizationUnitAsync(adminRole.Id, ou.Id); - ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU1", includeDetails: true); + ou = await _organizationUnitRepository.GetAsync("OU1", includeDetails: true); ou.Roles.FirstOrDefault(r => r.RoleId == adminRole.Id).ShouldBeNull(); } } 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 c59d8eea0a..8999a9615a 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 @@ -113,6 +113,7 @@ namespace Volo.Abp.Identity await _userRepository.InsertAsync(john); var david = new IdentityUser(_testData.UserDavidId, "david", "david@abp.io"); + david.AddOrganizationUnit(_ou112.Id); await _userRepository.InsertAsync(david); var neo = new IdentityUser(_testData.UserNeoId, "neo", "neo@abp.io"); 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 7aef8f6c87..1d6728c0ae 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 @@ -171,7 +171,7 @@ namespace Volo.Abp.Identity private async Task GetOU(string diplayName) { - var organizationUnit = await OrganizationUnitRepository.GetOrganizationUnitAsync(diplayName); + var organizationUnit = await OrganizationUnitRepository.GetAsync(diplayName); organizationUnit.ShouldNotBeNull(); return organizationUnit; } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs index e49655829a..eae5ee5c1d 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/LazyLoading_Tests.cs @@ -69,7 +69,7 @@ namespace Volo.Abp.Identity { using (var uow = GetRequiredService().Begin()) { - var ou = await OrganizationUnitRepository.GetOrganizationUnitAsync(LookupNormalizer.NormalizeName("OU111"), includeDetails: false); + var ou = await OrganizationUnitRepository.GetAsync(LookupNormalizer.NormalizeName("OU111"), includeDetails: false); ou.Roles.ShouldNotBeNull(); //? ou.Roles.Any().ShouldBeTrue(); 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 4e35a606b3..fb06743500 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 @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Shouldly; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Guids; @@ -20,6 +22,7 @@ namespace Volo.Abp.Identity private readonly OrganizationUnitManager _organizationUnitManager; private readonly IIdentityRoleRepository _identityRoleRepository; private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly IIdentityUserRepository _identityUserRepository; public OrganizationUnitRepository_Tests() { @@ -29,7 +32,8 @@ namespace Volo.Abp.Identity _guidGenerator = GetRequiredService(); _organizationUnitManager = GetRequiredService(); _identityRoleRepository = GetRequiredService(); - _unitOfWorkManager = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + _identityUserRepository = GetRequiredService(); } [Fact] @@ -57,7 +61,7 @@ namespace Volo.Abp.Identity [Fact] public async Task GetOrganizationUnitAsync() { - var organizationUnit = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111"); + var organizationUnit = await _organizationUnitRepository.GetAsync("OU111"); organizationUnit.ShouldNotBeNull(); } @@ -78,12 +82,22 @@ namespace Volo.Abp.Identity [Fact] public async Task GetOrganizationUnitRolesAsync() { - OrganizationUnit ou = await _organizationUnitRepository.GetOrganizationUnitAsync("OU111", true); + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); - var ou111Roles = await _organizationUnitRepository.GetOrganizationUnitRoles(ou.Id, true); + var ou111Roles = await _organizationUnitRepository.GetRolesAsync(ou.Id, true); ou111Roles.Count.ShouldBe(2); ou111Roles.ShouldContain(n => n.Name == "manager"); ou111Roles.ShouldContain(n => n.Name == "moderator"); } + + [Fact] + public async Task GetUsersInOrganizationUnitListAsync() + { + 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 dodo = users.ToDictionary(u => u.Id, u => u); + users.Count.ShouldBeGreaterThan(0); + } } } From 56667e3b520ae9d7d40df7d9b6da810818483212 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Fri, 24 Apr 2020 14:56:14 +0300 Subject: [PATCH 28/35] refactored-II --- .../EntityFrameworkCore/EfCoreIdentityRoleRepository.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs index d2a83f276d..8ebe3fd985 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.Guids; namespace Volo.Abp.Identity.EntityFrameworkCore { @@ -32,7 +31,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore string sorting = null, int maxResultCount = int.MaxValue, int skipCount = 0, - bool includeDetails = true, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet From 7093238d0916f3b6718310baa99e814fb1eeaead Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 30 Apr 2020 18:37:20 +0300 Subject: [PATCH 29/35] OrganizationUnit domain property update for parentId and code --- .../Volo/Abp/Identity/OrganizationUnit.cs | 8 ++++---- .../Volo/Abp/Identity/OrganizationUnitManager_Tests.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs index 4f49e6935d..3d1bbb0531 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnit.cs @@ -18,7 +18,7 @@ namespace Volo.Abp.Identity /// Parent Id. /// Null, if this OU is a root. /// - public virtual Guid? ParentId { get; set; } + public virtual Guid? ParentId { get; internal set; } /// /// Hierarchical Code of this organization unit. @@ -26,13 +26,13 @@ namespace Volo.Abp.Identity /// This is a unique code for a Tenant. /// It's changeable if OU hierarchy is changed. /// - public virtual string Code { get; set; } + public virtual string Code { get; internal set; } /// /// Display name of this role. /// - public virtual string DisplayName { get; set; } - + public virtual string DisplayName { get; set; } + /// /// Roles of this OU. /// diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 65c1068bb4..55684108c3 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -41,10 +41,10 @@ namespace Volo.Abp.Identity public async Task UpdateAsync() { var ou = await _organizationUnitRepository.GetAsync("OU111"); - ou.Code = OrganizationUnit.CreateCode(123); + ou.DisplayName = "OU111 Updated"; await _organizationUnitManager.UpdateAsync(ou); - var ouAfterChange = await _organizationUnitRepository.GetAsync("OU111"); + var ouAfterChange = await _organizationUnitRepository.GetAsync("OU111 Updated"); ouAfterChange.Code.ShouldContain("123"); } From 06db56de98e305d929b12827ab6ff7ea0caef974 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 30 Apr 2020 19:08:11 +0300 Subject: [PATCH 30/35] fixed update test --- .../Volo/Abp/Identity/OrganizationUnitManager_Tests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index 55684108c3..2f9ac794ac 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -45,7 +45,7 @@ namespace Volo.Abp.Identity await _organizationUnitManager.UpdateAsync(ou); var ouAfterChange = await _organizationUnitRepository.GetAsync("OU111 Updated"); - ouAfterChange.Code.ShouldContain("123"); + ouAfterChange.DisplayName.ShouldContain("OU111 Updated"); } [Fact] From d5563826e21c5ae8f60e6e721d831da4fa2942ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 15 May 2020 18:35:40 +0300 Subject: [PATCH 31/35] Add missing , --- .../Volo/Abp/Identity/Localization/tr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json index 05317af89d..51f1e75dc5 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json @@ -73,7 +73,7 @@ "Permission:ChangePermissions": "İzinleri değiştirme", "Permission:UserManagement": "Kullanıcı yönetimi", "Permission:UserLookup": "Kullanıcı sorgulama", - "Volo.Abp.Identity:010002": "Bir kullanıcı en fazla {MaxUserMembershipCount} organizasyon birimine üye olabilir!" + "Volo.Abp.Identity:010002": "Bir kullanıcı en fazla {MaxUserMembershipCount} organizasyon birimine üye olabilir!", "DisplayName:Abp.Identity.Password.RequiredLength": "Uzunluk gerekli", "DisplayName:Abp.Identity.Password.RequiredUniqueChars": "Tekil karakter gerekli", "DisplayName:Abp.Identity.Password.RequireNonAlphanumeric": "Alfasayısal olmayan karakter gerekli", From ad35165c07c8f98410825bb45397f8de819ab919 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sun, 17 May 2020 04:53:33 +0300 Subject: [PATCH 32/35] organization unit domain update added GetMembersAsync and GetMEmbersCountAsync methods --- .../Identity/IOrganizationUnitRepository.cs | 16 ++++- .../EfCoreOrganizationUnitRepository.cs | 63 ++++++++++++++++--- .../MongoOrganizationUnitRepository.cs | 47 +++++++++++--- .../Identity/AbpIdentityTestDataBuilder.cs | 1 + .../OrganizationUnitRepository_Tests.cs | 39 +++++++++++- 5 files changed, 143 insertions(+), 23 deletions(-) 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 a0ef631d2b..248e663413 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 @@ -42,9 +42,23 @@ namespace Volo.Abp.Identity ); Task> GetRolesAsync( - Guid organizationUnitId, + OrganizationUnit organizationUnit, bool includeDetails = false, CancellationToken cancellationToken = default ); + + Task> GetMembersAsync( + OrganizationUnit organizationUnit, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, + bool includeDetails = false, + CancellationToken cancellationToken = default + ); + Task GetMembersCountAsync( + OrganizationUnit organizationUnit, + CancellationToken cancellationToken = default + ); } } 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 dbb0304438..f00b69bb30 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 @@ -20,7 +20,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore { } - public async Task> GetChildrenAsync( + public virtual async Task> GetChildrenAsync( Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -31,7 +31,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetAllChildrenWithParentCodeAsync( + public virtual async Task> GetAllChildrenWithParentCodeAsync( string code, Guid? parentId, bool includeDetails = false, @@ -43,7 +43,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetListAsync( + public virtual async Task> GetListAsync( string sorting = null, int maxResultCount = int.MaxValue, int skipCount = 0, @@ -56,7 +56,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetListAsync( + public virtual async Task> GetListAsync( IEnumerable ids, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -67,7 +67,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task GetAsync( + public virtual async Task GetAsync( string displayName, bool includeDetails = true, CancellationToken cancellationToken = default) @@ -78,22 +78,65 @@ namespace Volo.Abp.Identity.EntityFrameworkCore ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) ); - } - public async Task> GetRolesAsync( - Guid organizationUnitId, bool includeDetails = false, + } + + public virtual async Task> GetRolesAsync( + OrganizationUnit organizationUnit, + bool includeDetails = false, CancellationToken cancellationToken = default) { var query = from organizationRole in DbContext.Set() join role in DbContext.Roles.IncludeDetails(includeDetails) on organizationRole.RoleId equals role.Id - where organizationRole.OrganizationUnitId == organizationUnitId + where organizationRole.OrganizationUnitId == organizationUnit.Id select role; return await query.ToListAsync(GetCancellationToken(cancellationToken)); } + public virtual async Task> GetMembersAsync( + OrganizationUnit organizationUnit, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, + bool includeDetails = false, + CancellationToken cancellationToken = default + ) + { + var query = from userOu in DbContext.Set() + join user in DbContext.Users.IncludeDetails(includeDetails) on userOu.UserId equals user.Id + where userOu.OrganizationUnitId == organizationUnit.Id + select user; + + if (!filter.IsNullOrWhiteSpace()) + { + query = query.Where(u => + u.UserName.Contains(filter) || + u.Email.Contains(filter) || + (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) + ); + } + + return await query.OrderBy(sorting ?? nameof(IdentityUser.UserName)) + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task GetMembersCountAsync( + OrganizationUnit organizationUnit, + CancellationToken cancellationToken = default) + { + var query = from userOu in DbContext.Set() + join user in DbContext.Users on userOu.UserId equals user.Id + where userOu.OrganizationUnitId == organizationUnit.Id + select user; + + return await query.CountAsync(GetCancellationToken(cancellationToken)); + } + public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); - } + } } } 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 bc7cdcda91..102096f79f 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 @@ -19,7 +19,7 @@ namespace Volo.Abp.Identity.MongoDB { } - public async Task> GetChildrenAsync( + public virtual async Task> GetChildrenAsync( Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -29,7 +29,7 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetAllChildrenWithParentCodeAsync( + public virtual async Task> GetAllChildrenWithParentCodeAsync( string code, Guid? parentId, bool includeDetails = false, @@ -40,7 +40,7 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetListAsync( + public virtual async Task> GetListAsync( IEnumerable ids, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -50,7 +50,7 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task> GetListAsync( + public virtual async Task> GetListAsync( string sorting = null, int maxResultCount = int.MaxValue, int skipCount = 0, @@ -64,7 +64,7 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public async Task GetAsync( + public virtual async Task GetAsync( string displayName, bool includeDetails = true, CancellationToken cancellationToken = default) @@ -76,14 +76,43 @@ namespace Volo.Abp.Identity.MongoDB ); } - public async Task> GetRolesAsync( - Guid organizationUnitId, + public virtual async Task> GetRolesAsync( + OrganizationUnit organizationUnit, bool includeDetails = false, CancellationToken cancellationToken = default) { - var organizationUnit = await GetAsync(organizationUnitId, includeDetails, cancellationToken); var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(cancellationToken); - } + } + public virtual async Task> GetMembersAsync( + OrganizationUnit organizationUnit, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + return await DbContext.Users.AsQueryable() + .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) + .WhereIf>( + !filter.IsNullOrWhiteSpace(), + u => + u.UserName.Contains(filter) || + u.Email.Contains(filter) + ) + .OrderBy(sorting ?? nameof(IdentityUser.UserName)) + .As>() + .PageBy>(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + + public virtual async Task GetMembersCountAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) + { + return await DbContext.Users.AsQueryable() + .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) + .As>() + .CountAsync(GetCancellationToken(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 8999a9615a..9258be16af 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 @@ -119,6 +119,7 @@ namespace Volo.Abp.Identity var neo = new IdentityUser(_testData.UserNeoId, "neo", "neo@abp.io"); neo.AddRole(_supporterRole.Id); neo.AddClaim(_guidGenerator, new Claim("TestClaimType", "43")); + neo.AddOrganizationUnit(_ou111.Id); await _userRepository.InsertAsync(neo); } 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 fb06743500..1b8dac865a 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 @@ -84,20 +84,53 @@ namespace Volo.Abp.Identity { OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); - var ou111Roles = await _organizationUnitRepository.GetRolesAsync(ou.Id, true); + var ou111Roles = await _organizationUnitRepository.GetRolesAsync(ou, true); ou111Roles.Count.ShouldBe(2); ou111Roles.ShouldContain(n => n.Name == "manager"); ou111Roles.ShouldContain(n => n.Name == "moderator"); } [Fact] - public async Task GetUsersInOrganizationUnitListAsync() + public async Task GetMembersInOrganizationUnitListAsync() { 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 dodo = users.ToDictionary(u => u.Id, u => u); users.Count.ShouldBeGreaterThan(0); } + [Fact] + public async Task GetMembersInOrganizationUnitWithParamsAsync() + { + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); + var users = await _organizationUnitRepository.GetMembersAsync(ou, "UserName DESC", 5, 0, "n"); + + users.Count.ShouldBeGreaterThan(1); + users.Count.ShouldBeLessThanOrEqualTo(5); + + //Filter check + users.ShouldAllBe(u => u.UserName.Contains("ne") || u.Email.Contains("n")); + + //Order check + for (var i = 0; i < users.Count - 1; i++) + { + string.Compare( + users[i].UserName, + users[i + 1].UserName, + StringComparison.OrdinalIgnoreCase + ).ShouldBeGreaterThan(0); + } + + users = await _organizationUnitRepository.GetMembersAsync(ou, null, 999, 0, "undefined-username"); + users.Count.ShouldBe(0); + } + + [Fact] + public async Task GetCountMembersCountInOrganizationUnit() + { + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); + var users = await _organizationUnitRepository.GetMembersCountAsync(ou); + + users.ShouldBeGreaterThan(1); + } } } From d08946381ee7dd7063b48e6f7fcf72da220a0fd2 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Wed, 20 May 2020 02:23:00 +0300 Subject: [PATCH 33/35] updated tr localization and removed unused guidGenerator from MongoIdentityUserRepository --- .../Volo/Abp/Identity/Localization/tr.json | 3 ++- .../MongoDB/MongoIdentityUserRepository.cs | 21 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json index 51f1e75dc5..0b17e51276 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json @@ -64,6 +64,7 @@ "Identity.UserNotInRole": "Kullanıcı '{0}' rolünde değil.", "Identity.PasswordConfirmationFailed": "Yeni şifre ile onay şifresi uyuşmuyor.", "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "{0} isminde bir birim zaten var. Aynı seviyede aynı isimli iki birim olamaz.", + "Identity.OrganizationUnit.MaxUserMembershipCount": "Bir kullanıcı için izin verilen en fazla organizasyon birimi sayısı", "Volo.Abp.Identity:010001": "Kendi hesabınızı silemezsiniz!", "Permission:IdentityManagement": "Kimlik yönetimi", "Permission:RoleManagement": "Rol yönetimi", @@ -74,7 +75,7 @@ "Permission:UserManagement": "Kullanıcı yönetimi", "Permission:UserLookup": "Kullanıcı sorgulama", "Volo.Abp.Identity:010002": "Bir kullanıcı en fazla {MaxUserMembershipCount} organizasyon birimine üye olabilir!", - "DisplayName:Abp.Identity.Password.RequiredLength": "Uzunluk gerekli", + "DisplayName:Abp.Identity.Password.RequiredLength": "Uzunluk gerekli", "DisplayName:Abp.Identity.Password.RequiredUniqueChars": "Tekil karakter gerekli", "DisplayName:Abp.Identity.Password.RequireNonAlphanumeric": "Alfasayısal olmayan karakter gerekli", "DisplayName:Abp.Identity.Password.RequireLowercase": "Küçük harf gerekli", 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 3b6c1ef031..b82fdf987c 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,7 +8,6 @@ using System.Threading.Tasks; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; -using Volo.Abp.Guids; using Volo.Abp.MongoDB; namespace Volo.Abp.Identity.MongoDB @@ -58,13 +57,13 @@ namespace Volo.Abp.Identity.MongoDB var organizationUnitIds = user.OrganizationUnits .Select(r => r.OrganizationUnitId) - .ToArray(); - + .ToArray(); + var organizationUnits = DbContext.OrganizationUnits .AsQueryable() .Where(ou => organizationUnitIds.Contains(ou.Id)) - .ToArray(); - + .ToArray(); + var roleIds = organizationUnits.SelectMany(x => x.Roles.Select(r => r.RoleId)).ToArray(); return await DbContext.Roles //TODO: Such usage suppress filters! @@ -202,15 +201,15 @@ namespace Volo.Abp.Identity.MongoDB return result; } - public async Task> GetUsersInOrganizationsListAsync( - List organizationUnitIds, - CancellationToken cancellationToken = default) - { + public async Task> GetUsersInOrganizationsListAsync( + List organizationUnitIds, + CancellationToken cancellationToken = default) + { var result = await GetMongoQueryable() .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)) ; - return result; + return result; } public async Task> GetUsersInOrganizationUnitWithChildrenAsync( @@ -227,6 +226,6 @@ namespace Volo.Abp.Identity.MongoDB .Where(u => u.OrganizationUnits.Any(uou => organizationUnitIds.Contains(uou.OrganizationUnitId))) .ToListAsync(GetCancellationToken(cancellationToken)) ; - } + } } } From 431fe807eb392143789253b8d677087ffcb59c58 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Wed, 20 May 2020 11:40:26 +0300 Subject: [PATCH 34/35] Updated IOrganizationUnitRepository Updated GetRolesAsync with paging. added test --- .../Identity/IOrganizationUnitRepository.cs | 27 +++---- .../EfCoreOrganizationUnitRepository.cs | 52 ++++++++------ .../MongoOrganizationUnitRepository.cs | 47 +++++++------ .../OrganizationUnitRepository_Tests.cs | 70 +++++++++++-------- 4 files changed, 111 insertions(+), 85 deletions(-) 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 248e663413..c4867420ed 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 @@ -19,12 +19,12 @@ namespace Volo.Abp.Identity Guid? parentId, bool includeDetails = false, CancellationToken cancellationToken = default - ); - - Task GetAsync( - string displayName, - bool includeDetails = true, - CancellationToken cancellationToken = default + ); + + Task GetAsync( + string displayName, + bool includeDetails = true, + CancellationToken cancellationToken = default ); Task> GetListAsync( @@ -33,16 +33,19 @@ namespace Volo.Abp.Identity int skipCount = 0, bool includeDetails = false, CancellationToken cancellationToken = default - ); - - Task> GetListAsync( - IEnumerable ids, - bool includeDetails = false, - CancellationToken cancellationToken = default + ); + + Task> GetListAsync( + IEnumerable ids, + bool includeDetails = false, + CancellationToken cancellationToken = default ); Task> GetRolesAsync( OrganizationUnit organizationUnit, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, bool includeDetails = false, CancellationToken cancellationToken = default ); 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 f00b69bb30..180d011810 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 @@ -55,10 +55,10 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .OrderBy(sorting ?? nameof(OrganizationUnit.DisplayName)) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); - } - public virtual async Task> GetListAsync( + } + public virtual async Task> GetListAsync( IEnumerable ids, - bool includeDetails = false, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbSet @@ -78,10 +78,13 @@ namespace Volo.Abp.Identity.EntityFrameworkCore ou => ou.DisplayName == displayName, GetCancellationToken(cancellationToken) ); - } - + } + public virtual async Task> GetRolesAsync( - OrganizationUnit organizationUnit, + OrganizationUnit organizationUnit, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -89,6 +92,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore join role in DbContext.Roles.IncludeDetails(includeDetails) on organizationRole.RoleId equals role.Id where organizationRole.OrganizationUnitId == organizationUnit.Id select role; + query = query + .OrderBy(sorting ?? nameof(IdentityRole.Name)) + .PageBy(skipCount, maxResultCount); return await query.ToListAsync(GetCancellationToken(cancellationToken)); } @@ -108,35 +114,35 @@ namespace Volo.Abp.Identity.EntityFrameworkCore where userOu.OrganizationUnitId == organizationUnit.Id select user; - if (!filter.IsNullOrWhiteSpace()) - { - query = query.Where(u => - u.UserName.Contains(filter) || - u.Email.Contains(filter) || - (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) - ); + if (!filter.IsNullOrWhiteSpace()) + { + query = query.Where(u => + u.UserName.Contains(filter) || + u.Email.Contains(filter) || + (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) + ); } return await query.OrderBy(sorting ?? nameof(IdentityUser.UserName)) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); - } - - public virtual async Task GetMembersCountAsync( - OrganizationUnit organizationUnit, - CancellationToken cancellationToken = default) - { + } + + public virtual async Task GetMembersCountAsync( + OrganizationUnit organizationUnit, + CancellationToken cancellationToken = default) + { var query = from userOu in DbContext.Set() join user in DbContext.Users on userOu.UserId equals user.Id where userOu.OrganizationUnitId == organizationUnit.Id - select user; - - return await query.CountAsync(GetCancellationToken(cancellationToken)); + select user; + + return await query.CountAsync(GetCancellationToken(cancellationToken)); } public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); - } + } } } 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 102096f79f..666af68e8b 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 @@ -38,11 +38,11 @@ namespace Volo.Abp.Identity.MongoDB return await GetMongoQueryable() .Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value) .ToListAsync(GetCancellationToken(cancellationToken)); - } - - public virtual async Task> GetListAsync( + } + + public virtual async Task> GetListAsync( IEnumerable ids, - bool includeDetails = false, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable() @@ -78,19 +78,26 @@ namespace Volo.Abp.Identity.MongoDB public virtual async Task> GetRolesAsync( OrganizationUnit organizationUnit, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, bool includeDetails = false, CancellationToken cancellationToken = default) { var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); - return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)).ToListAsync(cancellationToken); - } - public virtual async Task> GetMembersAsync( - OrganizationUnit organizationUnit, - string sorting = null, - int maxResultCount = int.MaxValue, - int skipCount = 0, - string filter = null, - bool includeDetails = false, + return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)) + .OrderBy(sorting ?? nameof(IdentityRole.Name)) + .As>() + .PageBy>(skipCount, maxResultCount) + .ToListAsync(cancellationToken); + } + public virtual async Task> GetMembersAsync( + OrganizationUnit organizationUnit, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + string filter = null, + bool includeDetails = false, CancellationToken cancellationToken = default) { return await DbContext.Users.AsQueryable() @@ -105,14 +112,14 @@ namespace Volo.Abp.Identity.MongoDB .As>() .PageBy>(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); - } - - public virtual async Task GetMembersCountAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) - { + } + + public virtual async Task GetMembersCountAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) + { return await DbContext.Users.AsQueryable() .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) - .As>() - .CountAsync(GetCancellationToken(cancellationToken)); - } + .As>() + .CountAsync(GetCancellationToken(cancellationToken)); + } } } 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 1b8dac865a..a6cd719e1f 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 @@ -1,13 +1,13 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using Shouldly; -using System; -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Guids; using Volo.Abp.Modularity; -using Volo.Abp.Uow; +using Volo.Abp.Uow; using Xunit; namespace Volo.Abp.Identity @@ -18,7 +18,7 @@ namespace Volo.Abp.Identity private readonly IOrganizationUnitRepository _organizationUnitRepository; private readonly ILookupNormalizer _lookupNormalizer; private readonly IdentityTestData _testData; - private readonly IGuidGenerator _guidGenerator; + private readonly IGuidGenerator _guidGenerator; private readonly OrganizationUnitManager _organizationUnitManager; private readonly IIdentityRoleRepository _identityRoleRepository; private readonly IUnitOfWorkManager _unitOfWorkManager; @@ -32,8 +32,8 @@ namespace Volo.Abp.Identity _guidGenerator = GetRequiredService(); _organizationUnitManager = GetRequiredService(); _identityRoleRepository = GetRequiredService(); - _unitOfWorkManager = GetRequiredService(); - _identityUserRepository = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + _identityUserRepository = GetRequiredService(); } [Fact] @@ -78,36 +78,46 @@ namespace Volo.Abp.Identity .FirstOrDefault(ou => ou.DisplayName == "OU111"); ou.Roles.ShouldNotBeNull(); ou.Roles.Any().ShouldBeTrue(); - } + } [Fact] public async Task GetOrganizationUnitRolesAsync() { - OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", includeDetails: true); - var ou111Roles = await _organizationUnitRepository.GetRolesAsync(ou, true); + var ou111Roles = await _organizationUnitRepository.GetRolesAsync(ou, includeDetails: true); ou111Roles.Count.ShouldBe(2); ou111Roles.ShouldContain(n => n.Name == "manager"); ou111Roles.ShouldContain(n => n.Name == "moderator"); } [Fact] - public async Task GetMembersInOrganizationUnitListAsync() - { - 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 }); - users.Count.ShouldBeGreaterThan(0); + public async Task GetOrganizationUnitRolesWithPagingAsync() + { + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", 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"); + } + + [Fact] + public async Task GetMembersInOrganizationUnitListAsync() + { + 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 }); + users.Count.ShouldBeGreaterThan(0); } [Fact] - public async Task GetMembersInOrganizationUnitWithParamsAsync() - { - OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); - var users = await _organizationUnitRepository.GetMembersAsync(ou, "UserName DESC", 5, 0, "n"); - + public async Task GetMembersInOrganizationUnitWithParamsAsync() + { + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); + var users = await _organizationUnitRepository.GetMembersAsync(ou, "UserName DESC", 5, 0, "n"); + users.Count.ShouldBeGreaterThan(1); - users.Count.ShouldBeLessThanOrEqualTo(5); - - //Filter check + users.Count.ShouldBeLessThanOrEqualTo(5); + + //Filter check users.ShouldAllBe(u => u.UserName.Contains("ne") || u.Email.Contains("n")); //Order check @@ -121,16 +131,16 @@ namespace Volo.Abp.Identity } users = await _organizationUnitRepository.GetMembersAsync(ou, null, 999, 0, "undefined-username"); - users.Count.ShouldBe(0); + users.Count.ShouldBe(0); } [Fact] - public async Task GetCountMembersCountInOrganizationUnit() - { - OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); - var users = await _organizationUnitRepository.GetMembersCountAsync(ou); - - users.ShouldBeGreaterThan(1); + public async Task GetCountMembersCountInOrganizationUnit() + { + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); + var users = await _organizationUnitRepository.GetMembersCountAsync(ou); + + users.ShouldBeGreaterThan(1); } } } From 424d64e23a9d9921c86b00f91dacf84ce72616e4 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Wed, 20 May 2020 11:59:50 +0300 Subject: [PATCH 35/35] Updated OrganizationUnitRepository Added GetRolesCount and tests --- .../Abp/Identity/IOrganizationUnitRepository.cs | 5 +++++ .../EfCoreOrganizationUnitRepository.cs | 12 ++++++++++++ .../MongoDB/MongoOrganizationUnitRepository.cs | 15 ++++++++++++++- .../Identity/OrganizationUnitRepository_Tests.cs | 15 ++++++++++++--- 4 files changed, 43 insertions(+), 4 deletions(-) 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 c4867420ed..def41cdc8a 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 @@ -50,6 +50,11 @@ namespace Volo.Abp.Identity CancellationToken cancellationToken = default ); + Task GetRolesCountAsync( + OrganizationUnit organizationUnit, + CancellationToken cancellationToken = default + ); + Task> GetMembersAsync( OrganizationUnit organizationUnit, string sorting = null, 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 180d011810..350f64ffe7 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 @@ -99,6 +99,18 @@ namespace Volo.Abp.Identity.EntityFrameworkCore return await query.ToListAsync(GetCancellationToken(cancellationToken)); } + public virtual async Task GetRolesCountAsync( + OrganizationUnit organizationUnit, + CancellationToken cancellationToken = default) + { + var query = from organizationRole in DbContext.Set() + join role in DbContext.Roles on organizationRole.RoleId equals role.Id + where organizationRole.OrganizationUnitId == organizationUnit.Id + select role; + + return await query.CountAsync(GetCancellationToken(cancellationToken)); + } + public virtual async Task> GetMembersAsync( OrganizationUnit organizationUnit, string sorting = null, 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 666af68e8b..ae735300fd 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 @@ -91,6 +91,17 @@ namespace Volo.Abp.Identity.MongoDB .PageBy>(skipCount, maxResultCount) .ToListAsync(cancellationToken); } + + public virtual async Task GetRolesCountAsync( + OrganizationUnit organizationUnit, + CancellationToken cancellationToken = default) + { + var roleIds = organizationUnit.Roles.Select(r => r.RoleId).ToArray(); + return await DbContext.Roles.AsQueryable().Where(r => roleIds.Contains(r.Id)) + .As>() + .CountAsync(cancellationToken); + } + public virtual async Task> GetMembersAsync( OrganizationUnit organizationUnit, string sorting = null, @@ -114,7 +125,9 @@ namespace Volo.Abp.Identity.MongoDB .ToListAsync(GetCancellationToken(cancellationToken)); } - public virtual async Task GetMembersCountAsync(OrganizationUnit organizationUnit, CancellationToken cancellationToken = default) + public virtual async Task GetMembersCountAsync( + OrganizationUnit organizationUnit, + CancellationToken cancellationToken = default) { return await DbContext.Users.AsQueryable() .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) 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 a6cd719e1f..6f6835396d 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 @@ -135,12 +135,21 @@ namespace Volo.Abp.Identity } [Fact] - public async Task GetCountMembersCountInOrganizationUnit() + public async Task GetMembersCountOfOrganizationUnit() { OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); - var users = await _organizationUnitRepository.GetMembersCountAsync(ou); + var usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou); - users.ShouldBeGreaterThan(1); + usersCount.ShouldBeGreaterThan(1); + } + + [Fact] + public async Task GetRolesCountOfOrganizationUnit() + { + OrganizationUnit ou = await _organizationUnitRepository.GetAsync("OU111", true); + var rolesCount = await _organizationUnitRepository.GetRolesCountAsync(ou); + + rolesCount.ShouldBeGreaterThan(1); } } }