Browse Source

Enforce management permission checks for resource permissions

pull/24374/head
maliming 6 months ago
parent
commit
ea32e2c96d
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 15
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionChecker.cs
  2. 27
      framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs
  3. 6
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionChecker_Tests.cs
  4. 58
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionPopulator_Test.cs
  5. 2
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/AuthorizationTestResourcePermissionDefinitionProvider.cs
  6. 2
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/FakeResourcePermissionStore.cs
  7. 18
      framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestEntityResource.cs
  8. 5
      modules/permission-management/src/Volo.Abp.PermissionManagement.Application/Volo/Abp/PermissionManagement/PermissionAppService.cs

15
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionChecker.cs

@ -17,19 +17,22 @@ public class ResourcePermissionChecker : IResourcePermissionChecker, ITransientD
protected ICurrentTenant CurrentTenant { get; } protected ICurrentTenant CurrentTenant { get; }
protected IResourcePermissionValueProviderManager PermissionValueProviderManager { get; } protected IResourcePermissionValueProviderManager PermissionValueProviderManager { get; }
protected ISimpleStateCheckerManager<PermissionDefinition> StateCheckerManager { get; } protected ISimpleStateCheckerManager<PermissionDefinition> StateCheckerManager { get; }
protected IPermissionChecker PermissionChecker { get; }
public ResourcePermissionChecker( public ResourcePermissionChecker(
ICurrentPrincipalAccessor principalAccessor, ICurrentPrincipalAccessor principalAccessor,
IPermissionDefinitionManager permissionDefinitionManager, IPermissionDefinitionManager permissionDefinitionManager,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IResourcePermissionValueProviderManager permissionValueProviderManager, IResourcePermissionValueProviderManager permissionValueProviderManager,
ISimpleStateCheckerManager<PermissionDefinition> stateCheckerManager) ISimpleStateCheckerManager<PermissionDefinition> stateCheckerManager,
IPermissionChecker permissionChecker)
{ {
PrincipalAccessor = principalAccessor; PrincipalAccessor = principalAccessor;
PermissionDefinitionManager = permissionDefinitionManager; PermissionDefinitionManager = permissionDefinitionManager;
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
PermissionValueProviderManager = permissionValueProviderManager; PermissionValueProviderManager = permissionValueProviderManager;
StateCheckerManager = stateCheckerManager; StateCheckerManager = stateCheckerManager;
PermissionChecker = permissionChecker;
} }
public virtual async Task<bool> IsGrantedAsync(string name, string resourceName, string resourceKey) public virtual async Task<bool> IsGrantedAsync(string name, string resourceName, string resourceKey)
@ -69,6 +72,11 @@ public class ResourcePermissionChecker : IResourcePermissionChecker, ITransientD
return false; return false;
} }
if (!await PermissionChecker.IsGrantedAsync(claimsPrincipal, permission.ManagementPermissionName!))
{
return false;
}
var isGranted = false; var isGranted = false;
var context = new ResourcePermissionValueCheckContext(permission, claimsPrincipal, resourceName, resourceKey); var context = new ResourcePermissionValueCheckContext(permission, claimsPrincipal, resourceName, resourceKey);
foreach (var provider in PermissionValueProviderManager.ValueProviders) foreach (var provider in PermissionValueProviderManager.ValueProviders)
@ -96,7 +104,7 @@ public class ResourcePermissionChecker : IResourcePermissionChecker, ITransientD
public async Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string resourceName, string resourceKey) public async Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names, string resourceName, string resourceKey)
{ {
return await IsGrantedAsync(PrincipalAccessor.Principal, names, resourceName,resourceKey); return await IsGrantedAsync(PrincipalAccessor.Principal, names, resourceName, resourceKey);
} }
public async Task<MultiplePermissionGrantResult> IsGrantedAsync(ClaimsPrincipal? claimsPrincipal, string[] names, string resourceName, string resourceKey) public async Task<MultiplePermissionGrantResult> IsGrantedAsync(ClaimsPrincipal? claimsPrincipal, string[] names, string resourceName, string resourceKey)
@ -116,7 +124,8 @@ public class ResourcePermissionChecker : IResourcePermissionChecker, ITransientD
foreach (var name in names) foreach (var name in names)
{ {
var permission = await PermissionDefinitionManager.GetResourcePermissionOrNullAsync(resourceName, name); var permission = await PermissionDefinitionManager.GetResourcePermissionOrNullAsync(resourceName, name);
if (permission == null) if (permission == null ||
!await PermissionChecker.IsGrantedAsync(claimsPrincipal, permission.ManagementPermissionName!))
{ {
result.Result.Add(name, PermissionGrantResult.Prohibited); result.Result.Add(name, PermissionGrantResult.Prohibited);
continue; continue;

27
framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs

@ -9,19 +9,20 @@ namespace Volo.Abp.Authorization.Permissions.Resources;
public class ResourcePermissionPopulator : ITransientDependency public class ResourcePermissionPopulator : ITransientDependency
{ {
protected IPermissionDefinitionManager PermissionDefinitionManager { get; } protected IPermissionDefinitionManager PermissionDefinitionManager { get; }
protected IResourcePermissionChecker ResourcePermissionChecker { get; } protected IResourcePermissionChecker ResourcePermissionChecker { get; }
protected IResourcePermissionStore ResourcePermissionStore { get; } protected IResourcePermissionStore ResourcePermissionStore { get; }
protected IPermissionChecker PermissionChecker { get; }
public ResourcePermissionPopulator( public ResourcePermissionPopulator(
IPermissionDefinitionManager permissionDefinitionManager, IPermissionDefinitionManager permissionDefinitionManager,
IResourcePermissionChecker resourcePermissionChecker, IResourcePermissionChecker resourcePermissionChecker,
IResourcePermissionStore resourcePermissionStore) IResourcePermissionStore resourcePermissionStore,
IPermissionChecker permissionChecker)
{ {
PermissionDefinitionManager = permissionDefinitionManager; PermissionDefinitionManager = permissionDefinitionManager;
ResourcePermissionChecker = resourcePermissionChecker; ResourcePermissionChecker = resourcePermissionChecker;
ResourcePermissionStore = resourcePermissionStore; ResourcePermissionStore = resourcePermissionStore;
PermissionChecker = permissionChecker;
} }
public virtual async Task PopulateAsync<TResource>(TResource resource, string resourceName) public virtual async Task PopulateAsync<TResource>(TResource resource, string resourceName)
@ -36,9 +37,8 @@ public class ResourcePermissionPopulator : ITransientDependency
Check.NotNull(resources, nameof(resources)); Check.NotNull(resources, nameof(resources));
Check.NotNullOrWhiteSpace(resourceName, nameof(resourceName)); Check.NotNullOrWhiteSpace(resourceName, nameof(resourceName));
var resopurcePermissionNames = (await PermissionDefinitionManager.GetResourcePermissionsAsync()) var resopurcePermissions = (await PermissionDefinitionManager.GetResourcePermissionsAsync())
.Where(x => x.ResourceName == resourceName) .Where(x => x.ResourceName == resourceName)
.Select(x => x.Name)
.ToArray(); .ToArray();
foreach (var resource in resources) foreach (var resource in resources)
@ -48,17 +48,22 @@ public class ResourcePermissionPopulator : ITransientDependency
{ {
throw new AbpException("Resource key can not be null or empty."); throw new AbpException("Resource key can not be null or empty.");
} }
var results = await ResourcePermissionChecker.IsGrantedAsync(resopurcePermissionNames, resourceName, resourceKey); var results = await ResourcePermissionChecker.IsGrantedAsync(resopurcePermissions.Select(x => x.Name).ToArray(), resourceName, resourceKey);
foreach (var resopurcePermission in resopurcePermissionNames) foreach (var resopurcePermission in resopurcePermissions)
{ {
if (!await PermissionChecker.IsGrantedAsync(resopurcePermission.ManagementPermissionName!))
{
continue;
}
if (resource.ResourcePermissions == null) if (resource.ResourcePermissions == null)
{ {
ObjectHelper.TrySetProperty(resource, x => x.ResourcePermissions, () => new Dictionary<string, bool>()); ObjectHelper.TrySetProperty(resource, x => x.ResourcePermissions, () => new Dictionary<string, bool>());
} }
var hasPermission = results.Result.TryGetValue(resopurcePermission, out var granted) && granted == PermissionGrantResult.Granted; var hasPermission = results.Result.TryGetValue(resopurcePermission.Name, out var granted) && granted == PermissionGrantResult.Granted;
resource.ResourcePermissions![resopurcePermission] = hasPermission; resource.ResourcePermissions![resopurcePermission.Name] = hasPermission;
} }
} }
} }

6
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionChecker_Tests.cs

@ -21,6 +21,7 @@ public class ResourcePermissionChecker_Tests: AuthorizationTestBase
{ {
(await _resourcePermissionChecker.IsGrantedAsync("MyResourcePermission5", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(true); (await _resourcePermissionChecker.IsGrantedAsync("MyResourcePermission5", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(true);
(await _resourcePermissionChecker.IsGrantedAsync("UndefinedResourcePermission", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(false); (await _resourcePermissionChecker.IsGrantedAsync("UndefinedResourcePermission", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(false);
(await _resourcePermissionChecker.IsGrantedAsync("MyResourcePermission8", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(false);
} }
[Fact] [Fact]
@ -33,7 +34,8 @@ public class ResourcePermissionChecker_Tests: AuthorizationTestBase
"UndefinedPermission", "UndefinedPermission",
"MyResourcePermission3", "MyResourcePermission3",
"MyResourcePermission4", "MyResourcePermission4",
"MyResourcePermission5" "MyResourcePermission5",
"MyResourcePermission8"
}, TestEntityResource.ResourceName, TestEntityResource.ResourceKey5); }, TestEntityResource.ResourceName, TestEntityResource.ResourceKey5);
result.Result["MyResourcePermission1"].ShouldBe(PermissionGrantResult.Undefined); result.Result["MyResourcePermission1"].ShouldBe(PermissionGrantResult.Undefined);
@ -42,11 +44,13 @@ public class ResourcePermissionChecker_Tests: AuthorizationTestBase
result.Result["MyResourcePermission3"].ShouldBe(PermissionGrantResult.Granted); result.Result["MyResourcePermission3"].ShouldBe(PermissionGrantResult.Granted);
result.Result["MyResourcePermission4"].ShouldBe(PermissionGrantResult.Prohibited); result.Result["MyResourcePermission4"].ShouldBe(PermissionGrantResult.Prohibited);
result.Result["MyResourcePermission5"].ShouldBe(PermissionGrantResult.Granted); result.Result["MyResourcePermission5"].ShouldBe(PermissionGrantResult.Granted);
result.Result["MyResourcePermission8"].ShouldBe(PermissionGrantResult.Prohibited);
result = await _resourcePermissionChecker.IsGrantedAsync(new [] result = await _resourcePermissionChecker.IsGrantedAsync(new []
{ {
"MyResourcePermission6", "MyResourcePermission6",
}, TestEntityResource.ResourceName, TestEntityResource.ResourceKey6); }, TestEntityResource.ResourceName, TestEntityResource.ResourceKey6);
result.Result["MyResourcePermission6"].ShouldBe(PermissionGrantResult.Granted); result.Result["MyResourcePermission6"].ShouldBe(PermissionGrantResult.Granted);
result = await _resourcePermissionChecker.IsGrantedAsync(new [] result = await _resourcePermissionChecker.IsGrantedAsync(new []

58
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/ResourcePermissionPopulator_Test.cs

@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Authorization.Permissions.Resources;
using Volo.Abp.Authorization.TestServices.Resources;
using Xunit;
namespace Volo.Abp.Authorization;
public class ResourcePermissionPopulator_Tests : AuthorizationTestBase
{
private readonly ResourcePermissionPopulator _resourcePermissionPopulator;
public ResourcePermissionPopulator_Tests()
{
_resourcePermissionPopulator = GetRequiredService<ResourcePermissionPopulator>();
}
[Fact]
public async Task PopulateAsync()
{
var testResourceObject = new TestEntityResource(TestEntityResource.ResourceKey5);
testResourceObject.ResourcePermissions.IsNullOrEmpty().ShouldBeTrue();
await _resourcePermissionPopulator.PopulateAsync<TestEntityResource>(
testResourceObject,
TestEntityResource.ResourceName
);
testResourceObject.ResourcePermissions.ShouldNotBeNull();
testResourceObject.ResourcePermissions.Count.ShouldBe(7); // Does not include MyResourcePermission8 because current user has no TestEntityManagementPermission2
testResourceObject.ResourcePermissions["MyResourcePermission1"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission2"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission3"].ShouldBe(true);
testResourceObject.ResourcePermissions["MyResourcePermission4"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission5"].ShouldBe(true);
testResourceObject.ResourcePermissions["MyResourcePermission6"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission7"].ShouldBe(false);
testResourceObject = new TestEntityResource(TestEntityResource.ResourceKey6);
testResourceObject.ResourcePermissions.IsNullOrEmpty().ShouldBeTrue();
await _resourcePermissionPopulator.PopulateAsync<TestEntityResource>(
testResourceObject,
TestEntityResource.ResourceName
);
testResourceObject.ResourcePermissions.ShouldNotBeNull();
testResourceObject.ResourcePermissions.Count.ShouldBe(7); // Does not include MyResourcePermission8 because current user has no TestEntityManagementPermission2
testResourceObject.ResourcePermissions["MyResourcePermission1"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission2"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission3"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission4"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission5"].ShouldBe(false);
testResourceObject.ResourcePermissions["MyResourcePermission6"].ShouldBe(true);
testResourceObject.ResourcePermissions["MyResourcePermission7"].ShouldBe(false);
}
}

2
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/AuthorizationTestResourcePermissionDefinitionProvider.cs

@ -14,6 +14,7 @@ public class AuthorizationTestResourcePermissionDefinitionProvider : PermissionD
getGroup = context.AddGroup("TestGroup"); getGroup = context.AddGroup("TestGroup");
} }
getGroup.AddPermission("TestEntityManagementPermission"); getGroup.AddPermission("TestEntityManagementPermission");
getGroup.AddPermission("TestEntityManagementPermission2");
var permission1 = context.AddResourcePermission("MyResourcePermission1", resourceName: TestEntityResource.ResourceName, "TestEntityManagementPermission"); var permission1 = context.AddResourcePermission("MyResourcePermission1", resourceName: TestEntityResource.ResourceName, "TestEntityManagementPermission");
Assert.Throws<AbpException>(() => Assert.Throws<AbpException>(() =>
@ -29,6 +30,7 @@ public class AuthorizationTestResourcePermissionDefinitionProvider : PermissionD
context.AddResourcePermission("MyResourcePermission5", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission"); context.AddResourcePermission("MyResourcePermission5", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission");
context.AddResourcePermission("MyResourcePermission6", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider1)); context.AddResourcePermission("MyResourcePermission6", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider1));
context.AddResourcePermission("MyResourcePermission7", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider2)); context.AddResourcePermission("MyResourcePermission7", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider2));
context.AddResourcePermission("MyResourcePermission8", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission2");
Assert.Throws<AbpException>(() => Assert.Throws<AbpException>(() =>
{ {

2
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/FakeResourcePermissionStore.cs

@ -19,7 +19,7 @@ public class FakeResourcePermissionStore : IResourcePermissionStore, ITransientD
var result = new MultiplePermissionGrantResult(); var result = new MultiplePermissionGrantResult();
foreach (var name in names) foreach (var name in names)
{ {
result.Result.Add(name, (name == "MyResourcePermission3" || name == "MyResourcePermission5" && result.Result.Add(name, ((name == "MyResourcePermission3" || name == "MyResourcePermission5") &&
resourceName == TestEntityResource.ResourceName && resourceName == TestEntityResource.ResourceName &&
(resourceKey == TestEntityResource.ResourceKey3 || resourceKey == TestEntityResource.ResourceKey5) (resourceKey == TestEntityResource.ResourceKey3 || resourceKey == TestEntityResource.ResourceKey5)
? PermissionGrantResult.Granted ? PermissionGrantResult.Granted

18
framework/test/Volo.Abp.Authorization.Tests/Volo/Abp/Authorization/TestServices/Resources/TestEntityResource.cs

@ -1,8 +1,10 @@
using System; using System;
using System.Collections.Generic;
using Volo.Abp.Authorization.Permissions.Resources;
namespace Volo.Abp.Authorization.TestServices.Resources; namespace Volo.Abp.Authorization.TestServices.Resources;
public class TestEntityResource public class TestEntityResource : IHasResourcePermissions
{ {
public static readonly string ResourceName = typeof(TestEntityResource).FullName; public static readonly string ResourceName = typeof(TestEntityResource).FullName;
@ -13,6 +15,20 @@ public class TestEntityResource
public static readonly string ResourceKey5 = Guid.NewGuid().ToString(); public static readonly string ResourceKey5 = Guid.NewGuid().ToString();
public static readonly string ResourceKey6 = Guid.NewGuid().ToString(); public static readonly string ResourceKey6 = Guid.NewGuid().ToString();
public static readonly string ResourceKey7 = Guid.NewGuid().ToString(); public static readonly string ResourceKey7 = Guid.NewGuid().ToString();
private string Id { get; }
public TestEntityResource(string id)
{
Id = id;
}
public string GetObjectKey()
{
return Id;
}
public Dictionary<string, bool> ResourcePermissions { get; set; }
} }
public class TestEntityResource2 public class TestEntityResource2

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

@ -267,7 +267,10 @@ public class PermissionAppService : ApplicationService, IPermissionAppService
} }
} }
result.Permissions.Add(resourcePermissionGrantInfoDto); if(resourcePermissionGrantInfoDto.Permissions.Any())
{
result.Permissions.Add(resourcePermissionGrantInfoDto);
}
} }
return result; return result;

Loading…
Cancel
Save