- ABP Framework version: v7.0.1
- UI Type: Angular
- Database System: EF Core (Oracle)
- Auth Server Separated
I have custom Permission Definition Provider:
using AbxEps.CT.Core.Extensions;
using AbxEps.CT.Core.Localization;
using AbxEps.CT.Core.PortalMenu;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
using Volo.Abp.Threading;
using Volo.Abp.Users;
namespace AbxEps.CT.Core.Permissions
{
public class CorePermissionDefinitionProvider : PermissionDefinitionProvider
{
private readonly ICurrentUser _currentUser;
private readonly IAbxPortalsMenuAppService _abxPortalsMenuAppService;
public CorePermissionDefinitionProvider
(
IAbxPortalsMenuAppService abxPortalsMenuAppService,
ICurrentUser currentUser
)
{
_abxPortalsMenuAppService = abxPortalsMenuAppService;
_currentUser = currentUser;
}
public override void Define(IPermissionDefinitionContext context)
{
var coreCtGroup = context.AddGroup(CorePermissions.GroupName, L("Permission:Core"));
var fileMngPermission = coreCtGroup.AddPermission(CorePermissions.FileManager.Read, L("Permission:FileManager:Read"));
fileMngPermission.AddChild(CorePermissions.FileManager.Modify, L("Permission:FileManager:Modify"));
if (_currentUser.IsAuthenticated)
{
AsyncHelper.RunSync(() => InitPortalAccessPermissionsAsync(context)); // Not called, because when the host is started the user is still not authenticated - so "if" condition is not invoked
}
}
private async Task InitPortalAccessPermissionsAsync(IPermissionDefinitionContext context)
{
...
}
}
}
Whereas the permissions which are supposed to be added unconditionally (fileMngPermissions) are added successfully when host is running, the permissions which need to be added only after the user is authenticated (portalAccessPermissions) are obviously not added and not visible via IPermissionAppService
:
var allPermissionsForRole = await _permissionAppService.GetAsync("R", "Role 1");
How to add a whole CorePermissionDefinitionProvider
or the part of its relevant permissions (portalAccessPermissions) conditionally - once the user got authenticated?
P.S. I'd prefer not to use Middleware, because its Invoke
method is invoked on each request. Instead, I need to add my CorePermissionDefinitionProvider
or its authentication-related permissions once after the user authentication was successful. I use external authentication via Identity Server. So this functionality needs to reside inside the application project, not Identity Server project.
Making PermissionDefinitionManager
a ITransientDependency
(or probably I can make CorePermissionDefinitionProvider transient too) does not sound good either: I dot not want to trigger the check each time. I just need to trigger it ONCE, but after the user has been authenticated.
28 Answer(s)
-
0
Sure.
3 files here: Extension class which makes use of this "dynamic" provider,
overridden Static Store where the exception happens:
var providers = Options .DefinitionProviders .Select(p => scope.ServiceProvider.GetRequiredService(p) as IPermissionDefinitionProvider) .ToList()
if I don't use the
Configure<AbpPermissionOptions>
approachand the
PortalAccessPermissionDefinitionProvider
itself. -
0
hi
DisableConventionalRegistration will not add services to the DI container. so OnRegistered will not call. this is strange
https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs#L69-L75
-
0
Well, at least it's possible make it working using
AbpPermissionOptions
.. I don't know why it requires it. But seems like I managed to make "dynamic" permission definition provider work properly combining "static" and "dynamic" values:private IDictionary<string, PermissionGroupDefinition> _dynamicPermissionGroupDefinitions = new Dictionary<string, PermissionGroupDefinition>(); protected IDictionary<string, PermissionGroupDefinition> PermissionGroupDefinitions { get { var staticGroupDefinitions = _lazyPermissionGroupDefinitions.Value; var combinedGroupDefinitions = new Dictionary<string, PermissionGroupDefinition>(staticGroupDefinitions); foreach (var userAddedGroupDefinition in _dynamicPermissionGroupDefinitions) { combinedGroupDefinitions[userAddedGroupDefinition.Key] = userAddedGroupDefinition.Value; } return combinedGroupDefinitions; } } private readonly Lazy<Dictionary<string, PermissionGroupDefinition>> _lazyPermissionGroupDefinitions; private IDictionary<string, PermissionDefinition> _dynamicPermissionDefinitions = new Dictionary<string, PermissionDefinition>(); protected IDictionary<string, PermissionDefinition> PermissionDefinitions { get { var staticDefinitions = _lazyPermissionDefinitions.Value; var combinedDefinitions = new Dictionary<string, PermissionDefinition>(staticDefinitions); foreach (var userAddedDefinition in _dynamicPermissionDefinitions) { combinedDefinitions[userAddedDefinition.Key] = userAddedDefinition.Value; } return combinedDefinitions; } } private readonly Lazy<Dictionary<string, PermissionDefinition>> _lazyPermissionDefinitions; protected AbpPermissionOptions Options { get; } private readonly IServiceProvider _serviceProvider; public ExtendedStaticPermissionDefinitionStore( IServiceProvider serviceProvider, IOptions<AbpPermissionOptions> options) { _serviceProvider = serviceProvider; Options = options.Value; _lazyPermissionDefinitions = new Lazy<Dictionary<string, PermissionDefinition>>( CreatePermissionDefinitions, isThreadSafe: true ); _lazyPermissionGroupDefinitions = new Lazy<Dictionary<string, PermissionGroupDefinition>>( CreatePermissionGroupDefinitions, isThreadSafe: true ); } public void AddPermissionDefinitionProvider(IPermissionDefinitionProvider permissionDefinitionProvider) { using (var scope = _serviceProvider.CreateScope()) { var context = new PermissionDefinitionContext(scope.ServiceProvider); permissionDefinitionProvider.PreDefine(context); permissionDefinitionProvider.Define(context); permissionDefinitionProvider.PostDefine(context); foreach (var group in context.Groups) { _dynamicPermissionGroupDefinitions[group.Key] = group.Value; } var permissions = new Dictionary<string, PermissionDefinition>(); foreach (var groupDefinition in _dynamicPermissionGroupDefinitions.Values) { foreach (var permission in groupDefinition.Permissions) { AddPermissionToDictionaryRecursively(permissions, permission); } } foreach (var permission in permissions) { _dynamicPermissionDefinitions[permission.Key] = permission.Value; } } }
Probably would come in handy for someone. Closing the ticket... Thanks for inspiration!