Browse Source

Merge pull request #22214 from abpframework/permission-enhansment

Optimize the database queries for permission checks.
pull/22419/head
maliming 2 years ago
committed by GitHub
parent
commit
974c03cb7b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 54
      modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RolePermissionManagementProvider.cs
  2. 59
      modules/permission-management/src/Volo.Abp.PermissionManagement.Application/Volo/Abp/PermissionManagement/PermissionAppService.cs
  3. 16
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionDataSeeder.cs
  4. 26
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManagementProvider.cs
  5. 85
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs

54
modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RolePermissionManagementProvider.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -37,41 +38,44 @@ public class RolePermissionManagementProvider : PermissionManagementProvider
public async override Task<MultiplePermissionValueProviderGrantInfo> CheckAsync(string[] names, string providerName, string providerKey) public async override Task<MultiplePermissionValueProviderGrantInfo> CheckAsync(string[] names, string providerName, string providerKey)
{ {
var multiplePermissionValueProviderGrantInfo = new MultiplePermissionValueProviderGrantInfo(names); using (PermissionGrantRepository.DisableTracking())
var permissionGrants = new List<PermissionGrant>();
if (providerName == Name)
{ {
permissionGrants.AddRange(await PermissionGrantRepository.GetListAsync(names, providerName, providerKey)); var multiplePermissionValueProviderGrantInfo = new MultiplePermissionValueProviderGrantInfo(names);
var permissionGrants = new List<PermissionGrant>();
} if (providerName == Name)
{
permissionGrants.AddRange(await PermissionGrantRepository.GetListAsync(names, providerName, providerKey));
if (providerName == UserPermissionValueProvider.ProviderName) }
{
var userId = Guid.Parse(providerKey);
var roleNames = await UserRoleFinder.GetRoleNamesAsync(userId);
foreach (var roleName in roleNames) if (providerName == UserPermissionValueProvider.ProviderName)
{ {
permissionGrants.AddRange(await PermissionGrantRepository.GetListAsync(names, Name, roleName)); var userId = Guid.Parse(providerKey);
var roleNames = await UserRoleFinder.GetRoleNamesAsync(userId);
foreach (var roleName in roleNames)
{
permissionGrants.AddRange(await PermissionGrantRepository.GetListAsync(names, Name, roleName));
}
} }
}
permissionGrants = permissionGrants.Distinct().ToList(); permissionGrants = permissionGrants.Distinct().ToList();
if (!permissionGrants.Any()) if (!permissionGrants.Any())
{ {
return multiplePermissionValueProviderGrantInfo; return multiplePermissionValueProviderGrantInfo;
} }
foreach (var permissionName in names) foreach (var permissionName in names)
{
var permissionGrant = permissionGrants.FirstOrDefault(x => x.Name == permissionName);
if (permissionGrant != null)
{ {
multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(true, permissionGrant.ProviderKey); var permissionGrant = permissionGrants.FirstOrDefault(x => x.Name == permissionName);
if (permissionGrant != null)
{
multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(true, permissionGrant.ProviderKey);
}
} }
}
return multiplePermissionValueProviderGrantInfo; return multiplePermissionValueProviderGrantInfo;
}
} }
} }

59
modules/permission-management/src/Volo.Abp.PermissionManagement.Application/Volo/Abp/PermissionManagement/PermissionAppService.cs

@ -43,25 +43,24 @@ public class PermissionAppService : ApplicationService, IPermissionAppService
}; };
var multiTenancySide = CurrentTenant.GetMultiTenancySide(); var multiTenancySide = CurrentTenant.GetMultiTenancySide();
var permissionGroups = new List<PermissionGroupDto>();
foreach (var group in await PermissionDefinitionManager.GetGroupsAsync()) foreach (var group in await PermissionDefinitionManager.GetGroupsAsync())
{ {
var groupDto = CreatePermissionGroupDto(group); var groupDto = CreatePermissionGroupDto(group);
var neededCheckPermissions = new List<PermissionDefinition>();
var permissions = group.GetPermissionsWithChildren() var permissions = group.GetPermissionsWithChildren()
.Where(x => x.IsEnabled) .Where(x => x.IsEnabled)
.Where(x => !x.Providers.Any() || x.Providers.Contains(providerName)) .Where(x => !x.Providers.Any() || x.Providers.Contains(providerName))
.Where(x => x.MultiTenancySide.HasFlag(multiTenancySide)); .Where(x => x.MultiTenancySide.HasFlag(multiTenancySide));
var neededCheckPermissions = new List<PermissionDefinition>();
foreach (var permission in permissions) foreach (var permission in permissions)
{ {
if(permission.Parent != null && !neededCheckPermissions.Contains(permission.Parent)) if (permission.Parent != null && !neededCheckPermissions.Contains(permission.Parent))
{ {
continue; continue;
} }
if (await SimpleStateCheckerManager.IsEnabledAsync(permission)) if (await SimpleStateCheckerManager.IsEnabledAsync(permission))
{ {
neededCheckPermissions.Add(permission); neededCheckPermissions.Add(permission);
@ -73,42 +72,46 @@ public class PermissionAppService : ApplicationService, IPermissionAppService
continue; continue;
} }
var grantInfoDtos = neededCheckPermissions groupDto.Permissions.AddRange(neededCheckPermissions.Select(CreatePermissionGrantInfoDto));
.Select(CreatePermissionGrantInfoDto) permissionGroups.Add(groupDto);
.ToList(); }
var multipleGrantInfo = await PermissionManager.GetAsync(neededCheckPermissions.Select(x => x.Name).ToArray(), providerName, providerKey); var multipleGrantInfo = await PermissionManager.GetAsync(
permissionGroups.SelectMany(group => group.Permissions).Select(permission => permission.Name).ToArray(),
providerName,
providerKey);
foreach (var grantInfo in multipleGrantInfo.Result) foreach (var permissionGroup in permissionGroups)
{
foreach (var permission in permissionGroup.Permissions)
{ {
var grantInfoDto = grantInfoDtos.First(x => x.Name == grantInfo.Name); var grantInfo = multipleGrantInfo.Result.FirstOrDefault(x => x.Name == permission.Name);
if (grantInfo == null)
grantInfoDto.IsGranted = grantInfo.IsGranted;
foreach (var provider in grantInfo.Providers)
{ {
grantInfoDto.GrantedProviders.Add(new ProviderInfoDto continue;
{
ProviderName = provider.Name,
ProviderKey = provider.Key,
});
} }
groupDto.Permissions.Add(grantInfoDto); permission.IsGranted = grantInfo.IsGranted;
permission.GrantedProviders = grantInfo.Providers.Select(x => new ProviderInfoDto
{
ProviderName = x.Name,
ProviderKey = x.Key,
}).ToList();
} }
if (groupDto.Permissions.Any()) if (permissionGroup.Permissions.Any())
{ {
result.Groups.Add(groupDto); result.Groups.Add(permissionGroup);
} }
} }
return result; return result;
} }
private PermissionGrantInfoDto CreatePermissionGrantInfoDto(PermissionDefinition permission) protected virtual PermissionGrantInfoDto CreatePermissionGrantInfoDto(PermissionDefinition permission)
{ {
return new PermissionGrantInfoDto { return new PermissionGrantInfoDto
{
Name = permission.Name, Name = permission.Name,
DisplayName = permission.DisplayName?.Localize(StringLocalizerFactory), DisplayName = permission.DisplayName?.Localize(StringLocalizerFactory),
ParentName = permission.Parent?.Name, ParentName = permission.Parent?.Name,
@ -117,10 +120,10 @@ public class PermissionAppService : ApplicationService, IPermissionAppService
}; };
} }
private PermissionGroupDto CreatePermissionGroupDto(PermissionGroupDefinition group) protected virtual PermissionGroupDto CreatePermissionGroupDto(PermissionGroupDefinition group)
{ {
var localizableDisplayName = group.DisplayName as LocalizableString; var localizableDisplayName = group.DisplayName as LocalizableString;
return new PermissionGroupDto return new PermissionGroupDto
{ {
Name = group.Name, Name = group.Name,

16
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionDataSeeder.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -33,14 +34,17 @@ public class PermissionDataSeeder : IPermissionDataSeeder, ITransientDependency
{ {
using (CurrentTenant.Change(tenantId)) using (CurrentTenant.Change(tenantId))
{ {
var names = grantedPermissions.ToArray(); using (PermissionGrantRepository.DisableTracking())
var existsPermissionGrants = (await PermissionGrantRepository.GetListAsync(names, providerName, providerKey)).Select(x => x.Name).ToList();
var permissions = names.Except(existsPermissionGrants).Select(permissionName => new PermissionGrant(GuidGenerator.Create(), permissionName, providerName, providerKey, tenantId)).ToList();
if (!permissions.Any())
{ {
return; var names = grantedPermissions.ToArray();
var existsPermissionGrants = (await PermissionGrantRepository.GetListAsync(names, providerName, providerKey)).Select(x => x.Name).ToList();
var permissions = names.Except(existsPermissionGrants).Select(permissionName => new PermissionGrant(GuidGenerator.Create(), permissionName, providerName, providerKey, tenantId)).ToList();
if (!permissions.Any())
{
return;
}
await PermissionGrantRepository.InsertManyAsync(permissions);
} }
await PermissionGrantRepository.InsertManyAsync(permissions);
} }
} }
} }

26
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManagementProvider.cs

@ -1,5 +1,6 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -34,21 +35,24 @@ public abstract class PermissionManagementProvider : IPermissionManagementProvid
public virtual async Task<MultiplePermissionValueProviderGrantInfo> CheckAsync(string[] names, string providerName, string providerKey) public virtual async Task<MultiplePermissionValueProviderGrantInfo> CheckAsync(string[] names, string providerName, string providerKey)
{ {
var multiplePermissionValueProviderGrantInfo = new MultiplePermissionValueProviderGrantInfo(names); using (PermissionGrantRepository.DisableTracking())
if (providerName != Name)
{ {
return multiplePermissionValueProviderGrantInfo; var multiplePermissionValueProviderGrantInfo = new MultiplePermissionValueProviderGrantInfo(names);
} if (providerName != Name)
{
return multiplePermissionValueProviderGrantInfo;
}
var permissionGrants = await PermissionGrantRepository.GetListAsync(names, providerName, providerKey); var permissionGrants = await PermissionGrantRepository.GetListAsync(names, providerName, providerKey);
foreach (var permissionName in names) foreach (var permissionName in names)
{ {
var isGrant = permissionGrants.Any(x => x.Name == permissionName); var isGrant = permissionGrants.Any(x => x.Name == permissionName);
multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(isGrant, providerKey); multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(isGrant, providerKey);
} }
return multiplePermissionValueProviderGrantInfo; return multiplePermissionValueProviderGrantInfo;
}
} }
public virtual Task SetAsync(string name, string providerKey, bool isGranted) public virtual Task SetAsync(string name, string providerKey, bool isGranted)

85
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionStore.cs

@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.PermissionManagement; namespace Volo.Abp.PermissionManagement;
@ -67,36 +68,39 @@ public class PermissionStore : IPermissionStore, ITransientDependency
string currentName, string currentName,
PermissionGrantCacheItem currentCacheItem) PermissionGrantCacheItem currentCacheItem)
{ {
var permissions = await PermissionDefinitionManager.GetPermissionsAsync(); using (PermissionGrantRepository.DisableTracking())
{
var permissions = await PermissionDefinitionManager.GetPermissionsAsync();
Logger.LogDebug($"Getting all granted permissions from the repository for this provider name,key: {providerName},{providerKey}"); Logger.LogDebug($"Getting all granted permissions from the repository for this provider name,key: {providerName},{providerKey}");
var grantedPermissionsHashSet = new HashSet<string>( var grantedPermissionsHashSet = new HashSet<string>(
(await PermissionGrantRepository.GetListAsync(providerName, providerKey)).Select(p => p.Name) (await PermissionGrantRepository.GetListAsync(providerName, providerKey)).Select(p => p.Name)
); );
Logger.LogDebug($"Setting the cache items. Count: {permissions.Count}"); Logger.LogDebug($"Setting the cache items. Count: {permissions.Count}");
var cacheItems = new List<KeyValuePair<string, PermissionGrantCacheItem>>(); var cacheItems = new List<KeyValuePair<string, PermissionGrantCacheItem>>();
foreach (var permission in permissions) foreach (var permission in permissions)
{ {
var isGranted = grantedPermissionsHashSet.Contains(permission.Name); var isGranted = grantedPermissionsHashSet.Contains(permission.Name);
cacheItems.Add(new KeyValuePair<string, PermissionGrantCacheItem>( cacheItems.Add(new KeyValuePair<string, PermissionGrantCacheItem>(
CalculateCacheKey(permission.Name, providerName, providerKey), CalculateCacheKey(permission.Name, providerName, providerKey),
new PermissionGrantCacheItem(isGranted)) new PermissionGrantCacheItem(isGranted))
); );
if (permission.Name == currentName) if (permission.Name == currentName)
{ {
currentCacheItem.IsGranted = isGranted; currentCacheItem.IsGranted = isGranted;
}
} }
}
await Cache.SetManyAsync(cacheItems); await Cache.SetManyAsync(cacheItems);
Logger.LogDebug($"Finished setting the cache items. Count: {permissions.Count}"); Logger.LogDebug($"Finished setting the cache items. Count: {permissions.Count}");
}
} }
public virtual async Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string providerName, string providerKey) public virtual async Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string providerName, string providerKey)
@ -169,34 +173,37 @@ public class PermissionStore : IPermissionStore, ITransientDependency
string providerKey, string providerKey,
List<string> notCacheKeys) List<string> notCacheKeys)
{ {
var permissions = (await PermissionDefinitionManager.GetPermissionsAsync()) using (PermissionGrantRepository.DisableTracking())
.Where(x => notCacheKeys.Any(k => GetPermissionNameFormCacheKeyOrNull(k) == x.Name)).ToList(); {
var permissions = (await PermissionDefinitionManager.GetPermissionsAsync())
.Where(x => notCacheKeys.Any(k => GetPermissionNameFormCacheKeyOrNull(k) == x.Name)).ToList();
Logger.LogDebug($"Getting not cache granted permissions from the repository for this provider name,key: {providerName},{providerKey}"); Logger.LogDebug($"Getting not cache granted permissions from the repository for this provider name,key: {providerName},{providerKey}");
var grantedPermissionsHashSet = new HashSet<string>( var grantedPermissionsHashSet = new HashSet<string>(
(await PermissionGrantRepository.GetListAsync(notCacheKeys.Select(GetPermissionNameFormCacheKeyOrNull).ToArray(), providerName, providerKey)).Select(p => p.Name) (await PermissionGrantRepository.GetListAsync(notCacheKeys.Select(GetPermissionNameFormCacheKeyOrNull).ToArray(), providerName, providerKey)).Select(p => p.Name)
); );
Logger.LogDebug($"Setting the cache items. Count: {permissions.Count}"); Logger.LogDebug($"Setting the cache items. Count: {permissions.Count}");
var cacheItems = new List<KeyValuePair<string, PermissionGrantCacheItem>>(); var cacheItems = new List<KeyValuePair<string, PermissionGrantCacheItem>>();
foreach (var permission in permissions) foreach (var permission in permissions)
{ {
var isGranted = grantedPermissionsHashSet.Contains(permission.Name); var isGranted = grantedPermissionsHashSet.Contains(permission.Name);
cacheItems.Add(new KeyValuePair<string, PermissionGrantCacheItem>( cacheItems.Add(new KeyValuePair<string, PermissionGrantCacheItem>(
CalculateCacheKey(permission.Name, providerName, providerKey), CalculateCacheKey(permission.Name, providerName, providerKey),
new PermissionGrantCacheItem(isGranted)) new PermissionGrantCacheItem(isGranted))
); );
} }
await Cache.SetManyAsync(cacheItems); await Cache.SetManyAsync(cacheItems);
Logger.LogDebug($"Finished setting the cache items. Count: {permissions.Count}"); Logger.LogDebug($"Finished setting the cache items. Count: {permissions.Count}");
return cacheItems; return cacheItems;
}
} }
protected virtual string CalculateCacheKey(string name, string providerName, string providerKey) protected virtual string CalculateCacheKey(string name, string providerName, string providerKey)

Loading…
Cancel
Save