Browse Source

Enforce management permission checks for resource permissions

pull/24374/head
maliming 2 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 IResourcePermissionValueProviderManager PermissionValueProviderManager { get; }
protected ISimpleStateCheckerManager<PermissionDefinition> StateCheckerManager { get; }
protected IPermissionChecker PermissionChecker { get; }
public ResourcePermissionChecker(
ICurrentPrincipalAccessor principalAccessor,
IPermissionDefinitionManager permissionDefinitionManager,
ICurrentTenant currentTenant,
IResourcePermissionValueProviderManager permissionValueProviderManager,
ISimpleStateCheckerManager<PermissionDefinition> stateCheckerManager)
ISimpleStateCheckerManager<PermissionDefinition> stateCheckerManager,
IPermissionChecker permissionChecker)
{
PrincipalAccessor = principalAccessor;
PermissionDefinitionManager = permissionDefinitionManager;
CurrentTenant = currentTenant;
PermissionValueProviderManager = permissionValueProviderManager;
StateCheckerManager = stateCheckerManager;
PermissionChecker = permissionChecker;
}
public virtual async Task<bool> IsGrantedAsync(string name, string resourceName, string resourceKey)
@ -69,6 +72,11 @@ public class ResourcePermissionChecker : IResourcePermissionChecker, ITransientD
return false;
}
if (!await PermissionChecker.IsGrantedAsync(claimsPrincipal, permission.ManagementPermissionName!))
{
return false;
}
var isGranted = false;
var context = new ResourcePermissionValueCheckContext(permission, claimsPrincipal, resourceName, resourceKey);
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)
{
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)
@ -116,7 +124,8 @@ public class ResourcePermissionChecker : IResourcePermissionChecker, ITransientD
foreach (var name in names)
{
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);
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
{
protected IPermissionDefinitionManager PermissionDefinitionManager { get; }
protected IResourcePermissionChecker ResourcePermissionChecker { get; }
protected IResourcePermissionStore ResourcePermissionStore { get; }
protected IPermissionChecker PermissionChecker { get; }
public ResourcePermissionPopulator(
IPermissionDefinitionManager permissionDefinitionManager,
IResourcePermissionChecker resourcePermissionChecker,
IResourcePermissionStore resourcePermissionStore)
IResourcePermissionStore resourcePermissionStore,
IPermissionChecker permissionChecker)
{
PermissionDefinitionManager = permissionDefinitionManager;
ResourcePermissionChecker = resourcePermissionChecker;
ResourcePermissionStore = resourcePermissionStore;
PermissionChecker = permissionChecker;
}
public virtual async Task PopulateAsync<TResource>(TResource resource, string resourceName)
@ -36,9 +37,8 @@ public class ResourcePermissionPopulator : ITransientDependency
Check.NotNull(resources, nameof(resources));
Check.NotNullOrWhiteSpace(resourceName, nameof(resourceName));
var resopurcePermissionNames = (await PermissionDefinitionManager.GetResourcePermissionsAsync())
var resopurcePermissions = (await PermissionDefinitionManager.GetResourcePermissionsAsync())
.Where(x => x.ResourceName == resourceName)
.Select(x => x.Name)
.ToArray();
foreach (var resource in resources)
@ -48,17 +48,22 @@ public class ResourcePermissionPopulator : ITransientDependency
{
throw new AbpException("Resource key can not be null or empty.");
}
var results = await ResourcePermissionChecker.IsGrantedAsync(resopurcePermissionNames, resourceName, resourceKey);
foreach (var resopurcePermission in resopurcePermissionNames)
var results = await ResourcePermissionChecker.IsGrantedAsync(resopurcePermissions.Select(x => x.Name).ToArray(), resourceName, resourceKey);
foreach (var resopurcePermission in resopurcePermissions)
{
if (!await PermissionChecker.IsGrantedAsync(resopurcePermission.ManagementPermissionName!))
{
continue;
}
if (resource.ResourcePermissions == null)
{
ObjectHelper.TrySetProperty(resource, x => x.ResourcePermissions, () => new Dictionary<string, bool>());
}
var hasPermission = results.Result.TryGetValue(resopurcePermission, out var granted) && granted == PermissionGrantResult.Granted;
resource.ResourcePermissions![resopurcePermission] = hasPermission;
var hasPermission = results.Result.TryGetValue(resopurcePermission.Name, out var granted) && granted == PermissionGrantResult.Granted;
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("UndefinedResourcePermission", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(false);
(await _resourcePermissionChecker.IsGrantedAsync("MyResourcePermission8", TestEntityResource.ResourceName, TestEntityResource.ResourceKey5)).ShouldBe(false);
}
[Fact]
@ -33,7 +34,8 @@ public class ResourcePermissionChecker_Tests: AuthorizationTestBase
"UndefinedPermission",
"MyResourcePermission3",
"MyResourcePermission4",
"MyResourcePermission5"
"MyResourcePermission5",
"MyResourcePermission8"
}, TestEntityResource.ResourceName, TestEntityResource.ResourceKey5);
result.Result["MyResourcePermission1"].ShouldBe(PermissionGrantResult.Undefined);
@ -42,11 +44,13 @@ public class ResourcePermissionChecker_Tests: AuthorizationTestBase
result.Result["MyResourcePermission3"].ShouldBe(PermissionGrantResult.Granted);
result.Result["MyResourcePermission4"].ShouldBe(PermissionGrantResult.Prohibited);
result.Result["MyResourcePermission5"].ShouldBe(PermissionGrantResult.Granted);
result.Result["MyResourcePermission8"].ShouldBe(PermissionGrantResult.Prohibited);
result = await _resourcePermissionChecker.IsGrantedAsync(new []
{
"MyResourcePermission6",
}, TestEntityResource.ResourceName, TestEntityResource.ResourceKey6);
result.Result["MyResourcePermission6"].ShouldBe(PermissionGrantResult.Granted);
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.AddPermission("TestEntityManagementPermission");
getGroup.AddPermission("TestEntityManagementPermission2");
var permission1 = context.AddResourcePermission("MyResourcePermission1", resourceName: TestEntityResource.ResourceName, "TestEntityManagementPermission");
Assert.Throws<AbpException>(() =>
@ -29,6 +30,7 @@ public class AuthorizationTestResourcePermissionDefinitionProvider : PermissionD
context.AddResourcePermission("MyResourcePermission5", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission");
context.AddResourcePermission("MyResourcePermission6", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider1));
context.AddResourcePermission("MyResourcePermission7", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission").WithProviders(nameof(TestResourcePermissionValueProvider2));
context.AddResourcePermission("MyResourcePermission8", resourceName: typeof(TestEntityResource).FullName!, "TestEntityManagementPermission2");
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();
foreach (var name in names)
{
result.Result.Add(name, (name == "MyResourcePermission3" || name == "MyResourcePermission5" &&
result.Result.Add(name, ((name == "MyResourcePermission3" || name == "MyResourcePermission5") &&
resourceName == TestEntityResource.ResourceName &&
(resourceKey == TestEntityResource.ResourceKey3 || resourceKey == TestEntityResource.ResourceKey5)
? PermissionGrantResult.Granted

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

@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Authorization.Permissions.Resources;
namespace Volo.Abp.Authorization.TestServices.Resources;
public class TestEntityResource
public class TestEntityResource : IHasResourcePermissions
{
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 ResourceKey6 = 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

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;

Loading…
Cancel
Save