Browse Source

Implement `ResourcePermissionManager`.

pull/24374/head
maliming 7 months ago
parent
commit
90bf895cac
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 5
      modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/AbpPermissionManagementDomainIdentityModule.cs
  2. 80
      modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleResourcePermissionManagementProvider.cs
  3. 22
      modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/UserResourcePermissionManagementProvider.cs
  4. 34
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManagementProvider.cs
  5. 30
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManager.cs
  6. 3
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManagementOptions.cs
  7. 87
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManagementProvider.cs
  8. 257
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs

5
modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/AbpPermissionManagementDomainIdentityModule.cs

@ -1,4 +1,5 @@
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
using Volo.Abp.Users;
@ -18,10 +19,14 @@ public class AbpPermissionManagementDomainIdentityModule : AbpModule
{
options.ManagementProviders.Add<UserPermissionManagementProvider>();
options.ManagementProviders.Add<RolePermissionManagementProvider>();
options.ResourceManagementProviders.Add<UserResourcePermissionManagementProvider>();
options.ResourceManagementProviders.Add<RoleResourcePermissionManagementProvider>();
//TODO: Can we prevent duplication of permission names without breaking the design and making the system complicated
options.ProviderPolicies[UserPermissionValueProvider.ProviderName] = "AbpIdentity.Users.ManagePermissions";
options.ProviderPolicies[RolePermissionValueProvider.ProviderName] = "AbpIdentity.Roles.ManagePermissions";
options.ProviderPolicies[UserResourcePermissionValueProvider.ProviderName] = "AbpIdentity.Users.ManagePermissions";
options.ProviderPolicies[RoleResourcePermissionValueProvider.ProviderName] = "AbpIdentity.Roles.ManagePermissions";
});
}
}

80
modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/RoleResourcePermissionManagementProvider.cs

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.PermissionManagement.Identity;
public class RoleResourcePermissionManagementProvider : ResourcePermissionManagementProvider
{
public override string Name => RoleResourcePermissionValueProvider.ProviderName;
protected IUserRoleFinder UserRoleFinder { get; }
public RoleResourcePermissionManagementProvider(
IResourcePermissionGrantRepository resourcepPrmissionGrantRepository,
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant,
IUserRoleFinder userRoleFinder)
: base(
resourcepPrmissionGrantRepository,
guidGenerator,
currentTenant)
{
UserRoleFinder = userRoleFinder;
}
public override async Task<PermissionValueProviderGrantInfo> CheckAsync(string name, string resourceName, string resourceKey, string providerName, string providerKey)
{
var multipleGrantInfo = await CheckAsync(new[] { name }, resourceName, resourceKey, providerName, providerKey);
return multipleGrantInfo.Result.Values.First();
}
public override async Task<MultiplePermissionValueProviderGrantInfo> CheckAsync(string[] names, string resourceName, string resourceKey, string providerName, string providerKey)
{
using (ResourcePermissionGrantRepository.DisableTracking())
{
var multiplePermissionValueProviderGrantInfo = new MultiplePermissionValueProviderGrantInfo(names);
var resourcePermissionGrants = new List<ResourcePermissionGrant>();
if (providerName == Name)
{
resourcePermissionGrants.AddRange(await ResourcePermissionGrantRepository.GetListAsync(names, resourceName, resourceKey, providerName, providerKey));
}
if (providerName == UserResourcePermissionValueProvider.ProviderName)
{
var userId = Guid.Parse(providerKey);
var roleNames = await UserRoleFinder.GetRoleNamesAsync(userId);
foreach (var roleName in roleNames)
{
resourcePermissionGrants.AddRange(await ResourcePermissionGrantRepository.GetListAsync(names, resourceName, resourceKey, Name, roleName));
}
}
resourcePermissionGrants = resourcePermissionGrants.Distinct().ToList();
if (!resourcePermissionGrants.Any())
{
return multiplePermissionValueProviderGrantInfo;
}
foreach (var permissionName in names)
{
var resourcePermissionGrant = resourcePermissionGrants.FirstOrDefault(x => x.Name == permissionName);
if (resourcePermissionGrant != null)
{
multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(true, resourcePermissionGrant.ProviderKey);
}
}
return multiplePermissionValueProviderGrantInfo;
}
}
}

22
modules/identity/src/Volo.Abp.PermissionManagement.Domain.Identity/Volo/Abp/PermissionManagement/Identity/UserResourcePermissionManagementProvider.cs

@ -0,0 +1,22 @@
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.PermissionManagement.Identity;
public class UserResourcePermissionManagementProvider : ResourcePermissionManagementProvider
{
public override string Name => UserResourcePermissionValueProvider.ProviderName;
public UserResourcePermissionManagementProvider(
IResourcePermissionGrantRepository resourcePermissionGrantRepository,
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant)
: base(
resourcePermissionGrantRepository,
guidGenerator,
currentTenant)
{
}
}

34
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManagementProvider.cs

@ -0,0 +1,34 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.PermissionManagement;
public interface IResourcePermissionManagementProvider : ISingletonDependency //TODO: Consider to remove this pre-assumption
{
string Name { get; }
Task<PermissionValueProviderGrantInfo> CheckAsync(
[NotNull] string name,
[NotNull] string resourceName,
[NotNull] string resourceKey,
[NotNull] string providerName,
[NotNull] string providerKey
);
Task<MultiplePermissionValueProviderGrantInfo> CheckAsync(
[NotNull] string[] names,
[NotNull] string resourceName,
[NotNull] string resourceKey,
[NotNull] string providerName,
[NotNull] string providerKey
);
Task SetAsync(
[NotNull] string name,
[NotNull] string resourceName,
[NotNull] string resourceKey,
[NotNull] string providerKey,
bool isGranted
);
}

30
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/IResourcePermissionManager.cs

@ -7,33 +7,33 @@ public interface IResourcePermissionManager
{
Task<PermissionWithGrantedProviders> GetAsync(
string permissionName,
string providerName,
string providerKey,
string resourceName,
string resourceKey
string resourceKey,
string providerName,
string providerKey
);
Task<MultiplePermissionWithGrantedProviders> GetAsync(
string[] permissionNames,
string provideName,
string providerKey,
string resourceName,
string resourceKey
string resourceKey,
string providerName,
string providerKey
);
Task<List<PermissionWithGrantedProviders>> GetAllAsync(
string providerName,
string providerKey,
string resourceName,
string resourceKey
string resourceKey,
string providerName,
string providerKey
);
Task SetAsync(
string permissionName,
string providerName,
string providerKey,
string resourceName,
string resourceKey,
string providerName,
string providerKey,
bool isGranted
);
}
}

3
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionManagementOptions.cs

@ -7,6 +7,8 @@ public class PermissionManagementOptions
{
public ITypeList<IPermissionManagementProvider> ManagementProviders { get; }
public ITypeList<IResourcePermissionManagementProvider> ResourceManagementProviders { get; }
public Dictionary<string, string> ProviderPolicies { get; }
/// <summary>
@ -22,6 +24,7 @@ public class PermissionManagementOptions
public PermissionManagementOptions()
{
ManagementProviders = new TypeList<IPermissionManagementProvider>();
ResourceManagementProviders = new TypeList<IResourcePermissionManagementProvider>();
ProviderPolicies = new Dictionary<string, string>();
}
}

87
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManagementProvider.cs

@ -0,0 +1,87 @@
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.PermissionManagement;
public abstract class ResourcePermissionManagementProvider : IResourcePermissionManagementProvider
{
public abstract string Name { get; }
protected IResourcePermissionGrantRepository ResourcePermissionGrantRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ResourcePermissionManagementProvider(
IResourcePermissionGrantRepository resourcePermissionGrantRepository,
IGuidGenerator guidGenerator,
ICurrentTenant currentTenant)
{
ResourcePermissionGrantRepository = resourcePermissionGrantRepository;
GuidGenerator = guidGenerator;
CurrentTenant = currentTenant;
}
public virtual async Task<PermissionValueProviderGrantInfo> CheckAsync(string name, string resourceName,string resourceKey, string providerName, string providerKey)
{
var multiplePermissionValueProviderGrantInfo = await CheckAsync(new[] { name }, resourceName, resourceKey, providerName, providerKey);
return multiplePermissionValueProviderGrantInfo.Result.First().Value;
}
public virtual async Task<MultiplePermissionValueProviderGrantInfo> CheckAsync(string[] names, string resourceName, string resourceKey, string providerName, string providerKey)
{
using (ResourcePermissionGrantRepository.DisableTracking())
{
var multiplePermissionValueProviderGrantInfo = new MultiplePermissionValueProviderGrantInfo(names);
if (providerName != Name)
{
return multiplePermissionValueProviderGrantInfo;
}
var resourcePermissionGrants = await ResourcePermissionGrantRepository.GetListAsync(names, resourceName, resourceKey, providerName, providerKey);
foreach (var permissionName in names)
{
var isGrant = resourcePermissionGrants.Any(x => x.Name == permissionName);
multiplePermissionValueProviderGrantInfo.Result[permissionName] = new PermissionValueProviderGrantInfo(isGrant, providerKey);
}
return multiplePermissionValueProviderGrantInfo;
}
}
public virtual Task SetAsync(string name, string resourceName,string resourceKey, string providerKey, bool isGranted)
{
return isGranted
? GrantAsync(name, resourceName, resourceKey, providerKey)
: RevokeAsync(name, resourceName, resourceKey, providerKey);
}
protected virtual async Task GrantAsync(string name, string resourceName, string resourceKey, string providerKey)
{
var resourcePermissionGrants = await ResourcePermissionGrantRepository.FindAsync(name, resourceName, resourceKey, Name, providerKey);
if (resourcePermissionGrants != null)
{
return;
}
resourcePermissionGrants = new ResourcePermissionGrant(GuidGenerator.Create(), name, resourceName, resourceKey, Name, providerKey, CurrentTenant.Id);
await ResourcePermissionGrantRepository.InsertAsync(resourcePermissionGrants, true);
}
protected virtual async Task RevokeAsync(string name, string resourceName,string resourceKey, string providerKey)
{
var resourcePermissionGrants = await ResourcePermissionGrantRepository.FindAsync(name, resourceName, resourceKey, Name, providerKey);
if (resourcePermissionGrants == null)
{
return;
}
await ResourcePermissionGrantRepository.DeleteAsync(resourcePermissionGrants, true);
}
}

257
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs

@ -0,0 +1,257 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.SimpleStateChecking;
namespace Volo.Abp.PermissionManagement;
public class ResourcePermissionManager : IResourcePermissionManager, ISingletonDependency
{
protected IResourcePermissionGrantRepository ResourcePermissionGrantRepository { get; }
protected IPermissionDefinitionManager PermissionDefinitionManager { get; }
protected ISimpleStateCheckerManager<PermissionDefinition> SimpleStateCheckerManager { get; }
protected IGuidGenerator GuidGenerator { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IReadOnlyList<IResourcePermissionManagementProvider> ManagementProviders => _lazyProviders.Value;
protected PermissionManagementOptions Options { get; }
protected IDistributedCache<ResourcePermissionGrantCacheItem> Cache { get; }
private readonly Lazy<List<IResourcePermissionManagementProvider>> _lazyProviders;
public ResourcePermissionManager(
IPermissionDefinitionManager permissionDefinitionManager,
ISimpleStateCheckerManager<PermissionDefinition> simpleStateCheckerManager,
IResourcePermissionGrantRepository resourcePermissionGrantRepository,
IServiceProvider serviceProvider,
IGuidGenerator guidGenerator,
IOptions<PermissionManagementOptions> options,
ICurrentTenant currentTenant,
IDistributedCache<ResourcePermissionGrantCacheItem> cache)
{
GuidGenerator = guidGenerator;
CurrentTenant = currentTenant;
Cache = cache;
SimpleStateCheckerManager = simpleStateCheckerManager;
ResourcePermissionGrantRepository = resourcePermissionGrantRepository;
PermissionDefinitionManager = permissionDefinitionManager;
Options = options.Value;
_lazyProviders = new Lazy<List<IResourcePermissionManagementProvider>>(
() => Options
.ResourceManagementProviders
.Select(c => serviceProvider.GetRequiredService(c) as IResourcePermissionManagementProvider)
.ToList(),
true
);
}
public virtual async Task<PermissionWithGrantedProviders> GetAsync(string permissionName, string resourceName, string resourceKey, string providerName, string providerKey)
{
var permission = await PermissionDefinitionManager.GetResourcePermissionOrNullAsync(permissionName);
if (permission == null)
{
return new PermissionWithGrantedProviders(permissionName, false);
}
return await GetInternalAsync(
permission,
resourceName,
resourceKey,
providerName,
providerKey
);
}
public virtual async Task<MultiplePermissionWithGrantedProviders> GetAsync(string[] permissionNames, string resourceName, string resourceKey, string providerName, string providerKey)
{
var permissions = new List<PermissionDefinition>();
var undefinedPermissions = new List<string>();
foreach (var permissionName in permissionNames)
{
var permission = await PermissionDefinitionManager.GetResourcePermissionOrNullAsync(permissionName);
if (permission != null)
{
permissions.Add(permission);
}
else
{
undefinedPermissions.Add(permissionName);
}
}
if (!permissions.Any())
{
return new MultiplePermissionWithGrantedProviders(undefinedPermissions.ToArray());
}
var result = await GetInternalAsync(
permissions.ToArray(),
resourceName,
resourceKey,
providerName,
providerKey
);
foreach (var undefinedPermission in undefinedPermissions)
{
result.Result.Add(new PermissionWithGrantedProviders(undefinedPermission, false));
}
return result;
}
public virtual async Task<List<PermissionWithGrantedProviders>> GetAllAsync(string resourceName, string resourceKey, string providerName, string providerKey)
{
var permissionDefinitions = (await PermissionDefinitionManager.GetResourcePermissionsAsync()).ToArray();
var multiplePermissionWithGrantedProviders = await GetInternalAsync(permissionDefinitions, resourceName, resourceKey, providerName, providerKey);
return multiplePermissionWithGrantedProviders.Result;
}
public virtual async Task SetAsync(string permissionName, string resourceName, string resourceKey, string providerName, string providerKey, bool isGranted)
{
var permission = await PermissionDefinitionManager.GetResourcePermissionOrNullAsync(permissionName);
if (permission == null)
{
/* Silently ignore undefined permissions,
maybe they were removed from dynamic permission definition store */
return;
}
if (!permission.IsEnabled || !await SimpleStateCheckerManager.IsEnabledAsync(permission))
{
//TODO: BusinessException
throw new ApplicationException($"The resource permission named '{permission.Name}' is disabled!");
}
if (permission.Providers.Any() && !permission.Providers.Contains(providerName))
{
//TODO: BusinessException
throw new ApplicationException($"The resource permission named '{permission.Name}' has not compatible with the provider named '{providerName}'");
}
if (!permission.MultiTenancySide.HasFlag(CurrentTenant.GetMultiTenancySide()))
{
//TODO: BusinessException
throw new ApplicationException($"The resource permission named '{permission.Name}' has multitenancy side '{permission.MultiTenancySide}' which is not compatible with the current multitenancy side '{CurrentTenant.GetMultiTenancySide()}'");
}
var currentGrantInfo = await GetInternalAsync(permission, resourceName, resourceKey, providerName, providerKey);
if (currentGrantInfo.IsGranted == isGranted)
{
return;
}
var provider = ManagementProviders.FirstOrDefault(m => m.Name == providerName);
if (provider == null)
{
//TODO: BusinessException
throw new AbpException("Unknown permission management provider: " + providerName);
}
await provider.SetAsync(permissionName, resourceName, resourceKey, providerKey, isGranted);
}
public virtual async Task<ResourcePermissionGrant> UpdateProviderKeyAsync(ResourcePermissionGrant resourcePermissionGrant, string resourceName, string resourceKey, string providerKey)
{
using (CurrentTenant.Change(resourcePermissionGrant.TenantId))
{
//Invalidating the cache for the old key
await Cache.RemoveAsync(
ResourcePermissionGrantCacheItem.CalculateCacheKey(
resourcePermissionGrant.Name,
resourcePermissionGrant.ResourceName,
resourcePermissionGrant.ResourceKey,
resourcePermissionGrant.ProviderName,
resourcePermissionGrant.ProviderKey
)
);
}
resourcePermissionGrant.ProviderKey = providerKey;
return await ResourcePermissionGrantRepository.UpdateAsync(resourcePermissionGrant, true);
}
public virtual async Task DeleteAsync(string providerName, string resourceName, string resourceKey, string providerKey)
{
var permissionGrants = await ResourcePermissionGrantRepository.GetListAsync(providerName, resourceName, resourceKey, providerKey);
foreach (var permissionGrant in permissionGrants)
{
await ResourcePermissionGrantRepository.DeleteAsync(permissionGrant, true);
}
}
protected virtual async Task<PermissionWithGrantedProviders> GetInternalAsync(PermissionDefinition permission, string resourceName, string resourceKey, string providerName, string providerKey)
{
var multiplePermissionWithGrantedProviders = await GetInternalAsync(
new[] { permission },
resourceName,
resourceKey,
providerName,
providerKey
);
return multiplePermissionWithGrantedProviders.Result.First();
}
protected virtual async Task<MultiplePermissionWithGrantedProviders> GetInternalAsync(PermissionDefinition[] permissions, string resourceName, string resourceKey, string providerName, string providerKey)
{
var permissionNames = permissions.Select(x => x.Name).ToArray();
var multiplePermissionWithGrantedProviders = new MultiplePermissionWithGrantedProviders(permissionNames);
var neededCheckPermissions = new List<PermissionDefinition>();
foreach (var permission in permissions
.Where(x => x.IsEnabled)
.Where(x => x.MultiTenancySide.HasFlag(CurrentTenant.GetMultiTenancySide()))
.Where(x => !x.Providers.Any() || x.Providers.Contains(providerName)))
{
if (await SimpleStateCheckerManager.IsEnabledAsync(permission))
{
neededCheckPermissions.Add(permission);
}
}
if (!neededCheckPermissions.Any())
{
return multiplePermissionWithGrantedProviders;
}
foreach (var provider in ManagementProviders)
{
permissionNames = neededCheckPermissions.Select(x => x.Name).ToArray();
var multiplePermissionValueProviderGrantInfo = await provider.CheckAsync(permissionNames, resourceName, resourceKey, providerName, providerKey);
foreach (var providerResultDict in multiplePermissionValueProviderGrantInfo.Result)
{
if (providerResultDict.Value.IsGranted)
{
var permissionWithGrantedProvider = multiplePermissionWithGrantedProviders.Result
.First(x => x.Name == providerResultDict.Key);
permissionWithGrantedProvider.IsGranted = true;
permissionWithGrantedProvider.Providers.Add(new PermissionValueProviderInfo(provider.Name, providerResultDict.Value.ProviderKey));
}
}
}
return multiplePermissionWithGrantedProviders;
}
}
Loading…
Cancel
Save