Activities of "alexander.nikonov"

currentHash is changed. hasChangesInPermissions is true (hasChangesInGroups is false). All in all, the method SaveAsync works as expected, no catch triggered... However the permissions are not assigned...

Done. The created permissions are present in permissionRecords collection:

Despite this fact, when I try to assign them - the assignment is ignored until I restart the app:

Since I'm doing this from AppService not AbpModule as in the original code, I've simplified the code. I took the DI instances of some required services and used the code below (_dynamicPermissionDefinitionStore is not needed at all I think, because we do not use dynamic permissions, anyway, it makes no difference):

    private async Task RefreshAbpStaticAndDynamicPermissionsAsync()
    {
        await Policy
            .Handle<Exception>()
            .WaitAndRetryAsync(8, retryAttempt => TimeSpan.FromSeconds(RandomHelper.GetRandom((int)Math.Pow(2, retryAttempt) * 8, (int)Math.Pow(2, retryAttempt) * 12)))
            .ExecuteAsync(async _ => await _staticPermissionSaver.SaveAsync(), _cancellationTokenProvider.Token);

        await _dynamicPermissionDefinitionStore.GetGroupsAsync();
    }

However, it still does not work.

Do you have any further suggestions?

@maliming so basically I need to sequentially call SaveStaticPermissionsToDatabaseAsync and then - PreCacheDynamicPermissionsAsync?

Not resolved yet

I found out, that the following routing was somehow lost:

  {
    path: 'identity-server',
    loadChildren: () => import('@volo/abp.ng.identity-server').then(m => m.IdentityServerModule.forLazy()),
  },

Please, regain my points.

Thank you very much. I will try to improve my implementation using this change. I think I may close the ticket now.

Ok. Waiting.

OK - so I abandoned the idea to override the RoutesService and implemented the following handler (retaining the idea to hide the elements ASAP and unhide them after getting service data) - please have a look if there could be a more efficient solution.

    import { ABP, RoutesService } from '@abp/ng.core';
    import { Inject, Injectable, OnDestroy } from '@angular/core';
    import { BehaviorSubject, ReplaySubject, Subscription, combineLatest } from 'rxjs';
    import { distinctUntilChanged, filter, takeLast, takeUntil } from 'rxjs/operators';
    import { ModulePermissionsService } from '../services/module-permissions.service';
    
    
    @Injectable({
      providedIn: 'root'
    })
    export class ModulePermissionHandler implements OnDestroy {
    
      modulePermissionMap$: BehaviorSubject<{[key: string]: string[]}> = new BehaviorSubject<{[key: string]: string[]}>({});
      
      private destroy: ReplaySubject<any> = new ReplaySubject<any>(1);
      
      private stopMenuScan$: ReplaySubject<any> = new ReplaySubject<any>(1);
      
      private mapBindingComplete: boolean = false;
    
      constructor(
        private routesService: RoutesService,
        private modulePermissionsService: ModulePermissionsService
      ) {
      }
    
      ngOnDestroy(): void {
        this.deinit();
      }
    
      init() {
        this.routesService.flat.filter(x => x.requiredPolicy && (x as any).data?.moduleId).forEach(x => x.invisible = true);
        this.routesService.refresh();
        combineLatest([this.modulePermissionMap$, this.routesService.flat$])
          .pipe
          (
            filter(result => !this.mapBindingComplete && Object.keys(result[0]).length > 0 && Object.keys(result[1]).length > 0),
            takeUntil(this.destroy),
            takeUntil(this.stopMenuScan$)
          )
          .subscribe(([modulePermissionMap, nonLazyLoadedRoute])  => {
            let permissionProhibitedPageIds: string[] = [];
            nonLazyLoadedRoute.filter(node => node.requiredPolicy).forEach((nonLazyRouteItem: ABP.Route) => {
              let moduleId = (nonLazyRouteItem as any).data?.moduleId;
              if (moduleId) {
                const moduleIdPolicyViolated = !modulePermissionMap[moduleId] || modulePermissionMap[moduleId] && !modulePermissionMap[moduleId].includes(nonLazyRouteItem.requiredPolicy as string);
                const ordinaryRolePolicyViolated = !modulePermissionMap['_ordinaryRole'] || modulePermissionMap['_ordinaryRole'] && !modulePermissionMap['_ordinaryRole'].includes(nonLazyRouteItem.requiredPolicy as string);
                if (moduleIdPolicyViolated && ordinaryRolePolicyViolated) {
                  permissionProhibitedPageIds.push(nonLazyRouteItem.name);
                }
                else {
                  nonLazyRouteItem.invisible = false;
                }
              }
            });
            this.stopMenuScan$.next(null);
            this.stopMenuScan$.complete();
            this.routesService.remove(permissionProhibitedPageIds);
            this.mapBindingComplete = true;
            this.stopMenuScan$ = new ReplaySubject(1);
          });
    
        this.modulePermissionsService.getModulePermissionMap()
          .pipe(takeUntil(this.destroy))
          .subscribe(modulePermissionMap => {
            this.mapBindingComplete = false;
            this.modulePermissionMap$.next(modulePermissionMap);
          });
      }
    
      deinit() {
        this.destroy.next(null);
        this.destroy.complete();
      }
    }
    

Usage - app.component.ts:

   ngOnInit(): void {        
        this.oAuthService.events
          .pipe(filter(event => event?.type === 'logout'))
          .subscribe(() => {
            this.modulePermissionHandler.deinit();
          });
    
        this.currentUser$.subscribe(currentUser => {
          if (currentUser?.isAuthenticated) {
            this.modulePermissionHandler.init();
          }
        });
   }
   

And - yes - I had also to override PermissionGuard: I have copy-pasted this from route.provider.ts to app-routing.module.ts: and check this.modulePermissionMap$ in CanActivate method.

So far I have not found a better approach than hiding (setting invisible to an item with requiredPolicy and moduleId) in the createTree method) the items prior to removing or showing them inside subcription of combineLatest.

UPDATE: i've checked this approach and it has some drawbacks - after filtering the menu structure is broken (some intermediate parent nodes disappeared) and I cannot navigate to the displayed pages with "no matching route" error. I don't know if I am doing something wrong or it is bad idea to override RoutesService and hide the items in the createTree call.

Showing 181 to 190 of 345 entries
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on November 04, 2025, 06:41