ABP Framework version: v9.1
UI Type: Angular
Database System: EF Core (SQL Server)
Tiered (for MVC) or Auth Server Separated (for Angular): yes
Exception message and full stack trace:
Steps to reproduce the issue:
Good day. I'm trying to create roles at the host level that can be applied to the host and tenant [we're referring to these as global tenant roles]. The goal is for these roles to be assignable to users of tenants. We've successfully implemented the permission logic by overriding the PermissionValueProvider. To achieve this, we disabled multitenancy within the provider and looped through the host-level roles assigned to the user, checking if the required permissions are granted. Here's the code snippet:
GlobalPermissionValueProvider : PermissionValueProvider
public override async Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context)
{
var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;
if (userId == null)
{
return PermissionGrantResult.Undefined;
}
using (dataFilter.Disable<IMultiTenant>())
{
var hostRoles = await userRepository.GetRolesAsync(new Guid(userId));
foreach (var role in hostRoles.Where(r => r.TenantId == null))
{
var isGranted = await PermissionStore.IsGrantedAsync(
context.Permission.Name,
RolePermissionValueProvider.ProviderName,
role.Name
);
if (isGranted)
return PermissionGrantResult.Granted;
}
}
return PermissionGrantResult.Undefined;
}
public override async Task<MultiplePermissionGrantResult> CheckAsync(PermissionValuesCheckContext context)
{
var result = new MultiplePermissionGrantResult();
foreach (var permission in context.Permissions)
{
var singleCheck = new PermissionValueCheckContext(permission, context.Principal);
var grantResult = await CheckAsync(singleCheck);
result.Result[permission.Name] = grantResult;
}
return result;
}
HttpApiHostModule.cs
Configure<AbpPermissionOptions>(options =>
{
options.ValueProviders.Add<GlobalPermissionValueProvider>();
});
When I view the permissions for a tenant user that is assigned one of these roles (Users> Right Click > Permissions), the permissions set on the host role are not checked and not disabled. It seems they are not inherited correctly.
My questions are the following: 1.) What should I look into to fix the issue with displaying inherited permissions at the user level in the UI? 2.) Is there a better or more standard way to implement this global role-permission behavior across tenants?
Thank you.
5 Answer(s)
-
0
To fix the issue with displaying inherited permissions at the user level in the UI, you need to ensure that the Angular Permission Management UI is aware of your custom permission value provider and can reflect the effective permissions (including those inherited from host-level/global roles). The default ABP Permission Management UI only displays permissions that are directly granted to the user or their tenant roles. It does not natively aggregate or display permissions granted via custom/global logic unless you extend the backend Permission Management AppService to include these in the returned permission data. You should override or extend the Permission Management AppService (e.g., PermissionAppService) to merge the effective permissions from your GlobalPermissionValueProvider into the Permission Management DTOs returned to the UI. This way, the UI can display the correct checked/disabled state for inherited/global permissions.
There is no built-in, standard ABP way to implement host-level roles that are assignable to tenant users and have their permissions inherited across tenants. The approach you have taken—using a custom PermissionValueProvider and disabling the IMultiTenant filter to check host-level roles—is the recommended extensibility point for this scenario. However, for a more maintainable and standard approach:
- Document your custom provider and ensure it is registered before the default providers.
- Consider extending the Permission Management module's backend logic to expose "effective permissions" (including global/host-level) in the API, so the UI can reflect them.
- Optionally, contribute this pattern as a reusable module or community article for others.
Sources:
- https://docs.abp.io/en/abp/latest/Authorization#permission-value-providers
- https://docs.abp.io/en/abp/latest/Multi-Tenancy#multi-tenancy-and-permissions
This approach aligns with ABP's extensibility model for permissions, but the UI must be updated to reflect the effective permission state.
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
-
0
Just to clarify, if we extend the PermissionAppService to include inherited permissions and return them to the UI correctly, will any changes made to the enabled permissions at the user level be saved?
-
0
[htalavera] said: Just to clarify, if we extend the PermissionAppService to include inherited permissions and return them to the UI correctly, will any changes made to the enabled permissions at the user level be saved?
Hi, simply extending the
PermissionAppService.GetAsync
method to display inherited permissions in the UI won't automatically enable saving changes to those permissions at the user level.This is because when permissions are granted via the user or role permission models, they apply only to that specific user or role. In your case, since the permissions are globally granted to tenant users, overriding them at the user level won’t have any real effect (except for adding a few redundant records to the database). So, while newly granted permissions may work as expected, attempting to un-grant inherited ones likely won't take effect.
To handle this properly, you may need to override the
UpdateAsync
method in thePermissionAppService
to apply your custom logic and reviewGlobalPermissionValueProvider
again.Regards.
-
0
Got it. We were able to make it work. Thank you for the assistance.
-
0
[htalavera] said: Got it. We were able to make it work. Thank you for the assistance.
Thank you for the detailed explanation. Happy to help :)