@ -33,6 +33,87 @@ When you click *Actions* -> *Permissions* for a role, the permission management
In this dialog, you can grant permissions for the selected role. The tabs in the left side represents main permission groups and the right side contains the permissions defined in the selected group.
#### Reusing the Permission Management Dialog
The standard permission management dialog is reusable for any registered permission management provider. The provider name and key identify the object whose permissions are being managed.
##### MVC / Razor Pages
Use `abp.ModalManager` to open the built-in modal page:
The reusable dialog calls `IPermissionAppService`. The provider must be registered and mapped to an authorization policy as described in the [Permission Management Providers](#permission-management-providers) section. For non-admin users, only permissions that the current user already has are editable, and update requests are filtered by the same rule. Users with the built-in admin role are not subject to this editability filter.
Use `entityDisplayName` to customize the modal title and `hideBadges` to hide the granted-provider badges. The component emits `visibleChange`, so the two-way `[(visible)]` binding keeps the caller's visibility state synchronized.
### Resource Permission Management Dialog
In addition to standard permissions, this module provides a reusable dialog for managing **resource-based permissions** on specific resource instances. This allows administrators to grant or revoke permissions for users, roles and clients on individual resources (e.g., a specific document, project, or any entity).
@ -94,32 +175,45 @@ Use the `ResourcePermissionManagementModal` component's `OpenAsync` method to op
}
````
The MudBlazor package provides the same component API in the `Volo.Abp.PermissionManagement.Blazor.MudBlazor.Components` namespace.
#### Angular
Use the `ResourcePermissionManagementComponent`:
Import the standalone `ResourcePermissionManagementComponent` into your component:
````typescript
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Component } from '@angular/core';
import { ResourcePermissionManagementComponent } from '@abp/ng.permission-management';
`IPermissionManager` is the main service provided by this module. It is used to read and change the global permission values. `IPermissionManager` is typically used by the *Permission Management Dialog*. However, you can inject it if you need to set a permission value.
@ -146,7 +240,7 @@ public class MyService : ITransientDependency
}
public async Task GrantUserPermissionDemoAsync(
Guid userId, string roleName, string permission)
Guid userId, string permission)
{
await _permissionManager
.SetForUserAsync(userId, permission, true);
@ -154,6 +248,8 @@ public class MyService : ITransientDependency
}
````
The OpenIddict integration also provides `SetForClientAsync` for client permissions.
## IResourcePermissionManager
`IResourcePermissionManager` is the service for programmatically managing resource-based permissions. It is typically used by the *Resource Permission Management Dialog*. However, you can inject it when you need to grant, revoke, or query permissions for specific resource instances.
@ -243,32 +339,85 @@ public class MyService : ITransientDependency
## Cleaning Up Resource Permissions
When a resource is deleted, you should clean up its associated permissions to avoid orphaned permission records in the database. You can do this directly in your delete logic or handle it asynchronously through event handlers:
When a resource is deleted, you should clean up its associated permissions to avoid orphaned permission records in the database. Query all grants for the resource and delete the returned entities:
````csharp
public class DocumentService : ITransientDependency, IUnitOfWorkEnabled
`IUnitOfWorkEnabled` keeps the resource deletion and grant cleanup in the same unit of work. `ResourcePermissionGrant` is a multi-tenant entity, so repository queries are scoped by the current tenant data filter. If cleanup runs from the host or a background process, switch `ICurrentTenant` to the resource owner's tenant before calling `GetPermissionsAsync` and `DeleteManyAsync`; otherwise the query will not return that tenant's grants.
The `providerName` and `providerKey` arguments of `IResourcePermissionManager.DeleteAsync` identify one exact provider and key; a `null` provider key is not a wildcard. The Identity integration cleans up user and role grants, and the OpenIddict integration cleans up client grants when those entities are deleted. For your custom entities, you are responsible for removing all resource grants when the resource is deleted.
## Application Service and HTTP API
`IPermissionAppService` exposes the management operations under the `api/permission-management/permissions` route. Standard permission `GET` and `PUT` operations require the authorization policy mapped to the requested provider in `PermissionManagementOptions.ProviderPolicies`.
Standard and resource update operations handle omitted permissions differently:
* The standard permission `PUT` operation changes only the permission entries included in `UpdatePermissionsDto`. For non-admin users, entries the current user does not have are ignored.
* The resource permission `PUT` operation treats `UpdateResourcePermissionsDto.Permissions` as the complete desired set for the selected resource, provider, and provider key. Manageable permissions omitted from the list are revoked. Each resource permission is filtered by its `ManagementPermissionName` before it can be returned or changed.
## Seeding Permission Grants
Use `IPermissionDataSeeder` in a data seed contributor to add initial permission grants for a provider and key:
> ABP modules automatically handle permission cleanup for their own entities. For your custom entities, you are responsible for cleaning up resource permissions when resources are deleted.
The seeder is additive and tenant-aware. It inserts grants that do not exist for the selected provider, key, and tenant; it does not revoke existing grants that are absent from the input.
## Permission Management Providers
@ -279,6 +428,8 @@ Permission Management Module is extensible, just like the [permission system](..
The OpenIddict integration also registers a provider for client permissions.
`IPermissionManager` uses these providers when you get/set permissions. You can define your own provider by implementing the `IPermissionManagementProvider` or inheriting from the `PermissionManagementProvider` base class.
**Example:**
@ -286,7 +437,9 @@ Permission Management Module is extensible, just like the [permission system](..
````csharp
public class CustomPermissionManagementProvider : PermissionManagementProvider
The order of the providers are important. Providers are executed in the reverse order. That means the `CustomPermissionManagementProvider` is executed first for this example. You can insert your provider in any order in the `Providers` list.
`IPermissionManager` enumerates `ManagementProviders` in registration order when it reads permission values. A write operation selects the registered provider whose `Name` matches the requested provider name. Every provider name must therefore be unique.
### Resource Permission Management Providers
@ -399,15 +554,20 @@ Permission value providers are used to determine if a permission is granted. The
### Resource Permission Value Providers
Similar to the standard permission system, you can create custom value providers for resource permissions. ABP comes with two built-in resource permission value providers:
Similar to the standard permission system, you can create custom value providers for resource permissions. ABP comes with three built-in resource permission value providers:
* `UserResourcePermissionValueProvider` (`U`): Checks permissions granted directly to users
* `RoleResourcePermissionValueProvider` (`R`): Checks permissions granted to roles
* `ClientResourcePermissionValueProvider` (`C`): Checks permissions granted directly to clients
You can create your own custom value provider by implementing the `IResourcePermissionValueProvider` interface or inheriting from the `ResourcePermissionValueProvider` base class:
````csharp
using System;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization.Permissions.Resources;
public class OwnerResourcePermissionValueProvider : ResourcePermissionValueProvider
@ -441,6 +601,33 @@ public class OwnerResourcePermissionValueProvider : ResourcePermissionValueProvi
: PermissionGrantResult.Undefined;
}
public override async Task<MultiplePermissionGrantResult> CheckAsync(
ResourcePermissionValuesCheckContext context)
{
var permissionNames = context.Permissions
.Select(permission => permission.Name)
.Distinct()
.ToArray();
var result = new MultiplePermissionGrantResult(permissionNames);
var currentUserId = context.Principal?.FindUserId();
The module uses the `AbpPermissionManagement` connection string name. `AbpPermissionManagementDbProperties.DbTablePrefix` and `DbSchema` default to the common ABP database prefix and schema, and can be changed before configuring the database model.
With the default `Abp` prefix, the EF Core provider maps the following tables and the MongoDB provider maps collections with the same names:
* `AbpPermissionGrants`
* `AbpResourcePermissionGrants`
* `AbpPermissionGroups`
* `AbpPermissions`
In EF Core, the permission group and permission definition tables are mapped only when the model is configured as a host database.