Browse Source

Add resource-based permission value providers

pull/24374/head
maliming 9 months ago
parent
commit
fccc3f20f6
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 6
      framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProvider.cs
  2. 4
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
  3. 43
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProviderManager.cs
  4. 79
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/RoleResourcePermissionValueProvider.cs
  5. 46
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/UserResourcePermissionValueProvider.cs

6
framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProvider.cs

@ -7,11 +7,11 @@ public abstract class ResourcePermissionValueProvider : IResourcePermissionValue
{
public abstract string Name { get; }
protected IResourcePermissionStore PermissionStore { get; }
protected IResourcePermissionStore ResourcePermissionStore { get; }
protected ResourcePermissionValueProvider(IResourcePermissionStore permissionStore)
protected ResourcePermissionValueProvider(IResourcePermissionStore resourcePermissionStore)
{
PermissionStore = permissionStore;
ResourcePermissionStore = resourcePermissionStore;
}
public abstract Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context);

4
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs

@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Authorization.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity;
@ -42,6 +43,9 @@ public class AbpAuthorizationModule : AbpModule
options.ValueProviders.Add<UserPermissionValueProvider>();
options.ValueProviders.Add<RolePermissionValueProvider>();
options.ValueProviders.Add<ClientPermissionValueProvider>();
options.ResourceValueProviders.Add<UserResourcePermissionValueProvider>();
options.ResourceValueProviders.Add<RoleResourcePermissionValueProvider>();
});
Configure<AbpVirtualFileSystemOptions>(options =>

43
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionValueProviderManager.cs

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionValueProviderManager : IResourcePermissionValueProviderManager, ISingletonDependency
{
public IReadOnlyList<IResourcePermissionValueProvider> ValueProviders => _lazyProviders.Value;
private readonly Lazy<List<IResourcePermissionValueProvider>> _lazyProviders;
protected AbpPermissionOptions Options { get; }
protected IServiceProvider ServiceProvider { get; }
public ResourcePermissionValueProviderManager(
IServiceProvider serviceProvider,
IOptions<AbpPermissionOptions> options)
{
Options = options.Value;
ServiceProvider = serviceProvider;
_lazyProviders = new Lazy<List<IResourcePermissionValueProvider>>(GetProviders, true);
}
protected virtual List<IResourcePermissionValueProvider> GetProviders()
{
var providers = Options
.ValueProviders
.Select(type => (ServiceProvider.GetRequiredService(type) as IResourcePermissionValueProvider)!)
.ToList();
var multipleProviders = providers.GroupBy(p => p.Name).FirstOrDefault(x => x.Count() > 1);
if(multipleProviders != null)
{
throw new AbpException($"Duplicate permission value provider name detected: {multipleProviders.Key}. Providers:{Environment.NewLine}{multipleProviders.Select(p => p.GetType().FullName!).JoinAsString(Environment.NewLine)}");
}
return providers;
}
}

79
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/RoleResourcePermissionValueProvider.cs

@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class RoleResourcePermissionValueProvider : ResourcePermissionValueProvider
{
public const string ProviderName = "R";
public override string Name => ProviderName;
public RoleResourcePermissionValueProvider(IResourcePermissionStore resourcePermissionStore)
: base(resourcePermissionStore)
{
}
public override async Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context)
{
var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray();
if (roles == null || !roles.Any())
{
return PermissionGrantResult.Undefined;
}
foreach (var role in roles.Distinct())
{
if (await ResourcePermissionStore.IsGrantedAsync(context.Permission.Name, Name, role))
{
return PermissionGrantResult.Granted;
}
}
return PermissionGrantResult.Undefined;
}
public override async Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context)
{
var permissionNames = context.Permissions.Select(x => x.Name).Distinct().ToList();
Check.NotNullOrEmpty(permissionNames, nameof(permissionNames));
var result = new MultiplePermissionGrantResult(permissionNames.ToArray());
var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray();
if (roles == null || !roles.Any())
{
return result;
}
foreach (var role in roles.Distinct())
{
var multipleResult = await ResourcePermissionStore.IsGrantedAsync(permissionNames.ToArray(), Name, role);
foreach (var grantResult in multipleResult.Result.Where(grantResult =>
result.Result.ContainsKey(grantResult.Key) &&
result.Result[grantResult.Key] == PermissionGrantResult.Undefined &&
grantResult.Value != PermissionGrantResult.Undefined))
{
result.Result[grantResult.Key] = grantResult.Value;
permissionNames.RemoveAll(x => x == grantResult.Key);
}
if (result.AllGranted || result.AllProhibited)
{
break;
}
if (permissionNames.IsNullOrEmpty())
{
break;
}
}
return result;
}
}

46
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/UserResourcePermissionValueProvider.cs

@ -0,0 +1,46 @@
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Authorization.Permissions.Resources;
public class UserResourcePermissionValueProvider : ResourcePermissionValueProvider
{
public const string ProviderName = "U";
public override string Name => ProviderName;
public UserResourcePermissionValueProvider(IResourcePermissionStore resourcePermissionStore)
: base(resourcePermissionStore)
{
}
public override async Task<PermissionGrantResult> CheckAsync(ResourcePermissionValueCheckContext context)
{
var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;
if (userId == null)
{
return PermissionGrantResult.Undefined;
}
return await ResourcePermissionStore.IsGrantedAsync(context.Permission.Name, Name, userId)
? PermissionGrantResult.Granted
: PermissionGrantResult.Undefined;
}
public override async Task<MultiplePermissionGrantResult> CheckAsync(ResourcePermissionValuesCheckContext context)
{
var permissionNames = context.Permissions.Select(x => x.Name).Distinct().ToArray();
Check.NotNullOrEmpty(permissionNames, nameof(permissionNames));
var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;
if (userId == null)
{
return new MultiplePermissionGrantResult(permissionNames);
}
return await ResourcePermissionStore.IsGrantedAsync(permissionNames, Name, userId);
}
}
Loading…
Cancel
Save