| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Threading.Tasks;
- using Abp;
- using Abp.Application.Features;
- using Abp.Authorization;
- using Abp.Collections.Extensions;
- using Abp.Domain.Services;
- using Abp.Domain.Uow;
- using Abp.Localization;
- using Abp.MultiTenancy;
- using Abp.Runtime.Caching;
- using IwbZero.Authorization.Base.Permissions;
- using IwbZero.Authorization.Base.Roles;
- using IwbZero.Authorization.Users;
- using IwbZero.IdentityFramework;
- using IwbZero.Runtime.Caching;
- using IwbZero.Runtime.Session;
- using IwbZero.Zero.Configuration;
- using Microsoft.AspNet.Identity;
- namespace IwbZero.Authorization.Roles
- {
- /// <summary>
- /// Extends <see cref="RoleManager{TRole,TKey}"/> of ASP.NET Identity Framework.
- /// Applications should derive this class with appropriate generic arguments.
- /// </summary>
- public abstract class IwbRoleManager<TRole, TUser>
- : RoleManager<TRole, int>,
- IDomainService
- where TRole : IwbSysRole<TUser>, new()
- where TUser : IwbSysUser<TUser>
- {
- public ILocalizationManager LocalizationManager { get; set; }
- protected string LocalizationSourceName { get; set; }
- public IIwbSession AbpSession { get; set; }
- public IRoleManagementConfig RoleManagementConfig { get; private set; }
- public FeatureDependencyContext FeatureDependencyContext { get; set; }
- private IRolePermissionStore<TRole> RolePermissionStore
- {
- get
- {
- if (!(Store is IRolePermissionStore<TRole>))
- {
- throw new AbpException("Store is not IRolePermissionStore");
- }
- return Store as IRolePermissionStore<TRole>;
- }
- }
- protected IwbRoleStore<TRole, TUser> IwbStore { get; private set; }
- protected IPermissionManager PermissionManager { get; }
- protected ICacheManager CacheManager { get; }
- protected IUnitOfWorkManager UnitOfWorkManager { get; }
- //private readonly IRepository<OrganizationUnit, long> _organizationUnitRepository;
- //private readonly IRepository<OrganizationUnitRole, long> _organizationUnitRoleRepository;
- /// <summary>
- /// Constructor.
- /// </summary>
- protected IwbRoleManager(
- IwbRoleStore<TRole, TUser> store,
- IPermissionManager permissionManager,
- IRoleManagementConfig roleManagementConfig,
- ICacheManager cacheManager,
- IUnitOfWorkManager unitOfWorkManager)
- : base(store)
- {
- PermissionManager = permissionManager;
- CacheManager = cacheManager;
- UnitOfWorkManager = unitOfWorkManager;
- RoleManagementConfig = roleManagementConfig;
- IwbStore = store;
- AbpSession = NullIwbSession.Instance;
- LocalizationManager = NullLocalizationManager.Instance;
- LocalizationSourceName = IwbZeroConsts.LocalizationSourceName;
- }
- /// <summary>
- /// Checks if a role is granted for a permission.
- /// </summary>
- /// <param name="roleName">The role's name to check it's permission</param>
- /// <param name="permissionName">Name of the permission</param>
- /// <returns>True, if the role has the permission</returns>
- public virtual async Task<bool> IsGrantedAsync(string roleName, string permissionName)
- {
- return await IsGrantedAsync((await GetRoleByNameAsync(roleName)).Id, PermissionManager.GetPermission(permissionName));
- }
- /// <summary>
- /// Checks if a role has a permission.
- /// </summary>
- /// <param name="roleId">The role's id to check it's permission</param>
- /// <param name="permissionName">Name of the permission</param>
- /// <returns>True, if the role has the permission</returns>
- public virtual async Task<bool> IsGrantedAsync(int roleId, string permissionName)
- {
- return await IsGrantedAsync(roleId, PermissionManager.GetPermission(permissionName));
- }
- /// <summary>
- /// Checks if a role is granted for a permission.
- /// </summary>
- /// <param name="role">The role</param>
- /// <param name="permission">The permission</param>
- /// <returns>True, if the role has the permission</returns>
- public Task<bool> IsGrantedAsync(TRole role, Permission permission)
- {
- return IsGrantedAsync(role.Id, permission);
- }
- /// <summary>
- /// Checks if a role is granted for a permission.
- /// </summary>
- /// <param name="roleId">role id</param>
- /// <param name="permission">The permission</param>
- /// <returns>True, if the role has the permission</returns>
- public virtual async Task<bool> IsGrantedAsync(int roleId, Permission permission)
- {
- //Get cached role permissions
- var cacheItem = await GetRolePermissionCacheItemAsync(roleId);
- //Check the permission
- return cacheItem.GrantedPermissions.Contains(permission.Name);
- }
- /// <summary>
- /// Checks if a role is granted for a permission.
- /// </summary>
- /// <param name="role">role </param>
- /// <param name="operType"></param>
- /// <param name="permission">The permission</param>
- /// <param name="dataKey"></param>
- /// <returns>True, if the role has the permission</returns>
- public virtual async Task<bool> IsGrantedAsync(TRole role, string dataKey, int operType, Permission permission)
- {
- return await IsGrantedAsync(role.Id, dataKey, operType, permission.Name);
- }
- /// <summary>
- /// Checks if a role is granted for a permission.
- /// </summary>
- /// <param name="roleId">role id</param>
- /// <param name="operType"></param>
- /// <param name="permission">The permission</param>
- /// <param name="dataKey"></param>
- /// <returns>True, if the role has the permission</returns>
- public virtual async Task<bool> IsGrantedAsync(int roleId, string dataKey, int operType, Permission permission)
- {
- return await IsGrantedAsync(roleId, dataKey, operType, permission.Name);
- }
- /// <summary>
- /// Checks if a role is granted for a permission.
- /// </summary>
- /// <param name="role">role </param>
- /// <param name="operType"></param>
- /// <param name="permissionName">The permission</param>
- /// <param name="dataKey"></param>
- /// <returns>True, if the role has the permission</returns>
- public virtual async Task<bool> IsGrantedAsync(TRole role, string dataKey, int operType, string permissionName)
- {
- return await IsGrantedAsync(role.Id, dataKey, operType, permissionName);
- }
- /// <summary>
- /// Checks if a role is granted for a data Permission.
- /// </summary>
- /// <param name="roleId">role id</param>
- /// <param name="operType"></param>
- /// <param name="permissionName">The permission</param>
- /// <param name="dataKey"></param>
- /// <returns>True, if the role has the permission</returns>
- public virtual async Task<bool> IsGrantedAsync(int roleId, string dataKey, int operType, string permissionName)
- {
- //Get cached role permissions
- var cacheItem = await GetRoleDataPermissionCacheItemAsync(roleId);
- //Check the permission
- // ReSharper disable once PossibleUnintendedLinearSearchInSet
- return cacheItem.GrantedPermissions.Contains($"{permissionName}@{dataKey}@{operType}", DataPermissionNameComparer.Instance);
- }
- /// <summary>
- /// Gets granted permission names for a role.
- /// </summary>
- /// <param name="roleId">Role id</param>
- /// <returns>List of granted permissions</returns>
- public virtual async Task<IReadOnlyList<Permission>> GetGrantedPermissionsAsync(int roleId)
- {
- return await GetGrantedPermissionsAsync(await GetRoleByIdAsync(roleId));
- }
- /// <summary>
- /// Gets granted permission names for a role.
- /// </summary>
- /// <param name="roleName">Role name</param>
- /// <returns>List of granted permissions</returns>
- public virtual async Task<IReadOnlyList<Permission>> GetGrantedPermissionsAsync(string roleName)
- {
- return await GetGrantedPermissionsAsync(await GetRoleByNameAsync(roleName));
- }
- /// <summary>
- /// Gets granted permissions for a role.
- /// </summary>
- /// <param name="role">Role</param>
- /// <returns>List of granted permissions</returns>
- public virtual async Task<IReadOnlyList<Permission>> GetGrantedPermissionsAsync(TRole role)
- {
- var permissionList = new List<Permission>();
- foreach (var permission in PermissionManager.GetAllPermissions())
- {
- if (await IsGrantedAsync(role.Id, permission))
- {
- permissionList.Add(permission);
- }
- }
- return permissionList;
- }
- /// <summary>
- /// Sets all granted permissions of a role at once.
- /// Prohibits all other permissions.
- /// </summary>
- /// <param name="roleId">Role id</param>
- /// <param name="permissions">Permissions</param>
- public virtual async Task SetGrantedPermissionsAsync(int roleId, IEnumerable<Permission> permissions)
- {
- await SetGrantedPermissionsAsync(await GetRoleByIdAsync(roleId), permissions);
- }
- /// <summary>
- /// Sets all granted permissions of a role at once.
- /// Prohibits all other permissions.
- /// </summary>
- /// <param name="role">The role</param>
- /// <param name="permissions">Permissions</param>
- public virtual async Task SetGrantedPermissionsAsync(TRole role, IEnumerable<Permission> permissions)
- {
- var oldPermissions = await GetGrantedPermissionsAsync(role);
- var newPermissions = permissions.ToArray();
- foreach (var permission in oldPermissions.Where(p => !newPermissions.Contains(p, PermissionEqualityComparer.Instance)))
- {
- //await ProhibitPermissionAsync(role, permission);
- await RemovePermissionAsync(role, permission);
- }
- foreach (var permission in newPermissions.Where(p => !oldPermissions.Contains(p, PermissionEqualityComparer.Instance)))
- {
- await GrantPermissionAsync(role, permission);
- }
- }
- /// <summary>
- /// Grants a permission for a role.
- /// </summary>
- /// <param name="role">Role</param>
- /// <param name="permission">Permission</param>
- public async Task GrantPermissionAsync(TRole role, Permission permission)
- {
- if (await IsGrantedAsync(role.Id, permission))
- {
- return;
- }
- await RolePermissionStore.RemovePermissionAsync(role, new PermissionGrantInfo(permission.Name, false));
- await RolePermissionStore.AddPermissionAsync(role, new PermissionGrantInfo(permission.Name, true));
- await SetGrantedPermissionCacheItem(role.Id, permission.Name);
- }
- /// <summary>
- /// Prohibits a permission for a role.
- /// </summary>
- /// <param name="role">Role</param>
- /// <param name="permission">Permission</param>
- public async Task ProhibitPermissionAsync(TRole role, Permission permission)
- {
- if (!await IsGrantedAsync(role.Id, permission))
- {
- return;
- }
- await RolePermissionStore.RemovePermissionAsync(role, new PermissionGrantInfo(permission.Name, true));
- await RolePermissionStore.AddPermissionAsync(role, new PermissionGrantInfo(permission.Name, false));
- await SetGrantedPermissionCacheItem(role.Id, permission.Name, false);
- }
- /// <summary>
- /// Prohibits a permission for a role.
- /// </summary>
- /// <param name="role">Role</param>
- /// <param name="permission">Permission</param>
- public async Task RemovePermissionAsync(TRole role, Permission permission)
- {
- if (!await IsGrantedAsync(role.Id, permission))
- {
- return;
- }
- await RolePermissionStore.RemovePermissionAsync(role, new PermissionGrantInfo(permission.Name, true));
- await SetGrantedPermissionCacheItem(role.Id, permission.Name, false);
- }
- /// <summary>
- /// Prohibits all permissions for a role.
- /// </summary>
- /// <param name="role">Role</param>
- public async Task ProhibitAllPermissionsAsync(TRole role)
- {
- foreach (var permission in PermissionManager.GetAllPermissions())
- {
- await ProhibitPermissionAsync(role, permission);
- }
- }
- private async Task SetGrantedPermissionCacheItem(int roleId, string permissionName, bool isAdded = true)
- {
- var permissionCacheItem = await GetRolePermissionCacheItemAsync(roleId);
- if (isAdded)
- permissionCacheItem.GrantedPermissions.AddIfNotContains(permissionName);
- else
- permissionCacheItem.GrantedPermissions.Remove(permissionName);
- }
- /// <summary>
- /// Resets all permission settings for a role.
- /// It removes all permission settings for the role.
- /// </summary>
- /// <param name="role">Role</param>
- public async Task ResetAllPermissionsAsync(TRole role)
- {
- await RolePermissionStore.RemoveAllPermissionSettingsAsync(role);
- }
- /// <summary>
- /// Creates a role.
- /// </summary>
- /// <param name="role">Role</param>
- public override async Task<IdentityResult> CreateAsync(TRole role)
- {
- role.SetNormalizedName();
- var result = await CheckDuplicateRoleNameAsync(role.Id, role.Name, role.DisplayName);
- if (!result.Succeeded)
- {
- return result;
- }
- var tenantId = GetCurrentTenantId();
- if (tenantId.HasValue && !role.TenantId.HasValue)
- {
- role.TenantId = tenantId.Value;
- }
- return await base.CreateAsync(role);
- }
- public override async Task<IdentityResult> UpdateAsync(TRole role)
- {
- role.SetNormalizedName();
- var result = await CheckDuplicateRoleNameAsync(role.Id, role.Name, role.DisplayName);
- if (!result.Succeeded)
- {
- return result;
- }
- return await base.UpdateAsync(role);
- }
- /// <summary>
- /// Deletes a role.
- /// </summary>
- /// <param name="role">Role</param>
- public override async Task<IdentityResult> DeleteAsync(TRole role)
- {
- if (role.IsStatic)
- {
- return AbpIdentityResult.Failed(string.Format(L("CanNotDeleteStaticRole"), role.Name));
- }
- return await base.DeleteAsync(role);
- }
- /// <summary>
- /// Gets a role by given id.
- /// Throws exception if no role with given id.
- /// </summary>
- /// <param name="roleId">Role id</param>
- /// <returns>Role</returns>
- /// <exception cref="AbpException">Throws exception if no role with given id</exception>
- public virtual async Task<TRole> GetRoleByIdAsync(int roleId)
- {
- var role = await FindByIdAsync(roleId);
- if (role == null)
- {
- throw new AbpException("There is no role with id: " + roleId);
- }
- return role;
- }
- /// <summary>
- /// Gets a role by given name.
- /// Throws exception if no role with given roleName.
- /// </summary>
- /// <param name="roleName">Role name</param>
- /// <returns>Role</returns>
- /// <exception cref="AbpException">Throws exception if no role with given roleName</exception>
- public virtual async Task<TRole> GetRoleByNameAsync(string roleName)
- {
- var role = await FindByNameAsync(roleName);
- if (role == null)
- {
- throw new AbpException("There is no role with name: " + roleName);
- }
- return role;
- }
- public async Task GrantAllPermissionsAsync(TRole role)
- {
- FeatureDependencyContext.TenantId = role.TenantId;
- var permissions = PermissionManager.GetAllPermissions(role.GetMultiTenancySide())
- .Where(permission =>
- permission.FeatureDependency == null ||
- permission.FeatureDependency.IsSatisfied(FeatureDependencyContext)
- );
- await SetGrantedPermissionsAsync(role, permissions);
- }
- [UnitOfWork]
- public virtual async Task<IdentityResult> CreateStaticRoles(int tenantId)
- {
- var staticRoleDefinitions = RoleManagementConfig.StaticRoles.Where(sr => sr.Side == MultiTenancySides.Tenant);
- using (UnitOfWorkManager.Current.SetTenantId(tenantId))
- {
- foreach (var staticRoleDefinition in staticRoleDefinitions)
- {
- var role = new TRole
- {
- TenantId = tenantId,
- Name = staticRoleDefinition.RoleName,
- DisplayName = staticRoleDefinition.RoleName,
- AccountType = 1,
- RoleType = 0,
- IsStatic = true
- };
- role.SetNormalizedName();
- var identityResult = await CreateAsync(role);
- if (!identityResult.Succeeded)
- {
- return identityResult;
- }
- }
- }
- return IdentityResult.Success;
- }
- [UnitOfWork]
- public virtual async Task<IdentityResult> CreateStaticRoles(int tenantId, TRole role)
- {
- var staticRoleDefinitions = RoleManagementConfig.StaticRoles.Where(sr => sr.Side == MultiTenancySides.Tenant);
- using (UnitOfWorkManager.Current.SetTenantId(tenantId))
- {
- foreach (var staticRoleDefinition in staticRoleDefinitions)
- {
- role.TenantId = tenantId;
- role.Name = staticRoleDefinition.RoleName;
- role.DisplayName = staticRoleDefinition.RoleName;
- role.IsStatic = true;
- role.SetNormalizedName();
- var identityResult = await CreateAsync(role);
- if (!identityResult.Succeeded)
- {
- return identityResult;
- }
- }
- }
- return IdentityResult.Success;
- }
- public virtual async Task<IdentityResult> CheckDuplicateRoleNameAsync(int? expectedRoleId, string name, string displayName)
- {
- var role = await FindByNameAsync(name);
- if (role != null && role.Id != expectedRoleId)
- {
- return AbpIdentityResult.Failed(string.Format(L("RoleNameIsAlreadyTaken"), name));
- }
- role = await FindByDisplayNameAsync(displayName);
- if (role != null && role.Id != expectedRoleId)
- {
- return AbpIdentityResult.Failed(string.Format(L("RoleDisplayNameIsAlreadyTaken"), displayName));
- }
- return IdentityResult.Success;
- }
- private Task<TRole> FindByDisplayNameAsync(string displayName)
- {
- return IwbStore.FindByDisplayNameAsync(displayName);
- }
- private async Task<RolePermissionCacheItem> GetRolePermissionCacheItemAsync(int roleId)
- {
- var cacheKey = roleId + "@" + (GetCurrentTenantId() ?? 0);
- return await CacheManager.GetRolePermissionCache().GetAsync(cacheKey, async () =>
- {
- var newCacheItem = new RolePermissionCacheItem(roleId);
- var role = await Store.FindByIdAsync(roleId);
- if (role == null)
- {
- throw new AbpException("There is no role with given id: " + roleId);
- }
- var staticRoleDefinition = RoleManagementConfig.StaticRoles.FirstOrDefault(r =>
- r.RoleName == role.Name && r.Side == role.GetMultiTenancySide());
- if (staticRoleDefinition != null)
- {
- foreach (var permission in PermissionManager.GetAllPermissions())
- {
- if (staticRoleDefinition.IsGrantedByDefault(permission))
- {
- newCacheItem.GrantedPermissions.Add(permission.Name);
- }
- }
- }
- foreach (var permissionInfo in await RolePermissionStore.GetPermissionsAsync(roleId))
- {
- if (permissionInfo.IsGranted)
- {
- newCacheItem.GrantedPermissions.AddIfNotContains(permissionInfo.Name);
- }
- else
- {
- newCacheItem.GrantedPermissions.Remove(permissionInfo.Name);
- }
- }
- return newCacheItem;
- });
- }
- private async Task<RolePermissionCacheItem> GetRoleDataPermissionCacheItemAsync(int roleId)
- {
- var cacheKey = $"Data-{roleId}@{GetCurrentTenantId() ?? 0}";
- return await CacheManager.GetRolePermissionCache().GetAsync(cacheKey, async () =>
- {
- var newCacheItem = new RolePermissionCacheItem(roleId);
- var role = await Store.FindByIdAsync(roleId);
- if (role == null)
- {
- throw new AbpException("There is no role with given id: " + roleId);
- }
- foreach (var permissionInfo in await RolePermissionStore.GetPermissionsAsync(roleId))
- {
- if (permissionInfo.IsGranted)
- {
- if (permissionInfo.OperType == 1)
- {
- newCacheItem.GrantedPermissions.AddIfNotContains($"{permissionInfo.Name}@{permissionInfo.DataKey}@{(int)OperType.Create}");
- newCacheItem.GrantedPermissions.AddIfNotContains($"{permissionInfo.Name}@{permissionInfo.DataKey}@{(int)OperType.Update}");
- newCacheItem.GrantedPermissions.AddIfNotContains($"{permissionInfo.Name}@{permissionInfo.DataKey}@{(int)OperType.Delete}");
- newCacheItem.GrantedPermissions.AddIfNotContains($"{permissionInfo.Name}@{permissionInfo.DataKey}@{(int)OperType.Query}");
- }
- else
- {
- newCacheItem.GrantedPermissions.AddIfNotContains($"{permissionInfo.Name}@{permissionInfo.DataKey}@{permissionInfo.OperType}");
- }
- }
- else
- {
- newCacheItem.GrantedPermissions.Remove($"{permissionInfo.Name}@{permissionInfo.DataKey}@{permissionInfo.OperType}");
- }
- }
- return newCacheItem;
- });
- }
- 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;
- }
- }
- }
|