- ABP Framework version: v8.1.3
- UI Type: Angular
- Database System: EF Core (Oracle)
- Auth Server Separated
We used a built-in ABP cache in our ABP framework-based solutions plus Ocelot gateway project which aggregated the permissions from different sites plus RabbitMQ synchronization for updating the permissions cache on all the sites once these permissions are updated on the single Permission Management page.
We now decided to abandon this structure in favor of Redis server cache.
Still, it is not clear for me, how to get the list of ALL the permissions (for all the sites) having now Redis server cache at hand?
I took a look at the keys of the running Redis server for the started applications, but the naming is a mess and it does not look like it contains the permissions in principle... Maybe I need to add some code to manually place ALL the permissions in Redis cache after the application has started?? Which looks a bit weird...
32 Answer(s)
-
0
hi
You should use the services related to ABP permission management instead of directly reading/writing to the Redis cache.
-
0
hi
You should use the services related to ABP permission management instead of directly reading/writing to the Redis cache.
I didn't intend to use some non-standard methods. I started from usual
IPermissionManager
methods. But it only returns me "per-application" permissions, not all. Please give me a real example of the code which would return the permissions for ALL the running applications. -
0
hi
You can use
IPermissionDefinitionManager
to get allpermission definitions
. -
0
hi
You can use
IPermissionDefinitionManager
to get allpermission definitions
.It does not return "all" permission definitions. It only returns the definitions of the current application plus the definitions from the modules which I consumed as Nuget packages (including ABP permissions, of course).
But I was talking about ALL the permission definitions from ALL running applications. Otherwise what is the point of using Redis cache, which supposedly has to store ALL such permissions?
I need to manage ALL the permissions from ALL running applications using Permission Management page on one of my portals, but those changes need to be spread across all the running applications straight after.
-
0
hi
Have you enabled the Dynamic Permission feature?
https://abp.io/support/questions/5671/Generate-Permission-Automatically-from-external-service#answer-3a0d4bfb-8d49-dcad-8e23-50b633870090
-
0
hi
Have you enabled the Dynamic Permission feature?
https://abp.io/support/questions/5671/Generate-Permission-Automatically-from-external-service#answer-3a0d4bfb-8d49-dcad-8e23-50b633870090
No. I will. Do i have to add this inside HttpApiHostModule? And also inside OpenIdServerModule?
-
0
hi
You need to enable
IsDynamicPermissionStoreEnabled & SaveStaticPermissionsToDatabase
in every project. -
0
I now started getting the exception in my custom service, but inside your code. Have no clue why. Did I miss some additional steps when moving to dynamic permissions? This step - "You should add a dynamic permission group and add sub-permissions to it" or it is not relevant?
[Dependency(ReplaceServices = true)] [ExposeServices(typeof(IAbpApplicationConfigurationAppService))] public class ModulePermissionApplicationConfigurationAppService : AbpApplicationConfigurationAppService, IAbpApplicationConfigurationAppService { public override async Task<ApplicationConfigurationDto> GetAsync(ApplicationConfigurationRequestOptions options) { var result = await base.GetAsync(options); //HERE ... } ... }
The exception is:
[01:23:05 ERR] Volo.Abp.AbpException: Undefined feature: LeptonManagement.Enable at Volo.Abp.Features.FeatureDefinitionManager.GetAsync(String name) at Volo.Abp.Features.FeatureChecker.GetOrNullAsync(String name) at Volo.Abp.Features.FeatureCheckerBase.IsEnabledAsync(String name) at Volo.Abp.Features.FeatureCheckerExtensions.IsEnabledAsync(IFeatureChecker featureChecker, Boolean requiresAll, String[] featureNames) at Volo.Abp.Features.RequireFeaturesSimpleStateChecker
1.IsEnabledAsync(SimpleStateCheckerContext
1 context) at Volo.Abp.SimpleStateChecking.SimpleStateCheckerManager1.InternalIsEnabledAsync(TState state, Boolean useBatchChecker) at Volo.Abp.SimpleStateChecking.SimpleStateCheckerManager
1.IsEnabledAsync(TState state) at Volo.Abp.Authorization.Permissions.PermissionChecker.IsGrantedAsync(ClaimsPrincipal claimsPrincipal, String[] names) at Volo.Abp.Authorization.Permissions.PermissionChecker.IsGrantedAsync(String[] names) at Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationAppService.GetAuthConfigAsync() at Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationAppService.GetAsync(ApplicationConfigurationRequestOptions options) at AbxEps.CT.ModulePermission.ModulePermissionApplicationConfigurationAppService.GetAsync(ApplicationConfigurationRequestOptions options) in C:\CT\AbxEps.AbpModules\AbxEps.CT.ModulePermission\src\AbxEps.CT.ModulePermission.Application\ModulePermissionApplicationConfigurationAppService.cs:line 77 at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter
1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue
1.ProceedAsync() at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func
3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope) at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter
1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue
1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func
3 proceed) at Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync(ApplicationConfigurationRequestOptions options) at lambda_method3395(Closure, Object) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker. -
0
hi
Undefined feature: LeptonManagement.Enable
Can you test your code with a brand new database and redis?
-
0
hi
Undefined feature: LeptonManagement.Enable
Can you test your code with a brand new database and redis?
Even if i tested it in a test solution using a clean DB (which is almost impossible), it would not help me to troubleshoot the error in our solution. I suggest to drilldown the error instead.
So I took a look a the DB and can see that the mentioned feature is present. Why is it reported as undefined?
-
0
hi
Can you try to enable the dynamic feature as well?
It will also store the feature's definitions to the database.
-
0
I did it and now everything seems to be in order. But now there is a long way to modify a custom mechanism of permissions we had in addition to the standard one and it was based on static permissions and built-in ABP cache.
I can close this ticket. But I do not guarantee I won't have further questions along the way. Should I close the ticket and then reopen if needed?
-
0
hi
If you got a new problem, You can create a new one.
Thanks.
-
0
hi
If you got a new problem, You can create a new one.
Thanks.
Still, I eventually found the thing which does not work now. So we have had an additional mechanism of permissions, with a different provider name (MR). And it worked properly - in the given example, a usual role "Role 1" has permissions assigned, as you can see. However these permissions are all displayed as non-granted by standard methods after changing to dynamic permissions + Redis. Any clues why?
-
0
hi
Did you change the record in the database table directly?
If you change the data in the database, you need to clear the cache. Otherwise, the framework will not know if the database has been changed.
-
0
No, I did not change the data in DB. It is the same as it was before switching to Redis + dynamic permissions.
-
0
hi
Please share your code to reproduce this.
Thanks.
-
0
Unfortunately, I cannot share our code. So I will try to cope with this myself and just share new details when I find our what's happening.
-
0
hi
You can share the code of the service call.
For example, how do you grand permission to a role and then check the permissions code snippet?
-
0
So I want to get the list, where
input.IsGranted
istrue
for let's say "Role 1". But now it returns me no such data (multipleGrantInfo.Result
does not contain data whereIsGranted
istrue
). It used to return data properly before and as you were able to see from the screen above, there is data for "Role 1", the tenant is correct, the provider name,ModulePermissionRoleValueProvider.ProviderName
, is correct ("MR"):public virtual async Task<PagedResultDto<PermissionGrantInfoDto>> GetModuleRolesAsPermissionsAsync(GetRolePermissionsInput input) { var parentRole = await _identityRoleRepository.FindAsync(input.Id, false); if (parentRole == null) { throw new BusinessException(DomainErrorCodes.NotFound, _stringLocalizer.GetString("Roles:RoleNotFound")); } var permissionDefinitionGroups = await _permissionDefinitionManager.GetGroupsAsync(); var permissionDefinitionModuleRoleGroup = permissionDefinitionGroups.FirstOrDefault(x => x.Name == ModulePermissionConsts.GroupName); if (permissionDefinitionModuleRoleGroup == null) { throw new ConfigurationErrorsException("Missing Module Role Permission Definition Group"); } var groupDto = CreatePermissionGroupDto(permissionDefinitionModuleRoleGroup); var neededCheckPermissions = new List<PermissionDefinition>(); foreach (var topLevelPermission in permissionDefinitionModuleRoleGroup.GetPermissionsWithChildren() .Where(x => x.Name != ModulePermissionConsts.RoleSubGroupName && x.IsEnabled && x.Providers.Contains(ModulePermissionRoleValueProvider.ProviderName))) { if (await _simpleStateCheckerManager.IsEnabledAsync(topLevelPermission)) { neededCheckPermissions.Add(topLevelPermission); } } if (!neededCheckPermissions.Any()) { return new PagedResultDto<PermissionGrantInfoDto> { TotalCount = 0, Items = new List<PermissionGrantInfoDto>() }; } var grantInfoDtos = neededCheckPermissions.Select(CreatePermissionGrantInfoDto); var multipleGrantInfo = await _permissionManager.GetAsync ( neededCheckPermissions.Select(x => x.Name).ToArray(), ModulePermissionRoleValueProvider.ProviderName, parentRole.Name ); foreach (var grantInfo in multipleGrantInfo.Result.WhereIf(input.IsGranted.HasValue, x => x.IsGranted == input.IsGranted.Value)) { var grantInfoDto = grantInfoDtos.First(x => x.Name == grantInfo.Name); grantInfoDto.IsGranted = grantInfo.IsGranted; foreach (var provider in grantInfo.Providers) { grantInfoDto.GrantedProviders.Add(new ProviderInfoDto { ProviderName = provider.Name, ProviderKey = provider.Key, }); } groupDto.Permissions.Add(grantInfoDto); } return new PagedResultDto<PermissionGrantInfoDto> { TotalCount = groupDto.Permissions.Count, Items = groupDto.Permissions.ComplexOrderBy(input.Sorting).Skip(input.SkipCount).Take(input.MaxResultCount).ToList() }; }
It looks to me that the method
var multipleGrantInfo = await _permissionManager.GetAsync ( neededCheckPermissions.Select(x => x.Name).ToArray(), ModulePermissionRoleValueProvider.ProviderName, parentRole.Name );
just ignores the value from DB now and so
IsGranted
is always false, because the input parameters here are all correct (neededCheckPermissions contains correct names, ProviderName is 'MR' and role name is 'Role 1'). BTW,List<PermissionValueProviderInfo> Providers
contains no elements which also looks weird to me, i think logically it always would have to contain at least 'MR' according to the DB and the corresponding screenshot above. -
0
hi
BTW, List<PermissionValueProviderInfo> Providers contains no elements which also looks weird to me, i think logically it always would have to contain at least 'MR' according to the DB and the corresponding screenshot above.
Can you debug the app to inject the
IOptions<PermissionManagementOptions>
to check itsManagementProviders
property. -
0
hi
BTW, List<PermissionValueProviderInfo> Providers contains no elements which also looks weird to me, i think logically it always would have to contain at least 'MR' according to the DB and the corresponding screenshot above.
Can you debug the app to inject the
IOptions<PermissionManagementOptions>
to check itsManagementProviders
property. -
0
I have one more idea, please hold on.
-
0
hi
In which project did you add your
ModulePermissionRoleValueProvider
toManagementProviders
?Does the current debug project depend on your project?
-
0
I did not transfer these lines to the project which now is responsible for Role Management:
Configure<PermissionManagementOptions>(options => { options.ManagementProviders.Add<ModulePermissionManagementProvider>(); options.ProviderPolicies[ModulePermissionRoleValueProvider.ProviderName] = ModulePermissionConsts.RoleSubGroupName; });
After I added this, the permissions are properly reflected.
But I have noticed that now after moving to dynamic permissions and Redis, selecting the permissions (basically, invoking the method above) is very slow. Can it only be related to Redis? All Redis settings are default: