update userManager logic for organization unit

pull/2563/head
Mehmet Perk 6 years ago
parent fbd0d067a0
commit 1b56ed47bb

@ -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; }
}
}

@ -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",

@ -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";
}
}
}

@ -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)
);
}

@ -129,7 +129,7 @@ namespace Volo.Abp.Identity
/// <summary>
/// Navigation property for this organization units.
/// </summary>
public virtual ICollection<OrganizationUnitUser> OrganizationUnits { get; protected set; }
public virtual ICollection<IdentityUserOrganizationUnit> OrganizationUnits { get; protected set; }
protected IdentityUser()
{
@ -154,7 +154,7 @@ namespace Volo.Abp.Identity
Claims = new Collection<IdentityUserClaim>();
Logins = new Collection<IdentityUserLogin>();
Tokens = new Collection<IdentityUserToken>();
OrganizationUnits = new Collection<OrganizationUnitUser>();
OrganizationUnits = new Collection<IdentityUserOrganizationUnit>();
ExtraProperties = new Dictionary<string, object>();
}
@ -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)

@ -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<IdentityUserManager> 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<IdentityUser> 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<bool> IsInOrganizationUnitAsync(Guid userId, Guid ouId)
{
return await IsInOrganizationUnitAsync(
await GetByIdAsync(userId),
await _organizationUnitRepository.GetAsync(ouId)
);
}
public virtual Task<bool> 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<int>(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<List<OrganizationUnit>> 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));
}
}
}

@ -2,12 +2,12 @@
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity.Organizations
namespace Volo.Abp.Identity
{
/// <summary>
/// Represents membership of a User to an OU.
/// </summary>
public class OrganizationUnitUser : CreationAuditedEntity<Guid>, IMultiTenant, ISoftDelete
public class IdentityUserOrganizationUnit : CreationAuditedEntity<Guid>, IMultiTenant, ISoftDelete
{
/// <summary>
@ -33,7 +33,7 @@ namespace Volo.Abp.Identity.Organizations
/// <summary>
/// Initializes a new instance of the <see cref="UserOrganizationUnit"/> class.
/// </summary>
public OrganizationUnitUser()
public IdentityUserOrganizationUnit()
{
}
@ -44,7 +44,7 @@ namespace Volo.Abp.Identity.Organizations
/// <param name="tenantId">TenantId</param>
/// <param name="userId">Id of the User.</param>
/// <param name="organizationUnitId">Id of the <see cref="OrganizationUnit"/>.</param>
public OrganizationUnitUser(Guid? tenantId, Guid userId, Guid organizationUnitId)
public IdentityUserOrganizationUnit(Guid? tenantId, Guid userId, Guid organizationUnitId)
{
TenantId = tenantId;
UserId = userId;

@ -10,5 +10,7 @@ namespace Volo.Abp.Identity.Organizations
Task<List<OrganizationUnit>> GetChildrenAsync(Guid? parentId);
Task<List<OrganizationUnit>> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId);
Task<List<OrganizationUnit>> GetListAsync(IEnumerable<Guid> ids);
}
}

@ -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<List<OrganizationUnit>> GetListAsync(IEnumerable<Guid> ids)
{
return await DbSet.Where(t => ids.Contains(t.Id)).ToListAsync();
}
}
}

@ -165,9 +165,9 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
b.HasIndex(ou => new { ou.RoleId, ou.OrganizationUnitId });
});
builder.Entity<OrganizationUnitUser>(b =>
builder.Entity<IdentityUserOrganizationUnit>(b =>
{
b.ToTable(options.TablePrefix + "OrganizationUnitUsers", options.Schema);
b.ToTable(options.TablePrefix + "UserOrganizationUnits", options.Schema);
b.HasKey(ou => new { ou.OrganizationUnitId, ou.UserId });

Loading…
Cancel
Save