Activities of "alexander.nikonov"

Does the currently logged-in user have the permission?

Well.. I understand now. No, he does not. But since "MR" are not only permissions for ordinary roles, but also they are ABP roles themselves (just having a special extra properties) - I want them to be always available, like any role (not like permission which must be granted). They are never supposed to be checked as permissions (their permissions are). So how to make them always available?

Thank you for the response. We are moving on.

I'm replacing "Roles" page completely. And here is a strange error. Suddenly I'm getting error on this line:

await _permissionAppService.UpdateAsync(AbxModuleRolePermissionValueProvider.ProviderName, moduleRole.Name, new UpdatePermissionsDto { Permissions = input.Permissions });

Volo.Abp.Authorization.AbpAuthorizationException: Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown. at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.CheckAsync(IAuthorizationService authorizationService, String policyName) at Volo.Abp.PermissionManagement.PermissionAppService.CheckProviderPolicy(String providerName) at Volo.Abp.PermissionManagement.PermissionAppService.UpdateAsync(String providerName, String providerKey, UpdatePermissionsDto input)

The same code for RolePermissionValueProvider.ProviderName works fine.

I'm having all "MR" providers defined: Definition, Management, Value. I had experimental page which used the faulty line and it DID work. Now I can't find anything what could make it stop working and I'm stuck. Do you have suggestions where and what I could check? It looks weird, because permission list is returned properly which means Definition Provider data is OK:

public class AbxModuleRolePermissionDefinitionProvider : PermissionDefinitionProvider
{
    public override void Define(IPermissionDefinitionContext context)
    {
        var currentUser = context.ServiceProvider.GetService<ICurrentUser>();

        if (currentUser.IsAuthenticated)
        {
            var moduleRoleGroup = context.AddGroup(ModuleRolePermissions.GroupName, L("Permission:ModuleRoleManagement"));

            var roleAppService = context.ServiceProvider.GetService<IRoleAppService>();

            var moduleRoles = roleAppService.GetModuleRolesAsync(new GetModuleRolesInput()).Result;

            var rolesPermission = moduleRoleGroup.AddPermission(ModuleRolePermissions.SubGroupName, L("Permission:ModuleRoles")).WithProviders("MR");

            for (var i = 0; i < moduleRoles.Items.Count; i++)
            {
                rolesPermission.AddChild(moduleRoles.Items[i].Name).WithProviders("MR");
            }
        }
    }
 }

Thank you. Everything works fine now.

Thank you. It works.

I now have the following questions:

a) After I create "MR" roles on one page - I navigate to the other page, where I am going to assign "MR" roles (= permission definitions with "MR" provider, as we discussed above) to an ordinary role. Alas, I cannot do that until I relogin the user. Do I need to manually add the created role:

            var moduleRole = new IdentityRole(GuidGenerator.Create(), roleName, CurrentTenant.Id)
            {
                IsDefault = false,
                IsPublic = false
            };
            moduleRole.ExtraProperties.Add("IsModuleRole", true);
            var newModuleRole = await _identityRoleRepository.InsertAsync(moduleRole, true);

to Definition Store before trying to bind it to an ordinary role (roleName):

   await _permissionAppService.UpdateAsync("MR", roleName, new UpdatePermissionsDto { Permissions = input.Permissions });

?

The above is happening because the following method returns null for moduleRole.Name until relogin:

var permission = await PermissionDefinitionManager.GetOrNullAsync(permissionName);

b) I'd like to clarify: in which cases do I need to implement own PermissionManagementProvider? It has the same methods as ValueProviders, CheckAsync...

c) If I modify the module roles assigned to an ordinary role - I want to modify the corresponding "moduleRole" claims. How and where to do that efficiently (possibly caching instead of pulling from DB each time) without user relogin? I think you might have used similar mechanism already for your data. I'd prefer to update the accessible pages (and APIs) even if the page in the Angular app is reloaded; Please keep in mind, that on one hand - we are talking about ABP roles (which differ from ordinary roles only by extra field), on other hand they are permission definitions for "MR" provider;

d) will permissionServive.getGrantedPolicy or *abpPermission directive in Angular work for my "MR" permissions in the same way as it work for ordinary "R" permissions?

Sorry for long posts - I'm trying to find the answers myself, but it's just too much coming up during this development.

Hi. We recently updated to 7.01. We're not planning to update to 7.03 so far, but would like it fixed by manually changing the wrong code. Yes, the problem comes up when moving items from right to left list.

Hi. My question is related to your reply. Please provide the link / instruction how to apply 7.0 patch. I may reopen my ticket if it matters.

How to apply this patch and where to find it? This is what I have found on github:

I need to filter out only "MR" roles here:

For this purpose I'm going to useIsModuleRole property:

Since I want to have it accessible in my claims by the time CheckAsync is called - I need to add this property there somehow. I've found out there are two ways to do that. I've tried both and in both cases the property is successfully added. But later it disappears and the only property I see in Properties is http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/ShortTypeName = role (I don't have idea who adds this, but looks like a default property). So my attempts are below:

  1. Using Contributor:

     public Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
     {
         var claimsIdentity = context.ClaimsPrincipal.Identities.First(x => x.AuthenticationType == IdentityAuthenticationType);
    
         var roleClaims = claimsIdentity.FindAll(x => x.Type == AbpClaimTypes.Role).ToArray();
    
         if (roleClaims.Length > 0)
         {
             var moduleRoles = _identityRoleRepository.GetListAsync().Result.Where(x => x.GetProperty("IsModuleRole", false)).Select(x => x.Name);
    
             if (moduleRoles.Any())
             {
                 for (var i = 0; i &lt; roleClaims.Length; i++)
                 {
                     if (moduleRoles.Contains(roleClaims[i].Value))
                     {
                         roleClaims[i].Properties.AddIfNotContains(new System.Collections.Generic.KeyValuePair&lt;string, string&gt;("IsModuleRole", "true")); // I can see the property is present in the claimsIdentity, but in the CheckAsync method - no more...
                     }
                 }
             }
         }
    
         return Task.CompletedTask;
     }
    
  2. Using Factory:

     public class AbxUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory
     {
         private static string IdentityAuthenticationType => "Identity.Application";
    
         private readonly IIdentityRoleRepository _identityRoleRepository;
    
         public AbxUserClaimsPrincipalFactory
         (           
             UserManager&lt;Volo.Abp.Identity.IdentityUser&gt; userManager,
             RoleManager&lt;Volo.Abp.Identity.IdentityRole&gt; roleManager,
             IOptions&lt;IdentityOptions&gt; options,
             ICurrentPrincipalAccessor currentPrincipalAccessor,
             IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory,
             IIdentityRoleRepository identityRoleRepository
         )
             : base(userManager, roleManager, options, currentPrincipalAccessor, abpClaimsPrincipalFactory)
         {
             _identityRoleRepository = identityRoleRepository;
         }
    
         [UnitOfWork]
         public async override Task&lt;ClaimsPrincipal&gt; CreateAsync(Volo.Abp.Identity.IdentityUser user)
         {
             var principal = await base.CreateAsync(user);
    
             var identity = principal.Identities.First(x => x.AuthenticationType == IdentityAuthenticationType);
    
             var roleClaims = identity.FindAll(x => x.Type == AbpClaimTypes.Role).ToArray();
    
             var moduleRoles = (await _identityRoleRepository.GetListAsync()).Where(x => x.GetProperty("IsModuleRole", false)).Select(x => x.Name);
    
             if (moduleRoles.Any())
             {
                 for (var i = 0; i &lt; roleClaims.Length; i++)
                 {
                     if (moduleRoles.Contains(roleClaims[i].Value))
                     {
                         roleClaims[i].Properties.AddIfNotContains(new System.Collections.Generic.KeyValuePair&lt;string, string&gt;("IsModuleRole", "true")); // I can see the property is present in the claimsIdentity, but in the CheckAsync method - no more...
                     }
                 }
             }
    
             return principal;
         }
     }
    

Probably here the Properties is occasionally replaced with a new collection?

    public class AbpClaimsMapMiddleware : IMiddleware, ITransientDependency
    {
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            var currentPrincipalAccessor = context.RequestServices
                .GetRequiredService&lt;ICurrentPrincipalAccessor&gt;();
    
            var mapOptions = context.RequestServices
                .GetRequiredService&lt;IOptions&lt;AbpClaimsMapOptions&gt;>().Value;
    
            var mapClaims = currentPrincipalAccessor
                .Principal
                .Claims
                .Where(claim => mapOptions.Maps.Keys.Contains(claim.Type));
    
            currentPrincipalAccessor
                .Principal
                .AddIdentity(
                    new ClaimsIdentity(
                        mapClaims
                            .Select(
                                claim => new Claim(
                                    mapOptions.Maps[claim.Type](),
                                    claim.Value,
                                    claim.ValueType,
                                    claim.Issuer
                                )
                            )
                    )
                );
    
            await next(context);
        }
    }

Oh, was a bit unexpected, but now I understand. I need a "root" permission definition - I cannot assign my permissions straight to the group:

{
    ...
    var rolesPermission = moduleRoleGroup.AddPermission(ModuleRolePermissions.SubGroupName, L("Permission:ModuleRoles")).WithProviders("MR");
    ...
}

{
    ...
    options.ProviderPolicies[AbxModuleRolePermissionValueProvider.ProviderName] = "ModuleRoles"; //TODO: Replace with constant ModuleRolePermissions.SubGroupName
    ...
}

Regarding what you have said in the very beginning:

You need to cover the role permission provider to load the permissions of the custom role under the role

do I need to REPLACE some ABP providers (instead of adding my own ones)? What I'm going to do eventually is to replace ABP "Permissions" dialog completely. At the same time, I want to retain as much existing code as possible. I.e. I'm extending Role Management with my two-level role system, but I don't want to break anything which already is functioning at ABP side (if ABP needs traditional approach at some page, it needs to keep functioning).

Thank you. OK - on Application.Contracts layer i've created AbxModuleRolePermissionDefinitionProvider where I defined all "so-called" permissions (according to our requirements - second-level roles):

public class AbxModuleRolePermissionDefinitionProvider : PermissionDefinitionProvider
{
    public override void Define(IPermissionDefinitionContext context)
    {
        var currentUser = context.ServiceProvider.GetService&lt;ICurrentUser&gt;();

        if (currentUser.IsAuthenticated)
        {
            var moduleRoleGroup = context.AddGroup(ModuleRolePermissions.GroupName, L("Permission:ModuleRoleManagement"));

            var moduleRoleAppService = context.ServiceProvider.GetService&lt;IModuleRoleAppService&gt;();

            var moduleRoles = moduleRoleAppService.GetModuleRolesAsync(new GetModuleRolesInput()).Result;

            for (var i = 0; i &lt; moduleRoles.Items.Count; i++)
            {
                moduleRoleGroup.AddPermission(moduleRoles.Items[i].Name).WithProviders(&quot;MR&quot;);
            }
        }
    }

    private static LocalizableString L(string name)
    {
        return LocalizableString.Create&lt;CoreResource&gt;(name);
    }

I also put the line related to policies into Module:

    Configure&lt;AbpPermissionOptions&gt;(options =>
    {
        options.ValueProviders.Add&lt;AbxModuleRolePermissionValueProvider&gt;();
    });

    Configure&lt;PermissionManagementOptions&gt;(options =>
    {
        options.ProviderPolicies[AbxModuleRolePermissionValueProvider.ProviderName] = "WHAT_IS_IT";
        options.ManagementProviders.Add&lt;AbxModuleRolePermissionManagementProvider&gt;();
    });

And this list is successfully loaded on my page (see the grid below). But nevertheless, when I try to update the permissions with the code in the first post, I'm getting the same error.

Showing 141 to 150 of 276 entries
Made with ❤️ on ABP v9.0.0-preview Updated on September 20, 2024, 08:30