Activities of "alexander.nikonov"

Hi,

we need to check this remotely, as we are unable understand the tenant switch scenario. is that okay with you?

As I wrote before, probably to reproduce the issue, tenant switching is not needed: it can be just UI button click which triggers https://localhost:44337/[test-app]/application-configuration?includeLocalizationResources=false call. Where the overriden AbpApplicationConfigurationAppService GetAsync() method returns the mentioned structure in extraProperties, so if some Module ID has false - the relevant page needs to be removed from ABP navigation menu. If the Module ID is not there - the page needs to be shown again. And this structure is randomly generated on each button click (giving different Module IDs from the existing ones), imitating tenant switching. Does it make sense to you?

Anyway, our policies do not allow us to share the code or show it via screen-sharing... Sorry.

Will try, thank you. Will keep you posted.

I'm afraid I can't do that. This is a commercial project - I can just show some pieces of code. Besides - we don't even have SQL Server Express setup (we use another DB) and we don't use test ABP app generation, so all preparation work would take a way more time than we are given for bug-fixing.

Probably you have some ready testing environment at your side set up? In this case even tenant switching functionality itself can be omitted - you just need to rerun this API call (by the UI button?):

And in the extra-properties return something like hidePageMap dictionary: { [moduleId of the page]: true, [moduleId of the page]: true } - moduleIDs can be randomly selected from the predefined collection you use (see below), so it imitates different users permissions when switching tenants.

Module ID for any relevant page is supplied (and read in Angular app) here: and here:

So each time you click the button and return result from application configuration - the menu needs to be shown according to the "visible" module IDs only.

P.S. Maybe in future I will ask our management to give us time for building original ABP solution test environment to be able to create bug reproduction scenarios, so it will be easier for all.

Hi Anjali.

Thank you for the response.

First - window.location.href = '/' does not help. The menu is still empty. But I was already able to make it work this way before using window.location.reload() or something like that. However, I want to avoid this approach. The reason is that this Angular thing is a Single Page Application and it does not look nice to reload a whole page instead of just refreshing a navigation menu - this is exactly what I want to get.

The idea is the following: after I receive this.configStateService.getDeep$('extraProperties.modulePermissionMap') from server, I want to make decision myself, what to show in the menu and what - not. Since ABP builds its menu based on ordinary permissions - I had to use the approach with

this.routesService.flat.filter(x => x.requiredPolicy && (x as any).data?.moduleId).forEach(x => x.invisible = true);
this.routesService.refresh();

to hide ALL the menu items from the very beginning and then start applying my logic (combineLatest([this.configStateService.getDeep$('extraProperties.modulePermissionMap'), this.routesService.flat$.pipe(take(1))])). Probably my approach is incorrect - then please advice me how to obtain my goal.

Can you provide the tenant switching context like after a tenant switch are you reloading the page?

After a successful tenant switch I'm calling the piece of code in complete callback (see the switch method code above). Also - due do the fact that switching a tenant causes changing the value of this.currentUser$ observable - the if (currentUser?.isAuthenticated) part is called (also shown above). Eventually, the aim of init method (as shown above too) is to filter out the available menu items according to user permission map in this.configStateService.getDeep$('extraProperties.modulePermissionMap') (you proposed this approach - using extraProperties- in another ticket and it was a good suggestion, everything works good, except when switching to another tenant).

Probably my code is incorrect, but I cannot share the project, sorry. So I only can write what I'd like to do:

when I switch to another tenant - the left navigation menu is refreshed and displays only those items which are available according to this current tenant users' permissions. Also I need to navigate to root (home) page, because it is the only page which is guaranteed to be available no matter what permissions are.

I really cannot switch to Redis, but I checked the UnitOfWork split and it did not help:

    [Authorize(IdentityPermissions.Roles.ManagePermissions)]
    public virtual async Task SetModuleRolesAsPermissionsAsync(Guid id, RoleUpdateDto input)
    {
        var parentRole = await _identityRoleRepository.FindAsync(id, false);
        if (parentRole == null)
        {
            throw new BusinessException(DomainErrorCodes.NotFound, _stringLocalizer.GetString("Roles:RoleNotFound"));
        }

        using (CurrentTenant.Change(null))
        {
            input.Permissions = await MergeParentAndChildPermissions(input.Permissions, parentRole.Name, ModulePermissionRoleValueProvider.ProviderName);
        }

        await InvalidateModuleRoleNameCache(parentRole.NormalizedName);

        using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
        {
            await _permissionAppService.UpdateAsync(ModulePermissionRoleValueProvider.ProviderName, parentRole.Name, new UpdatePermissionsDto { Permissions = input.Permissions.ToArray() });
            await uow.CompleteAsync();
        }

        using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
        {
            await _rabbitMqManager.UpdateAbpPermissionsAsync(input.Permissions.ToArray(), ModulePermissionRoleValueProvider.ProviderName, parentRole.Name, CurrentTenant.Id);
            await uow.CompleteAsync();
        }
    }
    

If this method did not work at all - I would suspect the issue with the method. But it works correctly - however only if I restart the mentioned host X after creating a module role (my permission definition).

The method which eventually updates ABP Permission Cache is simple:

    private async Task HandleAbpUpdatePermission(AbpPermissionRabbitMqUpdateEto abpPermissionData)
    {
        if (abpPermissionData == null)
        {
            return;
        }

        var abpPermissionGrantCache = _serviceProvider.GetService<IDistributedCache<PermissionGrantCacheItem>>();

        var currentTenant = _serviceProvider.GetService<ICurrentTenant>();

        using (currentTenant.Change(abpPermissionData.AbpTenantId))
        {
            await abpPermissionGrantCache.SetManyAsync(
                abpPermissionData.Permissions.Select(permission =>
                    new KeyValuePair<string, PermissionGrantCacheItem>(permission.Key, new PermissionGrantCacheItem(permission.Value))));
        }
    }
    

So what is happening after calling ABP PermissionAppService - _rabbitMqManager.UpdateAbpPermissionsAsync sends the message to the RabbitMQ queue and each host updates its own Permission Cache.

Is it possible to debug PermissionAppService trying to figure out why the update produces no result?

I think we are not ready to switch to Redis now... We will keep using ABP caches in the nearest time. At least it proved workable with RabbitMQ sync. I will keep you informed if splitting into units would help.

Ok, I will try. But we don't use Redis: we use ABP cache in each app and sync them via RabbitMQ. Does it make the difference?

Probably you mean I might create a test ABP solution using ABP Suite setting it up for free SQL Server Express version - then add custom Permission Definition provider stuff, then add the UI page in test Angular app for creating custom permission definitions + assigning definitions to a user role, after this - add the API method for "refreshing" permission definition and finally check if the assignment is successful.

Even if it sounds simple for you - it does not sound simple for me. Our project has been developing during 3 years, becoming more and more complex and customized. Unfortunately, we do not have dedicated time to create custom projects for resolving occured issues. The preparation stage to accomplish all this in test ABP solution seems to take a noticeable amount of time. Plus - even if everything would work out here - it would make little sense for us, since it would mean the problem is somewhere else: for instance, we use a separate host (let's call it "host X") which consumes Domain.Shared and Application.Contracts projects from other hosts (A, B, C). When I create a permission definition - i make API call to this host from host A (it is like an admin host). Then I use RabbitMQ queries to refresh ABP Permission cache in ALL hosts (A, B, C). When I want to assign the created permission definition - I also make API call from host A to host X... So, now until I restart host X - I cannot make this assignment. Probably the problem is actually in this.

I would prefer try to identify the problem in our site (by debugging, etc.) - step by step. Just let me know where do I need to look and what do I need to look (probably debug PermissionAppService or whatever).

One more note which maybe is useful, maybe not: the custom permission definition I'm trying to assign is also a role at the same time (we have two-layer role mechanism): So we actually assign a "module role" to an "ordinary role". But it should not be a problem I guess, because there is a custom Permission Definition Provider which just reads "module roles" as usual permissions from DB... Later on we assign "ordinary permissions" to "module roles".

Everything works fine in this implementation. The only issue is that I need to restart host X to be able to assign "module roles" to "ordinary roles" (user roles).

I don't think it's feasible unfortunately. Our project is commercial and highly customized... Besides, it uses Oracle DB. It would take ages to create a test project based on it.

Could you please take the method above as a reference instead, wrap it inside API and try calling it from some test Angular app after creating a permission definition from UI in this test app? After calling this method - as we suppose here - I should be able to assign the brand-new permission definition to a user role using ABP PermissionService (as also shown in the code above) without restarting the host...

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