Search code examples
angularauthorizationnebular

Nebular Roles - isGranted() always true


Good evening,

I am configuring Nebular to work with roles. Server side everything works, front end side everything seems like it's working but accessControl.isGranted() always returns true. This is some of the code I am using:

Roles definition:

@NgModule({

  imports: [
   // ...

   NbSecurityModule.forRoot({
     accessControl: {
       guest: {
         view: [],
       },
       worker: {
         parent: 'guest',
         view: ["home", "profile", "tools"],
       },
       customer: {
         parent: 'guest',
         view: ["home"],
       },
       manager: {
         parent: 'guest',
         view: '*',
         create: '*',
         remove: '*',
       },
     },
   }),

 ],

Role Provider

This is exactly the same as Nebular website

  getRole(): Observable<string> {
    return this.authService.onTokenChange()
      .pipe(
        map((token: NbAuthJWTToken) => {
          // console.log(token.getPayload()['role']) shows the expected role
          return token.isValid() ? token.getPayload()['role'] : 'guest';
        }),
      );
  }

imports and providers configured as in https://akveo.github.io/nebular/docs/security/acl-configuration--usage#role-provider

The code that does not work

I need to hide some sidebar entries base on role so I was doing, in my routing.module.ts:

this.menu = 
{
  // ....
  {
    path: "home",
    component: "HomeComponent",
    hidden: !accessChecker.isGranted('view', 'home'),
  },
  {
    path: "tools",
    component: "adminPanelComponent",
    hidden: !accessChecker.isGranted('view', 'tools'),
  },
  {
    path: "admin",
    component: "adminPanelComponent",
    hidden: !accessChecker.isGranted('view', 'admin'),
  }
  // ....
}

The problem is that the menu items are always visible, so isGranted is always true somehow. What is the problem?

Thank you!


Solution

  • I figured out that on the HTML the pipe async is used. In the component code I cannot use this pipe so I have to use a subscription to get the value correctly. I really didn't want to use subscriptions, but since I had to I figured out this solution:

    this.accessChecker.isGranted("view", "admin")
    .pipe( take(1) )
    .subscribe( (granted: boolean) => {
      hide_admin_menu = !granted;
    });
    
    ....
    ....
    
    this.menu = [
      {
        title: ...,
        icon: ...,
        hidden: hide_admin_menu,
      },
    
      ....
      ....
    ]
    

    Everything works now, but I feel like this is still not the best/most elegant solution.