using Abp; using Abp.Authorization; using Abp.Configuration; using Abp.Configuration.Startup; using Abp.Domain.Repositories; using Abp.Domain.Services; using Abp.Domain.Uow; using Abp.Json; using Abp.Localization; using Abp.Runtime.Caching; using Abp.UI; using Castle.Core.Internal; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Newtonsoft.Json; using System.Globalization; using VberZero.Authorization.Roles; using VberZero.BaseSystem.MultiTenancy; using VberZero.BaseSystem.Organizations; using VberZero.BaseSystem.Users; using VberZero.Caching; using VberZero.DomainService.AppGuids; using VberZero.DomainService.Notifications; using VberZero.IdentityFramework; using VberZero.Organizations; using VberZero.Session; using VberZero.Settings; using VberZero.Tools.StringModel; #pragma warning disable CS0162 namespace VberZero.Authorization.Users; public class VzUserManager : UserManager, IDomainService { protected IUserPermissionStore UserPermissionStore { get { if (!(Store is IUserPermissionStore)) { throw new AbpException("Store is not IUserPermissionStore"); } return Store as IUserPermissionStore; } } public ILocalizationManager LocalizationManager { get; set; } protected string LocalizationSourceName { get; set; } public IVzSession AbpSession { get; set; } //public FeatureDependencyContext FeatureDependencyContext { get; set; } protected VzRoleManager RoleManager { get; } protected VzUserStore UserStore { get; } protected IRepository UserRoleRepository { get; } public IMultiTenancyConfig MultiTenancy { get; set; } private readonly IPermissionManager _permissionManager; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly ICacheManager _cacheManager; private readonly IRepository _organizationUnitRepository; private readonly IRepository _userOrganizationUnitRepository; private readonly IOrganizationUnitSettings _organizationUnitSettings; private readonly ISettingManager _settingManager; private readonly IOptions _optionsAccessor; private readonly IAppNotifier _appNotifier; private readonly IAppGuidManager _appGuidManager; public VzUserManager( VzRoleManager roleManager, VzUserStore userStore, IOptions optionsAccessor, IPasswordHasher passwordHasher, IEnumerable> userValidators, IEnumerable> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger> logger, IPermissionManager permissionManager, IUnitOfWorkManager unitOfWorkManager, ICacheManager cacheManager, IRepository organizationUnitRepository, IRepository userOrganizationUnitRepository, IOrganizationUnitSettings organizationUnitSettings, ISettingManager settingManager, IAppNotifier appNotifier, IAppGuidManager appGuidManager, IRepository userRoleRepository) : base( userStore, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger) { _permissionManager = permissionManager; _unitOfWorkManager = unitOfWorkManager; _cacheManager = cacheManager; _organizationUnitRepository = organizationUnitRepository; _userOrganizationUnitRepository = userOrganizationUnitRepository; _organizationUnitSettings = organizationUnitSettings; _settingManager = settingManager; _appNotifier = appNotifier; _appGuidManager = appGuidManager; UserRoleRepository = userRoleRepository; _optionsAccessor = optionsAccessor; UserStore = userStore; RoleManager = roleManager; LocalizationManager = NullLocalizationManager.Instance; LocalizationSourceName = VzConsts.LocalizationSourceName; AbpSession = NullVzSession.Instance; } #region Permission #region IsGranted /// /// 检查用户权限 /// /// /// /// public virtual async Task IsGrantedAsync(long userId, string permissionName, bool isOnlyUser = false) { return await IsGrantedAsync(userId, _permissionManager.GetPermission(permissionName), isOnlyUser); } /// /// 检查用户权限 /// /// /// /// public virtual bool IsGranted(long userId, string permissionName, bool isOnlyUser = false) { return IsGranted(userId, _permissionManager.GetPermission(permissionName), isOnlyUser); } /// /// 检查用户权限 /// /// /// /// public virtual Task IsGrantedAsync(User user, Permission permission, bool isOnlyUser = false) { if (user == null) { throw new ArgumentNullException(nameof(user)); } return IsGrantedAsync(user.Id, permission, isOnlyUser); } /// /// 检查用户权限 /// /// /// /// public virtual bool IsGranted(User user, Permission permission, bool isOnlyUser = false) { if (user == null) { throw new ArgumentNullException(nameof(user)); } return IsGranted(user.Id, permission, isOnlyUser); } /// /// 检查用户权限 /// /// /// /// public virtual async Task IsGrantedAsync(long userId, Permission permission, bool isOnlyUser = false) { //Check for multi-tenancy side if (!permission.MultiTenancySides.HasFlag(GetCurrentMultiTenancySide())) { return false; } //Check for depended features //if (permission.FeatureDependency != null && GetCurrentMultiTenancySide() == MultiTenancySides.Tenant) //{ // FeatureDependencyContext.TenantId = GetCurrentTenantId(); // if (!await permission.FeatureDependency.IsSatisfiedAsync(FeatureDependencyContext)) // { // return false; // } //} //Get cached user permissions var cacheItem = await GetUserPermissionCacheItemAsync(userId); if (cacheItem == null) { return false; } //Check for user-specific value if (cacheItem.GrantedPermissions.Contains(permission.Name)) { return true; } if (cacheItem.ProhibitedPermissions.Contains(permission.Name)) { return false; } if (isOnlyUser) return false; //Check for roles foreach (var roleId in cacheItem.RoleIds) { if (await RoleManager.IsGrantedAsync(roleId, permission)) { return true; } } return false; } /// /// 检查用户权限 /// /// /// /// public virtual bool IsGranted(long userId, Permission permission, bool isOnlyUser = false) { //Check for multi-tenancy side if (!permission.MultiTenancySides.HasFlag(GetCurrentMultiTenancySide())) { return false; } //Check for depended features //if (permission.FeatureDependency != null && GetCurrentMultiTenancySide() == MultiTenancySides.Tenant) //{ // FeatureDependencyContext.TenantId = GetCurrentTenantId(); // if (!permission.FeatureDependency.IsSatisfied(FeatureDependencyContext)) // { // return false; // } //} //Get cached user permissions var cacheItem = GetUserPermissionCacheItem(userId); if (cacheItem == null) { return false; } //Check for user-specific value if (cacheItem.GrantedPermissions.Contains(permission.Name)) { return true; } if (cacheItem.ProhibitedPermissions.Contains(permission.Name)) { return false; } if (isOnlyUser) return false; //Check for roles foreach (var roleId in cacheItem.RoleIds) { if (RoleManager.IsGranted(roleId, permission)) { return true; } } return false; } #endregion IsGranted /// /// 获取用户的权限。 /// /// /// public virtual async Task> GetGrantedPermissionsAsync(User user) { var permissionList = new List(); foreach (var permission in _permissionManager.GetAllPermissions()) { if (await IsGrantedAsync(user.Id, permission)) { permissionList.Add(permission); } } return permissionList; } /// /// 一次设置用户的所有授予权限。 /// /// /// /// true 移除所有其他权限 false禁止所有其他权限 public virtual async Task SetGrantedPermissionsAsync(User user, IEnumerable permissions, bool isRemove = true) { var oldPermissions = await GetGrantedPermissionsAsync(user); var newPermissions = permissions.ToArray(); foreach (var permission in oldPermissions.Where(p => !newPermissions.Contains(p))) { if (isRemove) { await RemovePermissionAsync(user, permission); } else { await ProhibitPermissionAsync(user, permission); } } foreach (var permission in newPermissions.Where(p => !oldPermissions.Contains(p))) { await GrantPermissionAsync(user, permission); } } /// /// 禁止用户的所有权限。 /// /// public async Task ProhibitAllPermissionsAsync(User user) { foreach (var permission in _permissionManager.GetAllPermissions()) { await ProhibitPermissionAsync(user, permission); } } /// /// /// /// User public async Task ResetAllPermissionsAsync(User user) { await UserPermissionStore.RemoveAllPermissionSettingsAsync(user); } /// /// 重置用户的所有权限设置。 /// 它删除用户的所有权限设置。 用户将根据他的角色拥有权限。 /// 此方法不会禁止所有权限。 为此,请使用 。 /// /// User public void ResetAllPermissions(User user) { UserPermissionStore.RemoveAllPermissionSettings(user); } /// /// 如果尚未授予用户权限,则授予该用户权限。 /// /// User /// Permission public virtual async Task GrantPermissionAsync(User user, Permission permission) { await UserPermissionStore.RemovePermissionAsync(user, new PermissionGrantInfo(permission.Name, false)); if (await IsGrantedAsync(user.Id, permission)) { return; } await UserPermissionStore.AddPermissionAsync(user, new PermissionGrantInfo(permission.Name, true)); } /// /// 如果授予用户权限,则移除该权限。 /// /// User /// Permission public virtual async Task RemovePermissionAsync(User user, Permission permission) { if (!await IsGrantedAsync(user.Id, permission, true)) { return; } await UserPermissionStore.RemovePermissionAsync(user, new PermissionGrantInfo(permission.Name, true)); } /// /// 如果授予用户权限,则禁止该权限。 /// /// User /// Permission public virtual async Task ProhibitPermissionAsync(User user, Permission permission) { await UserPermissionStore.RemovePermissionAsync(user, new PermissionGrantInfo(permission.Name, true)); if (!await IsGrantedAsync(user.Id, permission)) { return; } await UserPermissionStore.AddPermissionAsync(user, new PermissionGrantInfo(permission.Name, false)); } private async Task GetUserPermissionCacheItemAsync(long userId) { var cacheKey = userId + "@" + (GetCurrentTenantId() ?? 0); return await _cacheManager.GetUserPermissionCache().GetAsync(cacheKey, async () => { var user = await FindByIdAsync(userId.ToString()); if (user == null) { return null; } var newCacheItem = new UserPermissionCacheItem(userId); foreach (var roleName in await GetRolesAsync(user)) { newCacheItem.RoleIds.Add((await RoleManager.GetRoleByNameAsync(roleName)).Id); } foreach (var permissionInfo in await UserPermissionStore.GetPermissionsAsync(userId)) { if (permissionInfo.IsGranted) { newCacheItem.GrantedPermissions.Add(permissionInfo.Name); } else { newCacheItem.ProhibitedPermissions.Add(permissionInfo.Name); } } return newCacheItem; }); } private UserPermissionCacheItem GetUserPermissionCacheItem(long userId) { var cacheKey = userId + "@" + (GetCurrentTenantId() ?? 0); return _cacheManager.GetUserPermissionCache()!.Get(cacheKey, () => { var user = UserStore.FindById(userId.ToString()); if (user == null) { return null; } var newCacheItem = new UserPermissionCacheItem(userId); foreach (var roleName in UserStore.GetRoles(user)) { newCacheItem.RoleIds.Add((RoleManager.GetRoleByName(roleName)).Id); } foreach (var permissionInfo in UserPermissionStore.GetPermissions(userId)) { if (permissionInfo.IsGranted) { newCacheItem.GrantedPermissions.Add(permissionInfo.Name); } else { newCacheItem.ProhibitedPermissions.Add(permissionInfo.Name); } } return newCacheItem; }); } #endregion Permission #region CURD #region Query public virtual Task FindByNameOrEmailOrPhoneAsync(string userNameOrEmailOrPhone) { return UserStore.FindByNameOrEmailOrPhoneAsync(userNameOrEmailOrPhone); } public virtual User FindByNameOrEmailOrPhone(string userNameOrEmailOrPhone) { return UserStore.FindByNameOrEmailOrPhone(userNameOrEmailOrPhone); } public virtual Task FindByNameOrEmailOrPhoneAsync(int? tenantId, string userNameOrEmailOrPhone) { return UserStore.FindByNameOrEmailOrPhoneAsync(tenantId, userNameOrEmailOrPhone); } public virtual User FindByNameOrEmailOrPhone(int? tenantId, string userNameOrEmailOrPhone) { return UserStore.FindByNameOrEmailOrPhone(tenantId, userNameOrEmailOrPhone); } public virtual Task> FindAllAsync(UserLoginInfo login) { return UserStore.FindAllAsync(login); } public virtual List FindAll(UserLoginInfo login) { return UserStore.FindAll(login); } public virtual Task FindAsync(int? tenantId, UserLoginInfo login) { return UserStore.FindAsync(tenantId, login); } public virtual User Find(int? tenantId, UserLoginInfo login) { return UserStore.Find(tenantId, login); } /// /// 通过给定的 id 获取用户。 /// 如果没有找到具有给定 id 的用户,则抛出异常。 /// /// /// public virtual async Task GetUserByIdAsync(long userId) { var user = await FindByIdAsync(userId.ToString()); if (user == null) { throw new AbpException("There is no user with id: " + userId); } return user; } /// /// 通过给定的 id 获取用户。 /// 如果没有找到具有给定 id 的用户,则抛出异常。 /// /// /// public virtual User GetUserById(long userId) { var user = UserStore.FindById(userId.ToString()); if (user == null) { throw new AbpException("There is no user with id: " + userId); } return user; } #endregion Query public virtual async Task CreateUser(User user, string[] roles, string[] permissionNames) { user.TenantId = AbpSession.TenantId; user.IsEmailConfirmed = true; user.Name = user.Surname; //var password = await _settingManager.GetSettingValueAsync(VzSettingNames.UserDefaultPassword); //CheckErrors(await CreateAsync(user,password)); CheckErrors(await CreateAsync(user)); await _unitOfWorkManager.Current.SaveChangesAsync(); var roleList = roles?.ToList() ?? new List(); roleList.Add(VzStaticRoleNames.Tenants.Default); roles = roleList.Distinct().ToArray(); if (roles is { Length: > 0 }) { CheckErrors(await SetRolesAsync(user, roles)); } if (permissionNames is { Length: > 0 }) { var grantedPermissions = _permissionManager.GetAllPermissions().Where(p => permissionNames.Contains(p.Name)); await SetGrantedPermissionsAsync(user, grantedPermissions); } await _appNotifier.SubscriptionNotifications(user); return user; } /// /// 创建用户 /// /// /// public override async Task CreateAsync(User user) { var result = await CheckDuplicateUsernameOrEmailOrPhoneAsync(user.Id, user.UserName, user.EmailAddress, user.PhoneNumber); if (!result.Succeeded) { return result; } var tenantId = GetCurrentTenantId(); if (tenantId.HasValue && !user.TenantId.HasValue) { user.TenantId = tenantId.Value; } await InitializeOptionsAsync(user.TenantId); user.UserName = await BindAccount(user.AccountType, user.AccountNo); user.AvatarPath = user.AvatarPath.Empty() ? $"/img/avatar/{user.Gender.ToInt()}_{new Random().Next(1, 6)}.png" : user.AvatarPath; var password = await _settingManager.GetSettingValueAsync(VzSettingNames.UserDefaultPassword); user.Password = PasswordHasher.HashPassword(user, password); user.SetNormalizedNames(); return await base.CreateAsync(user); } /// /// 修改用户 /// /// /// /// public override async Task UpdateAsync(User user) { if (user.UserName == User.AdminUserName && AbpSession.GetUserName() != User.SystemUserName) { throw new UserFriendlyException(string.Format(L("CanNotUpdateAdminUser"), User.AdminUserName)); } if (user.UserName == User.SystemUserName && AbpSession.GetUserName() != User.AdminUserName) { throw new UserFriendlyException(string.Format(L("CanNotUpdateAdminUser"), User.SystemUserName)); } var result = await CheckDuplicateUsernameOrEmailOrPhoneAsync(user.Id, user.UserName, user.EmailAddress, user.PhoneNumber); if (!result.Succeeded) { return result; } //Admin user's username can not be changed! if (user.UserName != User.AdminUserName && (await GetOldUserNameAsync(user.Id)) == User.AdminUserName) { throw new UserFriendlyException(string.Format(L("CanNotRenameAdminUser"), User.AdminUserName)); } //System user's username can not be changed! if (user.UserName != User.SystemUserName && (await GetOldUserNameAsync(user.Id)) == User.SystemUserName) { throw new UserFriendlyException(string.Format(L("CanNotRenameAdminUser"), User.SystemUserName)); } return await base.UpdateAsync(user); } // Microsoft.AspNetCore.Identity.UserManager doesn't have required sync version for method calls in this function //public override IdentityResult Update(User user) //{ // var result = CheckDuplicateUsernameOrEmailAddress(user.Id, user.UserName, user.EmailAddress); // if (!result.Succeeded) // { // return result; // } // //Admin user's username can not be changed! // if (user.UserName != UserBase.AdminUserName) // { // if ((GetOldUserName(user.Id)) == UserBase.AdminUserName) // { // throw new UserFriendlyException(string.Format(L("CanNotRenameAdminUser"), UserBase.AdminUserName)); // } // } // return base.Update(user); //} /// /// 删除用户 /// /// /// /// public override async Task DeleteAsync(User user) { if (user.UserName == User.AdminUserName || user.UserName == User.SystemUserName) { throw new UserFriendlyException(string.Format(L("CanNotDeleteAdminUser"), User.AdminUserName)); } return await base.DeleteAsync(user); } // Microsoft.AspNetCore.Identity.UserManager doesn't have required sync version for method calls in this function //public override IdentityResult Delete(User user) //{ // if (user.UserName == UserBase.AdminUserName) // { // throw new UserFriendlyException(string.Format(L("CanNotDeleteAdminUser"), UserBase.AdminUserName)); // } // return base.Delete(user); //} protected virtual async Task BindAccount(VzDefinition.AccountType accountType, string accountNo) { string userName = ""; if (accountType == VzDefinition.AccountType.System) { var guid = await _appGuidManager.GetGuidFromFileAsync(AppGuidType.System); CheckGuid(guid); userName = "S" + guid; } else if (accountType == VzDefinition.AccountType.Client) { var guid = await _appGuidManager.GetGuidFromFileAsync(AppGuidType.Client); CheckGuid(guid); userName = "C" + guid; /*绑定账号。。。 */ if (!string.IsNullOrEmpty(accountNo)) { } } else ThrowError("InvalidUserType"); return userName; } protected virtual int CheckGuid(int? guid) { if (guid == null || guid == 0) { ThrowError("GetGuidNoError"); return 0; } return (int)guid; } protected virtual void CheckErrors(string error) { throw new UserFriendlyException(error); } protected virtual void CheckErrors(IdentityResult identityResult) { identityResult.CheckErrors(LocalizationManager); } /// /// 抛出错误 /// /// /// 是否要本地化 protected virtual void ThrowError(string err, bool isLocalization = true) { CheckErrors(isLocalization ? L(err) : err); } #endregion CURD /// /// 查询用户的租户名(用户名,邮箱,手机号需要唯一) /// /// /// public async Task GetTenancyNameAsync(string userNameOrEmailOrPhone) { if (!VzConsts.MultiTenancyEnabled) { return Tenant.DefaultTenantName; } var tenancyName = await UserStore.GetTenancyNameAsync(userNameOrEmailOrPhone); return tenancyName; } /// /// 查询用户的租户名(用户名,邮箱,手机号需要唯一) /// /// /// public string GetTenancyName(string userNameOrEmailOrPhone) { if (!VzConsts.MultiTenancyEnabled) { return Tenant.DefaultTenantName; } var tenancyName = UserStore.GetTenancyName (userNameOrEmailOrPhone); return tenancyName; } /// /// 修改密码 /// /// /// /// public virtual async Task ChangePasswordAsync(User user, string newPassword) { var errors = new List(); foreach (var validator in PasswordValidators) { var validationResult = await validator.ValidateAsync(this, user, newPassword); if (!validationResult.Succeeded) { errors.AddRange(validationResult.Errors); } } if (errors.Any()) { return IdentityResult.Failed(errors.ToArray()); } await UserStore.SetPasswordHashAsync(user, PasswordHasher.HashPassword(user, newPassword)); await UpdateSecurityStampAsync(user); return IdentityResult.Success; } // IPasswordValidator doesn't have a sync version of Validate(...) //public virtual IdentityResult ChangePassword(User user, string newPassword) //{ // var errors = new List(); // foreach (var validator in PasswordValidators) // { // var validationResult = validator.Validate(this, user, newPassword); // if (!validationResult.Succeeded) // { // errors.AddRange(validationResult.Errors); // } // } // if (errors.Any()) // { // return IdentityResult.Failed(errors.ToArray()); // } // UserStore.SetPasswordHash(user, PasswordHasher.HashPassword(user, newPassword)); // return IdentityResult.Success; //} /// /// 检查用户名、邮箱、手机号的唯一性 /// /// /// /// /// /// /// public virtual async Task CheckDuplicateUsernameOrEmailOrPhoneAsync(long? expectedUserId, string userName, string emailAddress = "", string phoneNumber = "") { using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant)) { var user = (await FindByNameAsync(userName)); if (user != null && user.Id != expectedUserId) { throw new UserFriendlyException(string.Format(L("Identity.DuplicateUserName"), userName)); } if (!emailAddress.IsNullOrEmpty()) { user = (await FindByEmailAsync(emailAddress)); if (user != null && user.Id != expectedUserId) { throw new UserFriendlyException(string.Format(L("Identity.DuplicateEmail"), emailAddress)); } } if (!phoneNumber.IsNullOrEmpty()) { user = (await UserStore.FindByPhoneAsync(phoneNumber)); if (user != null && user.Id != expectedUserId) { throw new UserFriendlyException(string.Format(L("Identity.DuplicatePhoneNumber"), phoneNumber)); } } return IdentityResult.Success; } } //public override async Task> GetUsersInRoleAsync(string roleName) //{ // var role = await RoleManager.GetRoleByNameAsync(roleName); // var userIds = await UserRoleRepository.GetAll().Where(a => a.RoleId == role.Id).Select(a => a.UserId).ToListAsync(); // var users = await UserStore.UserRepository.GetAllListAsync(a => userIds.Contains(a.Id)); // return users; //} public virtual async Task SetRolesAsync(User user, string[] roleNames) { if ((user.UserName == User.AdminUserName || user.UserName == User.SystemUserName) && !roleNames.Contains(VzStaticRoleNames.Tenants.Admin)) { throw new UserFriendlyException(L("AdminRoleCannotRemoveFromAdminUser")); } //if (!roleNames.Contains(VzStaticRoleNames.Tenants.Default)) //{ // throw new UserFriendlyException(L("DefaultRoleCannotRemoveUser")); //} await UserStore.UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles); //Remove from removed roles foreach (var userRole in user.Roles.ToList()) { var role = await RoleManager.FindByIdAsync(userRole.RoleId.ToString()); if (role?.Name == VzStaticRoleNames.Tenants.Default) { continue; } if (role != null && roleNames.All(roleName => role.Name != roleName)) { var result = await RemoveFromRoleAsync(user, role.Name); if (!result.Succeeded) { return result; } } } //Add to added roles foreach (var roleName in roleNames) { var role = await RoleManager.GetRoleByNameAsync(roleName); if (user.Roles.All(ur => ur.RoleId != role.Id)) { var result = await AddToRoleAsync(user, roleName); if (!result.Succeeded) { return result; } } } return IdentityResult.Success; } public override async Task RemoveFromRoleAsync(User user, string roleName) { ThrowIfDisposed(); if (user == null) { throw new ArgumentNullException(nameof(user)); } try { var role = await RoleManager.GetRoleByNameAsync(roleName); var userRole = await UserRoleRepository.FirstOrDefaultAsync(a => a.UserId == user.Id && a.RoleId == role.Id); if (userRole != null) { await UserRoleRepository.DeleteAsync(userRole); return IdentityResult.Success; } return IdentityResult.Failed(new IdentityError() { Description = "用户没有此角色!" }); } catch (Exception e) { return IdentityResult.Failed(new IdentityError() { Description = e.Message }); } } #region OrganizationUnit public virtual async Task IsInOrganizationUnitAsync(long userId, long ouId) { return await _unitOfWorkManager.WithUnitOfWorkAsync(async () => await IsInOrganizationUnitAsync( await GetUserByIdAsync(userId), await _organizationUnitRepository.GetAsync(ouId) ) ); } public virtual async Task IsInOrganizationUnitAsync(User user, OrganizationUnit ou) { return await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { return await _userOrganizationUnitRepository.CountAsync(uou => uou.UserId == user.Id && uou.OrganizationUnitId == ou.Id ) > 0; }); } public virtual bool IsInOrganizationUnit(User user, OrganizationUnit ou) { return _unitOfWorkManager.WithUnitOfWork(() => { return _userOrganizationUnitRepository.Count(uou => uou.UserId == user.Id && uou.OrganizationUnitId == ou.Id ) > 0; }); } public virtual async Task AddToOrganizationUnitAsync(long userId, long ouId) { await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { await AddToOrganizationUnitAsync( await GetUserByIdAsync(userId), await _organizationUnitRepository.GetAsync(ouId) ); }); } public virtual async Task AddToOrganizationUnitAsync(User user, OrganizationUnit ou) { await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { var currentOus = await GetOrganizationUnitsAsync(user); if (currentOus.Any(cou => cou.Id == ou.Id)) { return; } await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, currentOus.Count + 1); await _userOrganizationUnitRepository.InsertAsync(new UserOrganizationUnit(user.TenantId, user.Id, ou.Id)); }); } public virtual void AddToOrganizationUnit(User user, OrganizationUnit ou) { _unitOfWorkManager.WithUnitOfWork(() => { var currentOus = GetOrganizationUnits(user); if (currentOus.Any(cou => cou.Id == ou.Id)) { return; } CheckMaxUserOrganizationUnitMembershipCount(user.TenantId, currentOus.Count + 1); _userOrganizationUnitRepository.Insert(new UserOrganizationUnit(user.TenantId, user.Id, ou.Id)); }); } public virtual async Task RemoveFromOrganizationUnitAsync(long userId, long ouId) { await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { await RemoveFromOrganizationUnitAsync( await GetUserByIdAsync(userId), await _organizationUnitRepository.GetAsync(ouId) ); }); } public virtual async Task RemoveFromOrganizationUnitAsync(User user, OrganizationUnit ou) { await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { await _userOrganizationUnitRepository.DeleteAsync(uou => uou.UserId == user.Id && uou.OrganizationUnitId == ou.Id ); }); } public virtual void RemoveFromOrganizationUnit(User user, OrganizationUnit ou) { _unitOfWorkManager.WithUnitOfWork(() => { _userOrganizationUnitRepository.Delete( uou => uou.UserId == user.Id && uou.OrganizationUnitId == ou.Id ); }); } public virtual async Task SetOrganizationUnitsAsync(long userId, params long[] organizationUnitIds) { await SetOrganizationUnitsAsync( await GetUserByIdAsync(userId), organizationUnitIds ); } private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(int? tenantId, int requestedCount) { var maxCount = await _organizationUnitSettings.GetMaxUserMembershipCountAsync(tenantId); if (requestedCount > maxCount) { throw new AbpException($"Can not set more than {maxCount} organization unit for a user!"); } } private void CheckMaxUserOrganizationUnitMembershipCount(int? tenantId, int requestedCount) { var maxCount = _organizationUnitSettings.GetMaxUserMembershipCount(tenantId); if (requestedCount > maxCount) { throw new AbpException($"Can not set more than {maxCount} organization unit for a user!"); } } public virtual async Task SetOrganizationUnitsAsync(User user, params long[] organizationUnitIds) { await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { if (organizationUnitIds == null) { organizationUnitIds = new long[0]; } await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, organizationUnitIds.Length); var currentOus = await GetOrganizationUnitsAsync(user); //Remove from removed OUs foreach (var currentOu in currentOus) { if (!organizationUnitIds.Contains(currentOu.Id)) { await RemoveFromOrganizationUnitAsync(user, currentOu); } } await _unitOfWorkManager.Current.SaveChangesAsync(); //Add to added OUs foreach (var organizationUnitId in organizationUnitIds) { if (currentOus.All(ou => ou.Id != organizationUnitId)) { await AddToOrganizationUnitAsync( user, await _organizationUnitRepository.GetAsync(organizationUnitId) ); } } }); } public virtual void SetOrganizationUnits(User user, params long[] organizationUnitIds) { _unitOfWorkManager.WithUnitOfWork(() => { if (organizationUnitIds == null) { organizationUnitIds = new long[0]; } CheckMaxUserOrganizationUnitMembershipCount(user.TenantId, organizationUnitIds.Length); var currentOus = GetOrganizationUnits(user); //Remove from removed OUs foreach (var currentOu in currentOus) { if (!organizationUnitIds.Contains(currentOu.Id)) { RemoveFromOrganizationUnit(user, currentOu); } } //Add to added OUs foreach (var organizationUnitId in organizationUnitIds) { if (currentOus.All(ou => ou.Id != organizationUnitId)) { AddToOrganizationUnit( user, _organizationUnitRepository.Get(organizationUnitId) ); } } }); } public virtual async Task> GetOrganizationUnitsAsync(User user) { var result = _unitOfWorkManager.WithUnitOfWork(() => { var query = from uou in _userOrganizationUnitRepository.GetAll() join ou in _organizationUnitRepository.GetAll() on uou.OrganizationUnitId equals ou.Id where uou.UserId == user.Id select ou; return query.ToList(); }); return await Task.FromResult(result); } public virtual List GetOrganizationUnits(User user) { return _unitOfWorkManager.WithUnitOfWork(() => { var query = from uou in _userOrganizationUnitRepository.GetAll() join ou in _organizationUnitRepository.GetAll() on uou.OrganizationUnitId equals ou.Id where uou.UserId == user.Id select ou; return query.ToList(); }); } public virtual async Task> GetUsersInOrganizationUnitAsync( OrganizationUnit organizationUnit, bool includeChildren = false) { var result = _unitOfWorkManager.WithUnitOfWork(() => { if (!includeChildren) { var query = from uou in _userOrganizationUnitRepository.GetAll() join user in Users on uou.UserId equals user.Id where uou.OrganizationUnitId == organizationUnit.Id select user; return query.ToList(); } else { var query = from uou in _userOrganizationUnitRepository.GetAll() join user in Users on uou.UserId equals user.Id join ou in _organizationUnitRepository.GetAll() on uou.OrganizationUnitId equals ou.Id where ou.Path.StartsWith(organizationUnit.Path) select user; return query.ToList(); } }); return await Task.FromResult(result); } public virtual List GetUsersInOrganizationUnit( OrganizationUnit organizationUnit, bool includeChildren = false) { return _unitOfWorkManager.WithUnitOfWork(() => { if (!includeChildren) { var query = from uou in _userOrganizationUnitRepository.GetAll() join user in Users on uou.UserId equals user.Id where uou.OrganizationUnitId == organizationUnit.Id select user; return query.ToList(); } else { var query = from uou in _userOrganizationUnitRepository.GetAll() join user in Users on uou.UserId equals user.Id join ou in _organizationUnitRepository.GetAll() on uou.OrganizationUnitId equals ou.Id where ou.Path.StartsWith(organizationUnit.Path) select user; return query.ToList(); } }); } #endregion OrganizationUnit public virtual async Task InitializeOptionsAsync(int? tenantId) { Options = JsonConvert.DeserializeObject(_optionsAccessor.Value.ToJsonString()); //Lockout if (Options != null) { Options.Lockout.AllowedForNewUsers = await IsTrueAsync( VzSettingNames.UserManagement.UserLockOut.IsEnabled, tenantId ); Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds( await GetSettingValueAsync( VzSettingNames.UserManagement.UserLockOut.DefaultAccountLockoutSeconds, tenantId ) ); Options.Lockout.MaxFailedAccessAttempts = await GetSettingValueAsync( VzSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout, tenantId ); //Password complexity Options.Password.RequireDigit = await GetSettingValueAsync( VzSettingNames.UserManagement.PasswordComplexity.RequireDigit, tenantId ); Options.Password.RequireLowercase = await GetSettingValueAsync( VzSettingNames.UserManagement.PasswordComplexity.RequireLowercase, tenantId ); Options.Password.RequireNonAlphanumeric = await GetSettingValueAsync( VzSettingNames.UserManagement.PasswordComplexity.RequireNonAlphanumeric, tenantId ); Options.Password.RequireUppercase = await GetSettingValueAsync( VzSettingNames.UserManagement.PasswordComplexity.RequireUppercase, tenantId ); Options.Password.RequiredLength = await GetSettingValueAsync( VzSettingNames.UserManagement.PasswordComplexity.RequiredLength, tenantId ); } } public virtual void InitializeOptions(int? tenantId) { Options = JsonConvert.DeserializeObject(_optionsAccessor.Value.ToJsonString()); //Lockout if (Options != null) { Options.Lockout.AllowedForNewUsers = IsTrue( VzSettingNames.UserManagement.UserLockOut.IsEnabled, tenantId ); Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds( GetSettingValue( VzSettingNames.UserManagement.UserLockOut.DefaultAccountLockoutSeconds, tenantId) ); Options.Lockout.MaxFailedAccessAttempts = GetSettingValue( VzSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout, tenantId); //Password complexity Options.Password.RequireDigit = GetSettingValue( VzSettingNames.UserManagement.PasswordComplexity.RequireDigit, tenantId ); Options.Password.RequireLowercase = GetSettingValue( VzSettingNames.UserManagement.PasswordComplexity.RequireLowercase, tenantId ); Options.Password.RequireNonAlphanumeric = GetSettingValue( VzSettingNames.UserManagement.PasswordComplexity.RequireNonAlphanumeric, tenantId ); Options.Password.RequireUppercase = GetSettingValue( VzSettingNames.UserManagement.PasswordComplexity.RequireUppercase, tenantId ); Options.Password.RequiredLength = GetSettingValue( VzSettingNames.UserManagement.PasswordComplexity.RequiredLength, tenantId ); } } protected virtual Task GetOldUserNameAsync(long userId) { return UserStore.GetUserNameFromDatabaseAsync(userId); } protected virtual string GetOldUserName(long userId) { return UserStore.GetUserNameFromDatabase(userId); } public override async Task> GetValidTwoFactorProvidersAsync(User user) { var providers = new List(); foreach (var provider in await base.GetValidTwoFactorProvidersAsync(user)) { var isEmailProviderEnabled = await IsTrueAsync( VzSettingNames.UserManagement.TwoFactorLogin.IsEmailProviderEnabled, user.TenantId ); if (provider == "Email" && !isEmailProviderEnabled) { continue; } var isSmsProviderEnabled = await IsTrueAsync( VzSettingNames.UserManagement.TwoFactorLogin.IsSmsProviderEnabled, user.TenantId ); if (provider == "Phone" && !isSmsProviderEnabled) { continue; } providers.Add(provider); } return providers; } private bool IsTrue(string settingName, int? tenantId) { return GetSettingValue(settingName, tenantId); } private Task IsTrueAsync(string settingName, int? tenantId) { return GetSettingValueAsync(settingName, tenantId); } private T GetSettingValue(string settingName, int? tenantId) where T : struct { return tenantId == null ? _settingManager.GetSettingValueForApplication(settingName) : _settingManager.GetSettingValueForTenant(settingName, tenantId.Value); } private Task GetSettingValueAsync(string settingName, int? tenantId) where T : struct { return tenantId == null ? _settingManager.GetSettingValueForApplicationAsync(settingName) : _settingManager.GetSettingValueForTenantAsync(settingName, tenantId.Value); } protected virtual string L(string name) { return LocalizationManager.GetString(LocalizationSourceName, name); } protected virtual string L(string name, CultureInfo cultureInfo) { return LocalizationManager.GetString(LocalizationSourceName, name, cultureInfo); } private int? GetCurrentTenantId() { if (_unitOfWorkManager.Current != null) { return _unitOfWorkManager.Current.GetTenantId(); } return AbpSession.TenantId; } private Abp.MultiTenancy.MultiTenancySides GetCurrentMultiTenancySide() { if (_unitOfWorkManager.Current != null) { return MultiTenancy.IsEnabled && !_unitOfWorkManager.Current.GetTenantId().HasValue ? Abp.MultiTenancy.MultiTenancySides.Host : Abp.MultiTenancy.MultiTenancySides.Tenant; } return AbpSession.MultiTenancySide; } public virtual async Task AddTokenValidityKeyAsync( User user, string tokenValidityKey, DateTime expireDate, CancellationToken cancellationToken = default(CancellationToken)) { await UserStore.AddTokenValidityKeyAsync(user, tokenValidityKey, expireDate, cancellationToken); } public virtual void AddTokenValidityKey( User user, string tokenValidityKey, DateTime expireDate, CancellationToken cancellationToken = default(CancellationToken)) { UserStore.AddTokenValidityKey(user, tokenValidityKey, expireDate, cancellationToken); } public virtual async Task IsTokenValidityKeyValidAsync( User user, string tokenValidityKey, CancellationToken cancellationToken = default(CancellationToken)) { return await UserStore.IsTokenValidityKeyValidAsync(user, tokenValidityKey, cancellationToken); } public virtual bool IsTokenValidityKeyValid( User user, string tokenValidityKey, CancellationToken cancellationToken = default(CancellationToken)) { return UserStore.IsTokenValidityKeyValid(user, tokenValidityKey, cancellationToken); } public virtual async Task RemoveTokenValidityKeyAsync( User user, string tokenValidityKey, CancellationToken cancellationToken = default(CancellationToken)) { await UserStore.RemoveTokenValidityKeyAsync(user, tokenValidityKey, cancellationToken); } public virtual void RemoveTokenValidityKey( User user, string tokenValidityKey, CancellationToken cancellationToken = default(CancellationToken)) { UserStore.RemoveTokenValidityKey(user, tokenValidityKey, cancellationToken); } public bool IsLockedOut(string userId) { var user = UserStore.FindById(userId); if (user == null) { throw new AbpException("There is no user with id: " + userId); } var lockoutEndDateUtc = UserStore.GetLockoutEndDate(user); return lockoutEndDateUtc > DateTimeOffset.UtcNow; } public bool IsLockedOut(User user) { var lockoutEndDateUtc = UserStore.GetLockoutEndDate(user); return lockoutEndDateUtc > DateTimeOffset.UtcNow; } public void ResetAccessFailedCount(User user) { UserStore.ResetAccessFailedCount(user); } }