From 7cbc6c370308ba2fb5d065818047fe68eefb20dd Mon Sep 17 00:00:00 2001 From: maliming Date: Wed, 19 Nov 2025 18:23:28 +0800 Subject: [PATCH] Implement resource permissions management with new interfaces and extension methods --- .../Resources/IHasResourcePermissions.cs | 8 ++++ .../ResourcePermissionCheckerExtensions.cs | 27 +------------ .../ResourcePermissionStoreExtensions.cs | 24 +++++++++++- .../Resources/ResourcePermissionPopulator.cs | 39 +++++++++++++++++++ .../Permissions/Resources/EntityExtensions.cs | 19 +++++++++ ...tityResourcePermissionCheckerExtensions.cs | 34 ++-------------- ...ityResourcePermissionRequirementHandler.cs | 5 +-- ...EntityResourcePermissionStoreExtensions.cs | 36 +++++++---------- .../ResourcePermissionManager.cs | 14 +------ 9 files changed, 109 insertions(+), 97 deletions(-) create mode 100644 framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IHasResourcePermissions.cs create mode 100644 framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs create mode 100644 framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityExtensions.cs diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IHasResourcePermissions.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IHasResourcePermissions.cs new file mode 100644 index 0000000000..971b326d77 --- /dev/null +++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/IHasResourcePermissions.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Volo.Abp.Authorization.Permissions.Resources; + +public interface IHasResourcePermissions +{ + public Dictionary ResourcePermissions { get; } +} diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionCheckerExtensions.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionCheckerExtensions.cs index 3a5fad9d7d..c1d153b246 100644 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionCheckerExtensions.cs +++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionCheckerExtensions.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Volo.Abp.Authorization.Permissions.Resources; @@ -32,28 +31,4 @@ public static class ResourcePermissionCheckerExtensions resourceKey.ToString()! ); } - - /// - /// Retrieves a dictionary of permissions and their granted statuses for a specific resource. - /// - /// The type of the resource. - /// The resource permission checker instance. - /// The resource instance for which permissions are being checked. - /// The unique key identifying the resource instance. - /// A task that represents the asynchronous operation. The task result contains a dictionary where keys are permission names and values indicate whether the corresponding permission is granted. - public static Task> GetPermissionsAsync( - this IResourcePermissionChecker resourcePermissionChecker, - TResource resource, - object resourceKey - ) - { - Check.NotNull(resourcePermissionChecker, nameof(resourcePermissionChecker)); - Check.NotNull(resource, nameof(resource)); - Check.NotNull(resourceKey, nameof(resourceKey)); - - return resourcePermissionChecker.GetPermissionsAsync( - typeof(TResource).FullName!, - resourceKey.ToString()! - ); - } } diff --git a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionStoreExtensions.cs b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionStoreExtensions.cs index 6ed817c232..f5604a7683 100644 --- a/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionStoreExtensions.cs +++ b/framework/src/Volo.Abp.Authorization.Abstractions/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionStoreExtensions.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace Volo.Abp.Authorization.Permissions.Resources; @@ -13,7 +14,24 @@ public static class ResourcePermissionStoreExtensions /// The resource instance to retrieve permissions for. /// The unique key identifying the resource instance. /// A task that represents the asynchronous operation. The task result contains an array of strings representing the granted permissions. - public static Task GetGrantedPermissionsAsync( + public static async Task GetGrantedPermissionsAsync( + this IResourcePermissionStore resourcePermissionStore, + TResource resource, + object resourceKey + ) + { + return (await GetPermissionsAsync(resourcePermissionStore, resource, resourceKey)).Where(x => x.Value).Select(x => x.Key).ToArray(); + } + + /// + /// Retrieves a dictionary of permissions and their granted status for the specified entity. + /// + /// The type of the resource. + /// The resource permission store instance. + /// The resource for which the permissions are being retrieved. + /// The unique key identifying the resource instance. + /// A dictionary where the keys are permission names and the values are booleans indicating whether the permission is granted. + public static async Task> GetPermissionsAsync( this IResourcePermissionStore resourcePermissionStore, TResource resource, object resourceKey @@ -23,10 +41,12 @@ public static class ResourcePermissionStoreExtensions Check.NotNull(resource, nameof(resource)); Check.NotNull(resourceKey, nameof(resourceKey)); - return resourcePermissionStore.GetGrantedPermissionsAsync( + var result = await resourcePermissionStore.GetPermissionsAsync( typeof(TResource).FullName!, resourceKey.ToString()! ); + + return result.Result.ToDictionary(x => x.Key, x => x.Value == PermissionGrantResult.Granted); } /// diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs new file mode 100644 index 0000000000..bc30fd20ab --- /dev/null +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/Resources/ResourcePermissionPopulator.cs @@ -0,0 +1,39 @@ +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.Permissions.Resources; + +public class ResourcePermissionPopulator : ITransientDependency +{ + protected IPermissionDefinitionManager PermissionDefinitionManager { get; } + + protected IResourcePermissionChecker ResourcePermissionChecker { get; } + + public ResourcePermissionPopulator(IPermissionDefinitionManager permissionDefinitionManager, IResourcePermissionChecker resourcePermissionChecker) + { + PermissionDefinitionManager = permissionDefinitionManager; + ResourcePermissionChecker = resourcePermissionChecker; + } + + public virtual async Task PopulateAsync(IHasResourcePermissions resource, string resourceName, string resourceKey) + { + Check.NotNull(resource, nameof(resource)); + Check.NotNull(resource.ResourcePermissions, nameof(resource.ResourcePermissions)); + Check.NotNullOrWhiteSpace(resourceName, nameof(resourceName)); + Check.NotNullOrWhiteSpace(resourceKey, nameof(resourceKey)); + + var resopurcePermissionNames = (await PermissionDefinitionManager.GetResourcePermissionsAsync()) + .Where(x => x.ResourceName == resourceName) + .Select(x => x.Name) + .ToArray(); + + var results = await ResourcePermissionChecker.IsGrantedAsync(resopurcePermissionNames, resourceName, resourceKey); + foreach (var resopurcePermission in resopurcePermissionNames) + { + var hasPermission = results.Result.TryGetValue(resopurcePermission, out var granted) && + granted == PermissionGrantResult.Granted; + resource.ResourcePermissions[resopurcePermission] = hasPermission; + } + } +} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityExtensions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityExtensions.cs new file mode 100644 index 0000000000..737cb95077 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityExtensions.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.Authorization.Permissions.Resources; + +public static class EntityExtensions +{ + public static string GetResourceName(this IEntity entity) + { + Check.NotNull(entity, nameof(entity)); + return entity.GetType().FullName!; + } + + public static string GetResourceKey(this IEntity entity) + { + Check.NotNull(entity, nameof(entity)); + return entity.GetKeys().JoinAsString(","); + } +} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionCheckerExtensions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionCheckerExtensions.cs index 963eaf20e0..8c61f3cb39 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionCheckerExtensions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionCheckerExtensions.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Domain.Entities; @@ -14,11 +13,7 @@ public static class EntityResourcePermissionCheckerExtensions /// The name of the permission to check. /// The entity for which the permission is being checked. /// A task that represents the asynchronous operation. The task result is a boolean indicating whether the permission is granted. - public static Task IsGrantedAsync( - this IResourcePermissionChecker resourcePermissionChecker, - string permissionName, - TEntity entity - ) + public static Task IsGrantedAsync(this IResourcePermissionChecker resourcePermissionChecker, string permissionName, TEntity entity) where TEntity : class, IEntity { Check.NotNull(resourcePermissionChecker, nameof(resourcePermissionChecker)); @@ -27,31 +22,8 @@ public static class EntityResourcePermissionCheckerExtensions return resourcePermissionChecker.IsGrantedAsync( permissionName, - typeof(TEntity).FullName!, - entity.GetKeys().JoinAsString(",") + entity, + entity.GetResourceKey() ); } - - /// - /// Retrieves a dictionary of permissions and their granted status for the specified entity. - /// - /// The type of the entity. - /// The resource permission checker instance. - /// The entity for which the permissions are being retrieved. - /// A dictionary where the keys are permission names and the values are booleans indicating whether the permission is granted. - public static Task> GetPermissionsAsync( - this IResourcePermissionChecker resourcePermissionChecker, - TEntity entity - ) - where TEntity : class, IEntity - { - Check.NotNull(resourcePermissionChecker, nameof(resourcePermissionChecker)); - Check.NotNull(entity, nameof(entity)); - - return resourcePermissionChecker.GetPermissionsAsync( - typeof(TEntity).FullName!, - entity.GetKeys().JoinAsString(",") - ); - } - } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionRequirementHandler.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionRequirementHandler.cs index f97ddbafef..9fe07efde9 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionRequirementHandler.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Authorization/Permissions/Resources/EntityResourcePermissionRequirementHandler.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Domain.Entities; @@ -21,8 +20,8 @@ public class EntityResourcePermissionRequirementHandler : AuthorizationHandlerThe resource permission store instance. /// The entity for which the permissions are being checked. /// An array of granted permission names as strings. - public static Task GetGrantedPermissionsAsync( + public static async Task GetGrantedPermissionsAsync( this IResourcePermissionStore resourcePermissionStore, TEntity entity ) @@ -24,37 +23,28 @@ public static class EntityResourcePermissionStoreExtensions Check.NotNull(resourcePermissionStore, nameof(resourcePermissionStore)); Check.NotNull(entity, nameof(entity)); - return resourcePermissionStore.GetGrantedPermissionsAsync( - typeof(TEntity).FullName!, - entity.GetKeys().JoinAsString(",") - ); + return (await GetPermissionsAsync(resourcePermissionStore, entity)).Where(x => x.Value).Select(x => x.Key).ToArray(); } /// - /// Retrieves an array of granted entity IDs for a specific permission. + /// Retrieves a dictionary of permissions and their granted status for the specified entity. /// /// The type of the entity. - /// The type of the entity's primary key. /// The resource permission store instance. - /// The name of the permission to check. - /// An array of entity IDs (of type ) for which the permission is granted. - public static async Task GetGrantedEntityIdsAsync( + /// The entity for which the permissions are being retrieved. + /// A dictionary where the keys are permission names and the values are booleans indicating whether the permission is granted. + public static async Task> GetPermissionsAsync( this IResourcePermissionStore resourcePermissionStore, - string permissionName + TEntity entity ) - where TEntity : class, IEntity + where TEntity : class, IEntity { Check.NotNull(resourcePermissionStore, nameof(resourcePermissionStore)); - Check.NotNullOrWhiteSpace(permissionName, nameof(permissionName)); + Check.NotNull(entity, nameof(entity)); - var keys = await resourcePermissionStore.GetGrantedResourceKeysAsync( - typeof(TEntity).FullName!, - permissionName + return await resourcePermissionStore.GetPermissionsAsync( + entity, + entity.GetResourceKey() ); - - return keys - .Select(x => Convert.ChangeType(x, typeof(TKey))) - .Cast() - .ToArray(); } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs index b9b80eb881..6228ddb97d 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/ResourcePermissionManager.cs @@ -330,25 +330,15 @@ public class ResourcePermissionManager : IResourcePermissionManager, ISingletonD var permissionNames = permissions.Select(x => x.Name).ToArray(); var multiplePermissionWithGrantedProviders = new MultiplePermissionWithGrantedProviders(permissionNames); - var neededCheckPermissions = new List(); - var resourcePermissions = await GetAvailablePermissionsAsync(resourceName); - foreach (var permission in resourcePermissions) - { - if (await SimpleStateCheckerManager.IsEnabledAsync(permission)) - { - neededCheckPermissions.Add(permission); - } - } - - if (!neededCheckPermissions.Any()) + if (!resourcePermissions.Any()) { return multiplePermissionWithGrantedProviders; } foreach (var provider in ManagementProviders) { - permissionNames = neededCheckPermissions.Select(x => x.Name).ToArray(); + permissionNames = resourcePermissions.Select(x => x.Name).ToArray(); var multiplePermissionValueProviderGrantInfo = await provider.CheckAsync(permissionNames, resourceName, resourceKey, providerName, providerKey); foreach (var providerResultDict in multiplePermissionValueProviderGrantInfo.Result)