Code Monkey home page Code Monkey logo

ngx-permissions's Introduction

ngx-permissions

Permission and roles based access control for your angular(angular 2,4,5,6,7,8+) applications(AOT, lazy modules compatible)

Disclaimer

- This library is PROHIBITED to use with russians projects or russians or belarusians 

We are against any forms of discrimination. We respect sanctions. We don’t support agressors

reason https://9gag.com/gag/a41zRvw and many more

If You can help Ukrainian army https://bank.gov.ua/en/about/support-the-armed-forces

Humanitarian aid https://bank.gov.ua/en/about/humanitarian-aid-to-ukraine

Any help is welcomed.

Build Status codecov npm version npm

Documentation and examples

Documentation here is outdated please visit wiki-page. To see better structured documentation go to wiki-page.
In one month the detailed functionality description will be available only on wiki page.

Demo

You can test library in Plunker

YouTube

I'm working on tutorial for the library will add more video with time. This is my first videos YouTube

Support

If You have chance please support on patreon for more open source ideas Support me on Patreon

Or on buy me a coffee BuyMeACoffee

Table of contents

Some functionality is missing visit wiki-page

Library Version 13 minimal angular 13.

With version 7 minimal angular version 8.0

With version 5 minimal rxjs dependency 6.0

With version 4 minimal rxjs dependency 5.5

Version 2 for angular 4/5. Version 1 for angular 2/4

Installation

To install this library, run:

$ npm install ngx-permissions --save

Consuming library

You can import library in any Angular application by running:

$ npm install ngx-permissions  --save

and then from your Angular AppModule:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

// Import your library
import { NgxPermissionsModule } from 'ngx-permissions';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,

    // Specify your library as an import
     NgxPermissionsModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

SharedModule

If you use a SharedModule that you import in multiple other feature modules, you can export the NgxPermissionsModule to make sure you don't have to import it in every module.

@NgModule({
    exports: [
        CommonModule,
        NgxPermissionsModule
    ]
})
export class SharedModule { }

Note: Never call a forRoot static method in the SharedModule. You might end up with different instances of the service in your injector tree. But you can use forChild if necessary.

Lazy loaded modules

When you lazy load a module, you should use the forChild static method to import the NgxPermissionsModule.

Since lazy loaded modules use a different injector from the rest of your application, you can configure them separately. You can also isolate the service by using permissionsIsolate: true or rolesIsolate: true. In which case the service is a completely isolated instance. Otherwise, by default, it will share its data with other instances of the service.

@NgModule({
    imports: [
        NgxPermissionsModule.forChild()
    ]
})
export class LazyLoadedModule { }
@NgModule({
    imports: [
        NgxPermissionsModule.forChild({
        permissionsIsolate: true, 
        rolesIsolate: true})
    ]
})
export class LazyIsolatedLoadedModule { }

Once your library is imported, you can use its components, directives and pipes in your Angular application:

Import service to the main application and load permissions

import { Component, OnInit } from '@angular/core';
import { NgxPermissionsService } from 'ngx-permissions';
import { HttpClient } from '@angular/common/http';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  title = 'app';

   constructor(private permissionsService: NgxPermissionsService,
               private http: HttpClient) {}

  ngOnInit(): void {
    const perm = ["ADMIN", "EDITOR"];

    this.permissionsService.loadPermissions(perm);
    
     this.http.get('url').subscribe((permissions) => {
       //const perm = ["ADMIN", "EDITOR"]; example of permissions
       this.permissionsService.loadPermissions(permissions);
    })
  }
}

Usage in templates

<div *ngxPermissionsOnly="['ADMIN', 'GUEST']">
    <div>You can see this text congrats</div>
</div>

<ng-template ngxPermissionsOnly="ADMIN">
  <div>You can see this text congrats</div>
 </ng-template>
 
 <ng-template [ngxPermissionsExcept]="['JOHNY']">
   <div> All will see it except JOHNY</div>
 </ng-template>

Managing permissions

Overview

  1. Introduction
  2. Defining permissions
  3. Individual permissions
  4. To load permissions before application start up
  5. Multiple permissions
  6. Removing permissions
  7. Retrieving permissions

Introduction

Let's start with little explanation what permission is. Permission is the most atomic ability that a user can have in your application. So you can think about permission as a smallest action that user can do inside your site.

But can user or anonymous be a permission? Technically yes, but from business point of view you should treat them as Roles that are more complex objects that can store more complex logic.

πŸ’‘ Note
It's a good convention to start permission with a verb and combine them with resource or object, so permissions like readDocuments or listSongs are meaningful and easy to understand for other programmes. Notice that they are named lowerCamelCase for easy differentiation form roles.

πŸ’€ Warning
This library is intended for simplify the client side development workflow in a role based web application. DO NOT RELY ONLY ON THIS CHECKS FOR YOU APPLICATION SECURITY! Client side checks can be easily bypassed, so always implement the checks on the backend!

Defining permissions

So, how do you tell Permission what does 'readDocuments' or 'listSongs' mean and how to know if the current user belongs to those definitions?

Well, Permission allows you to set different 'permissions' definitions along with the logic that determines if the current session belongs to them. To do that library exposes special container NgxPermissionsService that allows you to manipulate them freely.

Individual permissions

To add permissions individually NgxPermissionsService exposes method addPermission that generic usage is shown below or add as array:

[...]
 ngOnInit() {
    this.permissionsService.addPermission('changeSomething')
    this.permissionsService.addPermission(['changeSomething', 'anotherAlso'])
    this.permissionsService.addPermission('changeSomething', () => {
        return true;
    })
     
    this.permissionsService.addPermission('anotherPermissions', (permissionName, permissionsObject) => {
        return !!permissionsObject[permissionName];
    });
    this.permissionsService.addPermission(['anotherPermissions', 'AnotherOne'], (permissionName, permissionsObject) => {
        return !!permissionsObject[permissionName];
    });
     
    //Will add validation function to every permission
     this.permissionsService.addPermission(['anotherPermissions', 'AnotherOne'], (permissionName, permissionsObject) => {
         return !!permissionsObject[permissionName];
     });
     
     this.permissionsService.addPermission('permissions', (permissionName, permissionsObject) => {
       return this.checkSession().toPromise();
     });
 }

To load permissions before application start up

APP_INITIALIZER is defined in angular/core. You include it in your app.module.ts like this.

APP_INITIALIZER is an OpaqueToken that references the ApplicationInitStatus service. ApplicationInitStatus is a multi provider. It supports multiple dependencies and you can use it in your providers list multiple times. It is used like this.

import { APP_INITIALIZER } from '@angular/core';

@NgModule({
  providers: [
    DictionaryService,
    {
      provide: APP_INITIALIZER,
      useFactory: (ds: DictionaryService, ps: NgxPermissionsService ) => function() {return ds.load().then((data) => {return ps.loadPermissions(data)})},
      deps: [LoadService, NgxPermissionsService],
      multi: true
    }]
})
export class AppModule { }

Validation function are injected with any angular services. There are 2 local injectables available that can be used to implement more complex validation logic.

Injectable Local Description
permissionName String representing name of checked permission
permissionsObject Object of store permissions storing permissions properties

It also have to return one of values to properly represent results:

Validation result Returned value
Valid [true|Promise.resolve() but it should not resolve false]
Invalid [false|Promise.reject() or Promise.resolve(false)]

Multiple permissions

To define multiple permissions method loadPermissions can be used. The only difference from definePermission is that it accepts Array of permission names instead of single one.

Often meet example of usage is set of permissions (e.g. received from server after user login) that you will iterate over to check if permission is valid.

const permissions = ['listMeeting', 'seeMeeting', 'editMeeting', 'deleteMeeting']
NgxPermissionsService.loadPermissions(permissions) 
NgxPermissionsService.loadPermissions(permissions, (permissionName, permissionStore) => {
    return !!permissionStore[permissionName];
}) 

NOTE: This method will remove older permissions and pass only new;

Removing permissions

You can easily remove all permissions form the NgxPermissionsService (e.g. after user logged out or switched profile) by calling:

NgxPermissionsService.flushPermissions();

Alternatively you can use removePermission to delete defined permissions manually:

NgxPermissionsService.removePermission('user');

Retrieving permissions

And to get all user permissions use method getPermissions or use Observable permissions$:

var permissions = NgxPermissionsService.getPermissions();

NgxPermissionsService.permissions$.subscribe((permissions) => {
    console.log(permissions)
})

Managing roles

Before start

Make sure you are familiar with:

Overview

  1. Introduction
  2. Defining roles
  3. Individual roles
  4. Multiple roles
  5. Removing roles
  6. Getting all roles

Introduction

By definition a role is a named set of abilities (permissions) by which a specific group of users is identified. So for example USER or ANONYMOUS would be roles and not permissions. We can represent our USER role as a group of permissions that the role should be able to perform. For example: listArticles, editArticles and other custom server/browser validated privileges.

πŸ’‘ Note
It's a good convention to name roles with UPPER_CASE, so roles like ACCOUNTANT or ADMIN are easier to distinguish from permissions.

Defining roles

Individual roles

Similarly to permissions we are gonna use here RolesService that exposes addRole allowing to define custom roles used by users in your application.

[...]

NgxRolesService
  .addRole('ROLE_NAME', ['permissionNameA', 'permissionNameB', 'permissionNameC', ...])
  
NgxRolesService.addRole('Guest', () => {
      return this.sessionService.checkSession().toPromise();
  }); 

NgxRolesService.addRole('Guest', () => {
      return true;
  }); 

Validation function are injected with any angular services. There are 2 local injectables available that can be used to implement more complex validation logic.

Parameter Description
roleName String representing name of checked role
transitionProperties Array or validation function

It also have to return one of values to properly represent results:

Validation result Returned value
Valid [true|Promise.resolve() but it should not resolve false]
Invalid [false|Promise.reject() or Promise.resolve(false)]

Note: Right now to make request to the backend it only supports promises Note: If at least one of request fulfils it will show the component

Usage of addRole is very similar to addPermissions:

NgxRolesService
  NgxPermission
  // Library will internally validate if 'listEvents' and 'editEvents' permissions are valid when checking if role is valid   
  .addRole('ADMIN', ['listEvents', 'editEvents']);  
  
NgxRolesService.addRole('Guest', () => {
      return this.sessionService.checkSession().toPromise();
  });  
  

Multiple roles

Service NgxRolesService allows you define multiple roles with addRoles method. This method accepts Object containing keys as a role names and corresponding validators as values.

NgxRolesService    
  // Or use your own function/service to validate role
  .addRoles({
    'USER': ['canReadInvoices'],
    'ADMIN': ['canReadInvoices','canEditInvoices','canUploadImages'],
    'GUEST': () => {
        return this.sessionService.checkSessions().toPromise();
    }
  });

πŸ’‘ Note

Removing roles

To remove all roles use flushRoles method:

NgxRolesService.flushRoles();

Alternatively you can use removeRole to delete defined role manually:

NgxRolesService.removeRole('USER');

Getting all roles

To get specific role use method getRole:

let role = NgxRolesService.getRole('roleName');

And to get all roles form NgxRolesService use method getRoles or use Observable roles$:

let roles = NgxRolesService.getRoles();

NgxRolesService.roles$.subscribe((data) => {
    console.log(data);
})

Controlling access in views

Overview

  1. Permission directive
  2. Basic usage

Permission directive

Permission module exposes directive ngxPermissionsOnly and ngxPermissionsExcept that can show/hide elements of your application based on set of permissions.

πŸ”₯ Important
Else, then syntax is supported.
Note if you use then block don't put anything in main block it will be not visible, only then block will be used.

Permission directive accepts several attributes:

Attribute Value Description
ngxPermissionsOnly [String | String[]] Single or multiple permissions allowed to access content
ngxPermissionsExcept [String | String[]] Single or multiple permissions denied to access content
(permissionsAuthorized) EventEmitter EventEmitter emitted when authorized
(permissionsUnauthorized) EventEmitter EventEmitter emitted when unAuthorized

Basic usage

Directives accepts either single permission that has to be met in order to display it's content, You can use both ngxPermissionsOnly and ngxPermissionsExcept at the same time:

<ng-template [ngxPermissionsOnly]="['ADMIN']" (permissionsAuthorized)="yourCustomAuthorizedFunction()" (permissionsUnauthorized)="yourCustomAuthorizedFunction()">
    <div>You can see this text congrats</div>
 </ng-template>
 <ng-template [ngxPermissionsOnly]="'ADMIN'"  [ngxPermissionsExcept]="'Manager'">
    <div>You can see this text congrats</div>
 </ng-template>
  <ng-template ngxPermissionsOnly="ADMIN">
    <div>You can see this text congrats</div>
 </ng-template>
 
 <ng-template [ngxPermissionsExcept]="['JOHNY']">
   <div> All will see it except JOHNY</div>
 </ng-template>

Or set of permissions separated by 'coma':

<ng-template [ngxPermissionsOnly]="['ADMIN', 'GUEST']">
    <div>You can see this text congrats</div>
</ng-template>

 <ng-template [ngxPermissionsExcept]="['ADMIN', 'JOHNY']">
   <div>All will see it except admin and Johny</div>
 </ng-template>
  <ng-template [ngxPermissionsExcept]="['ADMIN', 'JOHNY']" [ngxPermissionsOnly]="['MANAGER']">
    <div>All will see it except admin and Johny</div>
  </ng-template>
  
  <ng-template [ngxPermissionsExcept]="['MANAGER']" 
  [ngxPermissionExceptThen]="thenBlock" 
  [ngxPermissionExceptElse]="elseBlock">
    </ng-template>
   <ng-template #elseBlock>
       <div>elseBlock</div>
   </ng-template>
   <ng-template #thenBlock>
       <div>thenBlock</div>
   </ng-template>
   
   <ng-template
     [ngxPermissionsOnly]="['MANAGER']" 
     [ngxPermissionsOnlyThen]="thenBlock" 
     [ngxPermissionsOnlyElse]="elseBlock">
       </ng-template>
      <ng-template #elseBlock>
          <div>elseBlock</div>
      </ng-template>
      <ng-template #thenBlock>
          <div>thenBlock</div>
      </ng-template>
    
    
 

Or just simply by *

<div *ngxPermissionsOnly="['ADMIN', 'GUEST']">
    <div>You can see this text congrats</div>
</div>

 <div *ngxPermissionsOnly="['THEN_BLOCK']; else elseBlock; then thenBlock">main</div>
     <ng-template #elseBlock>
         <div>elseBlock</div>
     </ng-template>
     <ng-template #thenBlock>
         <div>thenBlock</div>
     </ng-template>
     
 <div *ngxPermissionsExcept="['THEN_BLOCK']; else elseBlock; then thenBlock"></div>
       <ng-template #elseBlock>
           <div>elseBlock</div>
       </ng-template>
       <ng-template #thenBlock>
           <div>thenBlock</div>
       </ng-template>

Note: You cant use * style with other * style directives like *ngIf. You should wrap them. And YES i don't like it either.

 <div *ngxPermissionsOnly="['ADMIN', 'GUEST']">
  <div *ngIf="true">
    You can see this text congrats
  </div>
 </div>

πŸ”₯ Important
Using with except and only together should use ngxPermissionsElse or ngxPermissionsThen

    <ng-template [ngxPermissionsExcept]="'FAIL_BLOCK'" 
    [ngxPermissionsOnly]="'ONLY_BLOCK'"
    [ngxPermissionsElse]="elseBlock"
    [ngxPermissionsThen]="thenBlock">
              
    </ng-template>
    <ng-template #elseBlock>
        <div>elseBlock</div>
    </ng-template>
    <ng-template #thenBlock>
        <div>thenBlock</div>
    </ng-template>

Usage with Routes

  1. Introduction
  2. Property only and except
  3. Single permission/role
  4. Multiple permissions/roles
  5. Dynamic access
  6. Property redirectTo
  7. Single rule redirection
  8. Multiple rule redirection
  9. Dynamic redirection rules
  10. Implemented Guards
  11. Can Activate Guard
  12. Can Load Guard
  13. Can Activate Child Guard
  14. Common use cases
  15. Two guards when first make request for authorisation and gets permissions second checks for permissions

Introduction

Now you are ready to start working with controlling access to the states of your application. In order to restrict any state ngx-permission rely on angular-route's data property, reserving key permissions allowing to define authorization configuration.

Permissions object accepts following properties:

Property Accepted value
only [String|Array|Function]
except [String|Array|Function]
redirectTo [String]

Property only and except

Property only:

  • is used to explicitly define permission or role that are allowed to access the state
  • when used as String contains single permission or role
  • when used as Array contains set of permissions and/or roles

Property except:

  • is used to explicitly define permission or role that are denied to access the state
  • when used as String contains single permission or role
  • when used as Array contains set of permissions and/or roles

πŸ”₯ Important
If you combine both only and except properties you have to make sure they are not excluding each other, because denied roles/permissions would not allow access the state for users even if allowed ones would pass them.

Single permission/role

In simplest cases you allow users having single role permission to access the state. To achieve that you can pass as String desired role/permission to only/except property: You can use except and only at the same time;

import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { NgxPermissionsGuard } from 'ngx-permissions';

const appRoutes: Routes = [
  { path: 'home',
    component: HomeComponent,
    canActivate: [NgxPermissionsGuard],
    data: {
      permissions: {
        only: 'ADMIN'
      }
    }
  },
];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

In given case when user is trying to access home state NgxPermissionsGuard service is called checking if isAuthorized permission is valid:

  • if permission definition is not found it stops transition

Multiple permissions/roles

Often several permissions/roles are sufficient to allow/deny user to access the state. Then array value comes in handy:

import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { NgxPermissionsGuard } from 'ngx-permissions';

const appRoutes: Routes = [
  { path: 'home',
    component: HomeComponent,
    canActivate: [NgxPermissionsGuard],
    data: {
      permissions: {
        only: ['ADMIN', 'MODERATOR'],
        except: ['GUEST']
      }
    }
  },
];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

When NgxPermissionsGuard service will be called it would expect user to have either ADMIN or MODERATOR permissions to pass him to home route.

Dynamic access

You can find states that would require to verify access dynamically - often depending on parameters.

Let's imagine situation where user want to modify the invoice. We need to check every time if he is allowed to do that on state level. We are gonna use ActivatedRouteSnapshot and RouterStateSnapshot object to check weather he is able to do that.

To make AOT compatible you should export function. Below is presented code AOT Compatible

AOT compatible

export function testPermissions(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
  if (route.params['id'] === 42) {
    return ['MANAGER', "UTILS"]
  } else {
    return 'ADMIN'
  }
}
const appRoutes: Routes = [
  { path: 'dynamic/:id',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
        permissions: {
          only: testPermissions
        }
      }
    }
];

πŸ’€ Warning
The code below is not AOT compatible

const appRoutes: Routes = [
  { path: 'dynamic/:id',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
        permissions: {
          only: (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
              if (route.params['id'] === 42) {
                  return ['MANAGER', "UTILS"]
                } else {
                  return 'ADMIN'
                }
          }
        }
      }
    }
];

So whenever we try access state with param id = 42 set to true additional check for permission manager and utils will be made. Otherwise only ADMIN will be required.

πŸ”₯ Important
Notice that function must always return array or string of roles/permissions in order to work properly.

Property redirectTo

Property redirectTo:

  • when used as String defines single redirection rule
  • when used as Objects defines single/multiple redirection rules
  • when used as Function defines dynamic redirection rule(s)

Single redirection rule

In case you want to redirect to a specific state when the user is not authorized, set redirectTo path to that route.

import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { NgxPermissionsGuard } from 'ngx-permissions';

const appRoutes: Routes = [
  { path: 'home',
    component: HomeComponent,
    canActivate: [NgxPermissionsGuard],
    data: {
      permissions: {
        only: ['ADMIN', 'MODERATOR'],
        redirectTo: '/another-route'
      }
    }
  },
];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}

In order to pass additional properties like params, set redirectTo to an object. navigationCommands and navigationExtras are reserved words it corresponds to parameters passed to router.navigate function navigate(commands: any[], extras: NavigationExtras): Promise<boolean>

const appRoutes: Routes = [
  { path: 'home',
    component: HomeComponent,
    canActivate: [NgxPermissionsGuard],
    data: {
      permissions: {
        only: ['ADMIN', 'MODERATOR'],
        redirectTo: {
            navigationCommands: ['123'],
            navigationExtras: {
                skipLocationChange: true
            }
        }               
    }
  },
];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ]
})

Multiple redirection rules

In case you want to redirect the user based on denied permission/role to create redirection strategies. In order to do that you have to create redirection Object that contain keys representing rejected permissions or roles and values implementing redirection rules.

Redirection rules are represented by following values:

Value type Return Usage
String [String] Simple state transitions
Object [Object] Redirection with custom parameters or options
Function [String|Object] Dynamic properties-based redirection

πŸ’‘ Note
Use default property that will handle fallback redirect for not defined permissions.

The simplest example of multiple redirection rules are redirection based on pairs role/permission and state. When user is not granted to access the state will be redirected to agendaList if missing canReadAgenda permission or to dashboard when missing canEditAgenda. Property default is reserved for cases when you want handle specific cases leaving default redirection.

  const appRoutes: Routes = [
    { path: 'home',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
       permissions: {
               only: ['canReadAgenda','canEditAgenda'],
               redirectTo: {
                 canReadAgenda: 'agendaList',
                 canEditAgenda: 'dashboard',
                 default: 'login'
               }
        }
      }
    },
  ];
  @NgModule({
    imports: [
      RouterModule.forRoot(appRoutes)
    ],
    exports: [
      RouterModule
    ]
  })

If you need more control over redirection parameters Object as a value can be used to customise target url navigationCommands and transition navigationExtras.

πŸ’‘ Note navigationCommands and navigationExtras are reserved words it corresponds to parameters passed to router.navigate function navigate(commands: any[], extras: NavigationExtras): Promise<boolean>

  const appRoutes: Routes = [
    { path: 'home',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
         permissions: {
               only: ['canEditAgenda'],
               redirectTo: 
                 canEditAgenda: {
                   navigationCommands: 'dashboard',
                   navigationExtras: {
                       skipLocationChange: true
                   }
                 
                 },
                 default: 'login'
             }
          }
      }
    },
  ];
  @NgModule({
    imports: [
      RouterModule.forRoot(appRoutes)
    ],
    exports: [
      RouterModule
    ]
  })  

To present usage redirectTo as Object with values as Function in a state definition agenda presented below redirection rules are interpreted as:

  • when user does not have canReadAgenda invoked function returns string representing the state name to which unauthorized user will be redirected
  • when user does not have canEditAgenda invoked function returns object with custom options and params that will be passed along to transited dashboard url
 const appRoutes: Routes = [
    { path: 'home',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
       permissions: {
              only: ['canReadAgenda','canEditAgenda'],
              redirectTo: {
                canReadAgenda: (rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routeStateSnapshot: RouterStateSnapshot) => {
                  return 'dashboard';
                },
                canEditAgenda: (rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routeStateSnapshot: RouterStateSnapshot) => {
                  return {
                      navigationCommands: ['/dashboard'],
                      navigationExtras: {
                          skipLocationChange: true
                      }
                  }
                },
                default: 'login'
            }
        }
      }
    },
  ];
  @NgModule({
    imports: [
      RouterModule.forRoot(appRoutes)
    ],
    exports: [
      RouterModule
    ]
  })

πŸ”₯ Important
Above code is not AOT compatible to make it AOT compatible extract it to function navigationCommands and navigationExtras reserved words. Matching parameter to router.navigate function

export function canReadAgenda(rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routeStateSnapshot: RouterStateSnapshot) => {                                                 
    return 'dashboard';
},

redirectTo: {
    canReadAgenda: canReadAgenda
 
}

Dynamic redirection rules

Similarly to examples showing defining dynamic access to state redirection can also be defined based on any parameters of ActivatedRouteSnapshot and RouterStateSnapshot;

πŸ’‘ Note
Remember to always return state name or object.

const appRoutes: Routes = [
    { path: 'home/:isEditable',
      component: HomeComponent,
      canActivate: [NgxPermissionsGuard],
      data: {
      permissions: {
             only: ['canReadAgenda','canEditAgenda'],
             redirectTo: (rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routerStateSnapshot: RouterStateSnapshot) => {
               if(activateRouteSnapshot.params['id'] === 42){
                 return 'login';
               } else {
                 return 'dashboard'
               }
             }
      }
    },
  ];
  @NgModule({
    imports: [
      RouterModule.forRoot(appRoutes)
    ],
    exports: [
      RouterModule
    ]
  })

πŸ”₯ Important
The code above is not AOT compatible. To make it AOT compatible extract it to a function

export function redirectToFunc(rejectedPermissionName: string, activateRouteSnapshot: ActivatedRouteSnapshot, routerStateSnapshot: RouterStateSnapshot) => {
     if(activateRouteSnapshot.params['id'] === 42){
       return 'login';
     } else {
       return 'dashboard'
     }
   }

redirectTo: redirectToFunc

Implemented Guards

Can Activate Guard

NgxPermissionsGuard implements CanActivate interface, see examples above.

Can Load Guard

NgxPermissionsGuard implements CanLoad Interface. Functionality is the same as canActivate

const appRoutes: Routes = [

  {
    path: 'lazy',
    data: {
      permissions: {
        except: 'ADDDMIN',
      }
    },
    canLoad: [NgxPermissionsGuard],
    loadChildren: 'app/lazy-module/lazy-module.module#LazyModule'
  },
 

];
@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes)
  ],
  exports: [
    RouterModule
  ],
  providers: [
    // CanDeactivateGuard
  ]
})
export class AppRoutingModule {}


 

πŸ”₯ Warning

  • The only difference if you use as a function the parameter is only 1 and its type of Route
{
    path: 'lazy',
    data: {
      permissions: {
         only: (route: Route) => {
                  //logic here
                   return ['MANAGER', "UTILS"]
                  }
      }
    },
    canLoad: [NgxPermissionsGuard],
    loadChildren: 'app/lazy-module/lazy-module.module#LazyModule'
  },

Can Activate Child Guard

NgxPermissionsGuard implements CanLoad Interface. Functionality is the same as canActivate

πŸ”₯ Warning

  • Rules and data must be specified on Child Components not on parent component
const appRoutes: Routes = [
  { path: '',
    component: IsolateComponent,
    canActivateChild: [NgxPermissionsGuard],
    children: [
      {
        path: 'except-should',
        component: AnotherComponent,
        data: {
          permissions: {
            except: 'ADMIN'
          }
        }
      },
      {
        path: 'only-should',
        component: ComeComponent,
        data: {
          permissions: {
            only: 'GUEST'
          }
        }
      },
    ]
  },
];

Common use cases

Two guards when first make request for authorization and gets permissions second checks for permissions

This method only works with angular 4.3.2 or higher see angular/angular#15670

There are a lot of times you have 2 guard one for authorisation when it makes request for permissions and second is permissions guard and you want them to work in chain. To make them work in chain You should use them in a following way:

let routes = [
  { path: '', 
    canActivate: [AuthGuard],
    children: [
      {path: 'component', 
      component: ComponentName, 
      canActivate: [NgxPermissionsGuard],
      data: {
         permissions: {
           only: ['ADMIN', 'MODERATOR'],
           redirectTo: 'another-route'
         }
       }}
    ]
  }
]

Note: Make sure the permission request in chained in auth guard

   canActivate() {
       return authLogin().then((obj) => {
           // or load here if you dont need second request
           // this.permissions.service.loadPermissions(obj.permissions)
          
           return this.authPermissions.getPermissions('url');
       }).then((permissions) => {
           this.permissions.service.loadPermissions(permissions)
       )
   }

| --- |

Development

To generate all *.js, *.d.ts and *.metadata.json files:

$ npm run build

To lint all *.ts files:

$ npm run lint

Thank You

Thank You for using the library and support. HAVE A GREAT DAY!

For google

angular 2 permissions, angular 4 permissions, angular permissions, angular 5 permissions ng2 permissions ng permissions ng-permissions ng2-permissions angular2 permissions angular4 permissions angular 5 permissions

License

MIT Β© Oleksandr Khymenko

ngx-permissions's People

Contributors

alexkhymenko avatar dependabot[bot] avatar georgeknap avatar jkubiszewski avatar jrmlstf avatar kirjs avatar phra avatar sholvabai avatar thekiba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngx-permissions's Issues

CanLoad functionality

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report 
[x] Feature request
[ ] Documentation issue or request

Question

Are you going to provide a service to implement the canLoad function when importing a module with lazy loading? It would be a great help!

can I use 'and' with ngxPermissionsOnly

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[x] Documentation issue or request

Current behavior

it looks to me that

<div *ngxPermissionsOnly="['ADMIN', 'GUEST']">
    <div>You can see this text congrats</div>
</div>

works like or and will show if ADMIN or if GUEST.

Expected behavior

I'm looking for and use case, is it possible with current version?

I imagine it might be like

<div *ngxPermissionsAnd="['canDoAction1', 'canDoAction2']">
    Congrats you can do both actions:
    <div>item 1 <button>action1</button></div>
    <div>item 2 <button>action2</button></div>
</div>

so the area will appear only if user has permission to do both actions

View restriction permissions break on refresh

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

ngxpermissionsOnly shows an element on the first page load, but that item is hidden when the page is refreshed or when you navigate away from a page and then back again.

Expected behavior

ngxPermissionsOnly should show and hide elements consistently regardless of page refresh and navigation

Minimal reproduction of the problem with instructions

  1. Load permissions using addPermission or loadPermissions
  2. Use ngxPermissionsOnly directive in a view to show or hide an element
  3. Navigate to page using ngxPermissionsOnly --> Element is shown since user has correct permissions
  4. Refresh page
  5. Now element is hidden even though user has permissions

Code:
auth.service.ts:

export class AuthService {
	constructor(private ngxPermissionsService: NgxPermissionsService) {
		//...
	}

	//Function called after a user logs in
	public afterSignIn() {
		const permissionNames = ["create-contract", "create-payment", "create-prospect", "modify-contract", "modify-invoiced", "modify-prospect", "modify-quickbooks-reference-id", "modify-sales-actions"];

		// Always return true for testing purposes
		this.ngxPermissionsService.addPermission(allFrontendPermissionNames, (permissionName, permissionStore) => {
			return true;
		});

		//redirect to home component
	}
}

home.component.ts

<ng-template [ngxPermissionsExcept]="['modify-sales-actions', 'create-contract']">
	<div class='row'>
		<div class='col-sm-12'>
			<h1> Perms Test </h1>
		</div>
	</div>
</ng-template>

Environment


Angular version: 4.0.0
ngx-permissions version: 3.0.0

Browser:
- [x] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [x] Firefox version XX
- [x] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
  
  

No provider for InjectionToken USE_PERMISSIONS_STORE

ERROR Error: Uncaught (in promise): Error: StaticInjectorError[InjectionToken USE_PERMISSIONS_STORE]:
StaticInjectorError[InjectionToken USE_PERMISSIONS_STORE]:
NullInjectorError: No provider for InjectionToken USE_PERMISSIONS_STORE!
Error: StaticInjectorError[InjectionToken USE_PERMISSIONS_STORE]:
StaticInjectorError[InjectionToken USE_PERMISSIONS_STORE]:
NullInjectorError: No provider for InjectionToken USE_PERMISSIONS_STORE!
at NullInjector.get (core.js:993)
at resolveToken (core.js:1281)
at tryResolveToken (core.js:1223)
at StaticInjector.get (core.js:1094)
at resolveToken (core.js:1281)
at tryResolveToken (core.js:1223)
at StaticInjector.get (core.js:1094)
at resolveNgModuleDep (core.js:10878)
at NgModuleRef
.get (core.js:12110)
at resolveDep (core.js:12608)
at NullInjector.get (core.js:993)
at resolveToken (core.js:1281)
at tryResolveToken (core.js:1223)
at StaticInjector.get (core.js:1094)
at resolveToken (core.js:1281)
at tryResolveToken (core.js:1223)
at StaticInjector.get (core.js:1094)
at resolveNgModuleDep (core.js:10878)
at NgModuleRef
.get (core.js:12110)
at resolveDep (core.js:12608)
at resolvePromise (zone.js:821)
at resolvePromise (zone.js:785)
at eval (zone.js:870)
at ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:4744)
at ZoneDelegate.invokeTask (zone.js:420)
at Zone.runTask (zone.js:188)
at drainMicroTaskQueue (zone.js:594)
at

Role Based Button Disable !!!!!!!

Hai Alex,

I am using your library is there any possibility for user role Based Button disabled.

Please advice . Using permissionsAuthorized and permissionsAuthorized

Get permissions after page refresh

I do not know if I forgot something, but by forcing the reload of the page, I lose the permissions in memory.
The solution to my problem was to get the permissions saved in the localStorage and after the reload call the loadPermissions([permissions]) method ;
Would that be the best approach?

Guard and Directive use different logical operator

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request

Current behavior

<ng-template [ngxPermissionsOnly]="['ROLE_ADMIN','ROLE_USER']">
    <div>ROLE_ADMIN | ROLE_USER</div>
</ng-template>

View directive is OR-ed (ROLE_USER || ROLE_ADMIN)

{ path: 'quick-quote', component: QuickQuoteStartComponent,
    canActivate: [NgxPermissionsGuard],
    data: { permissions: { only: ['ROLE_USER','ROLE_ADMIN'], redirectTo: loginRedirect} }
  },

Route guard is AND-ed (ROLE_USER && ROLE_ADMIN)..

Expected behavior

They should work the same

Minimal reproduction of the problem with instructions

Environment


Angular version: @angular/cli: 1.4.6
ngx-permissions version: 2.1.1

Component loaded twice

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

When I use lib to restrict access to a component, this component will be loaded twice if access is granted

Expected behavior

The component should be loaded only once.

Minimal reproduction of the problem with instructions

<div *ngxPermissionsOnly="['DEFINE_REPORTING']">
    <hsmt-reporting [siteId]="siteId"></hsmt-reporting>
</div>

With this code I can see that the hsmt-reporting component constructor is run twice if access is granted.

Environment


Angular version: 4.0.3
ngx-permissions version: 2.1.1


Browser:
- [x] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
  

Usage of roles

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

Neither the directives ngxPermissionsOnly, ngxPermissionsExcept, nor except and only with routes work when using roles. Neither the plunker demo is working with roles.

Expected behavior

When user adds roles using their service, from the documentation it seems, they should be appliable as well as permissions added using their service.

Minimal reproduction of the problem with instructions

Go to roles page
https://plnkr.co/edit/n6Wa6hXg0JzI6e050wBt?p=preview

Environment


Angular version: v5.2.1
ngx-permissions version: X.Y.Z


Browser:
- [X] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

Whether I can give variables here without hardcoding the permissions for routes?

let routes = [
{ path: '',
canActivate: [AuthGuard],
children: [
{path: 'component',
component: ComponentName,
canActivate: [NgxPermissionsGuard],
data: {
permissions: {
only: ['ADMIN', 'MODERATOR'],
redirectTo: 'another-route'
}
}}
]
}
]
Here you've hardcoded the permissions only for the routes right? But I want to take the details from the database. Is there any way to load that?

Role Based Component

``

I'm submitting a...

Current behavior

Hi Alex,

I am happy to use your library in project!
Could you help me please with one question?

<myComponent  *ngxPermissionsOnly="'ADMIN'; authorisedStrategy: disabledFunc; unauthorisedStrategy: enableFunc">
         </myComponent>
 public disabledFunc(templateRef: TemplateRef<any>) {
            // I want the button in the component to disable. What should I do?
        }
@Component({
 selector: 'myComponent',
template: `
        <h2>{{title}}</h2>
        <button> <div>123</div></button>
`} 

I want the button in the component to disable. What should I do?

Please release v6 as rxjs 6 has been released and it is not compatible with current version

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ X] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

Does not work with rxjs 6.0

Expected behavior

Minimal reproduction of the problem with instructions

Environment


Angular version: X.Y.Z
ngx-permissions version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

ngx-permissions - NgxPermissionsGuard routing issue redirect to default route.

Current behavior

We have 3 child route and 1 root route

  1. oneadmin/login
  2. twoadmin/login
  3. site/login
  4. app route for root and lazy loading

I used to build angular 4 application with nodejs we have 2 admin panel, 1 site and app.module.ts we used for lazy loading, ngx-permissions, NgxPermissionsGuard.

After the user login from oneadmin they can access every route but if user is in dashboard user can't able to refresh page, if user refresh page it's redirect to http://127.0.0.1:3000.

http://127.0.0.1:3000/oneadmin/dashboard
http://127.0.0.1:3000/oneadmin/profile

here is route code

const oneadminroutes: Routes = [ 
  {
    path: 'oneadmin', pathMatch: 'full', redirectTo: 'oneadmin/login',
  },
  {
    path: 'oneadmin/login', component: LoginComponent,
  },
  {
    path: 'oneadmin',
    component: OneAdminComponent,
    pathMatch: 'prefix',
    children: [
      {
        path: 'dashboard',
        component: DashboardComponent,
        pathMatch: 'prefix',
        canActivate: [NgxPermissionsGuard],
        data: {
          permissions: { only: ['role1', 'role2', 'role3'] }
        }
      },
      {
        path: 'profile',
        component: UserProfileComponent,
        canActivate: [NgxPermissionsGuard],
        data: {
          permissions: { only: ['role1', 'role2', 'role3']  }
        }
      },
 ]
  }
];
export const OneadminRoutingModule: ModuleWithProviders = RouterModule.forChild(oneadminroutes);

Expected behavior

if user refresh the page it want redirect to to anywhere just stay them in to current page.
http://127.0.0.1:3000/oneadmin/dashboard

Environment


Angular version :
Angular CLI: 1.6.1
Node: 8.9.1
OS: linux ia32
Angular: 5.1.1
... animations, common, compiler, compiler-cli, core, forms
... http, platform-browser, platform-browser-dynamic
... platform-server, router

@angular/cli: 1.6.1
@angular/language-service: 4.4.6
@angular/tsc-wrapped: 4.4.6
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.1
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.6.2
webpack: 3.10.0

ngx-permissions version: ^3.0.0

Browser:
- [ ] Chromium (Ubuntu desktop) : version Version 62.0.3202.89 (Official Build) Built on Ubuntu , running on Ubuntu 16.04 (32-bit)
- [ ] Firefox version (Ubuntu desktop) : 57.0.1 (32-bit)

User has permission to current route

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[x] Documentation issue or request

Current behavior

First thank you for this! It was just what we were looking for. We have functionality where a user can impersonate another role. I’m wondering how I’d go about checking to see if if the user has permission to the current route?

Expected behavior

Minimal reproduction of the problem with instructions

Environment


Angular version: X.Y.Z
ngx-permissions version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

add disclaimer about insecure client permissions

hi,

i think that you should cite in the readme that this library should only be used to simplify the client side workflow but not as a security measure because client side checks are not secure at all.

Usage of roles

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[x] Documentation issue or request

Current behavior

Currently, I do not understand the value of using roles. All directives, guards work on concept of permissions only.

May be I am missing some critical information. Hope to understand the same better. e.g. I can get role and permissions object from backend system. I am able to create roles and corresponding permissions using the APIs described. But can I really use roles in the system? I am right now not sure.. because usage of roles in templates, guards etc is not clearly explained at the moment.

Expected behavior

Clear example or documentation on using roles. I am hoping that roles would allow me a shortcut in same directive / guards to specify 10 different permissions.

Can't access component variables

Hello guys!
I have kind of problem, when I can't access to component class fields from my ng-template's.
Could you help me, how could i solve this problem?

Here is code example

<ng-template [ngxPermissionsOnly]="'PERMISSION'"
             [ngxPermissionsOnlyThen]="allowAccess"
             [ngxPermissionsOnlyElse]="denyAccess">
</ng-template>`


<ng-template #allowAccess>
    <button type="submit" class="btn btn-primary">{{ componentVar }}</button>
</ng-template>

<ng-template #denyAccess>
    <button disabled type="submit" class="btn btn-primary">{{ componentVar }}</button>
</ng-template>

And text where should be componentVar is empty

How can use "canDoSomething" permission without role into the view ?

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[x] Documentation issue or request

Current behavior

I'm not sure if I understood well but how can I use my permissions into the view ? I've got this permission : "canEdit" and I would like to do something like that and I don't know if it's possible :

<ng-template [ngxPermissionsOnly]="['ROLE_USER']" OR "canEdit"> <button fxHide.xs="true" fxShow.gt-sm="true" mat-raised-button color="primary" (click)="redirect('items/add')"><i class="material-icons">add</i>Add item</button> </ng-template>

Is it possible to use the permission and not the role ?

Thank you :)

Expected behavior

Minimal reproduction of the problem with instructions

Environment


Angular version: X.Y.Z
ngx-permissions version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

TypeError: rxjs_Observable.Observable.merge(...).mergeAll is not a function

I'm submitting a Bug report

my code in my component (bandeau-qoq.component.ts)

import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Router } from '@angular/router';
...
import { NgxPermissionsService } from 'ngx-permissions';

@Component({
  selector: 'app-bandeau-qoq',
  templateUrl: './bandeau-qoq.component.html',
  styleUrls: ['./bandeau-qoq.component.less']
})
export class BandeauQoqComponent implements OnInit {
  public isCollapsed = false; // Indique si le bandeau doit Γͺtre rΓ©duit.

  // EnumΓ©ration 'Γ©tats des dossiers'
  private etatEnum = EtatEnum;

  private dossierService: DossierService; // Rendre le service accessible dans la vue
  private quoi: TypeSignalement;
  private ou: Regate;
  private quand: QuandForm;
  // Detecter la valeur prΓ©cΓ©dente de la version de dossier
  // Nous aide dans la gestion du cache des donnΓ©es globales
  @Input() isEditMode: boolean;
  @Input() dossier: Dossier;

  @Output() changeSection: EventEmitter = new EventEmitter();
  @Output() validationGlobale: EventEmitter = new EventEmitter();

  constructor(private dossierServiceInj: DossierService,
    private router: Router,
    private app: AppComponent,
    private permissionsService: NgxPermissionsService) {
    this.dossierService = dossierServiceInj;
  }

  ngOnInit() {
    console.log("permission :");
    const perm = ["ADMIN", "EDITOR"];

    this.permissionsService.loadPermissions(perm);
    console.log(this.permissionsService.getPermissions());

it's works fine : i can get the permissions in the console

my code in the template (bandeau-qoq.component.html)

<ng-container *ngxPermissionsOnly="['ADMIN']">

Current behavior

When i use a directive in the template, the following error appears in the console (chrome)

Error: Uncaught (in promise): TypeError: rxjs_Observable.Observable.merge(...).mergeAll is not a function
TypeError: rxjs_Observable.Observable.merge(...).mergeAll is not a function
    at NgxPermissionsService.hasArrayPermission (ngx-permissions.umd.js:189)

Environment


Angular version: 4.0.0
ngx-permissions version: 2.1.0


Browser: Chrome (desktop) version 61.0.3163.100 (Build officiel) (32 bits)

How to listen permissionsAuthorized event

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[x] Documentation issue or request

Current behavior

I'm trying to capture the permissionsAuthorized event that is thrown when the permission is granted, but the method that I have linked to the event is not executed.

Expected behavior

I need to listen when permission is granted.

Minimal reproduction of the problem with instructions

Template side:
<li *ngxPermissionsOnly="'canAccessSettings'" (permissionsAuthorized)="reloadMenu()">Item<li>

Component side:
public reloadMenu($event): void { console.log('reloadMenu', $event); }

Environment


Angular version: 5.2.5
ngx-permissions version: 4.1.0


Browser:
- [X] Chrome (desktop) version 64.0.3282.186
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

TestModule

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ x] Feature request
[ ] Documentation issue or request

Current behavior

No test support.

Expected behavior

It would be nice with mock module or the likes, so that:

  • the directives would be valid (and hence the test can be setup)
  • a mock permission evaluation, which would always allow access

Environment


Angular version: 5.2.1
ngx-permissions version: 3.1.0

Browser:
All

Move plunker to statblitz

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

Expected behavior

Minimal reproduction of the problem with instructions

Environment


Angular version: X.Y.Z
ngx-permissions version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

Issue on refresh page with Implemented Guards

I have the following issue i save my jwt token in the local storage now on page refresh i am retrieving the users permissions and roles from an api but it seems the guard is firing before the permissions and roles have been loaded. so my question is how can i wait for the roles and permissions to be resolved before firing the NgxPermissionsGuard

Issue with get permissions

I am loading the permissions in AppComponent as per the documentation and I am boot strapping the same component in app.module.ts.

When I am trying to get permissions in any other component then this returns empty object.

I have also added the NgxPermissionsService in providers array in app.module.ts

I have quick question i have loaded my roles via the RolesService how do i use or check against them say in the html template. For permissions it's simple by using the Permission directive. but for roles what do you use?

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

Expected behavior

Minimal reproduction of the problem with instructions

Environment


Angular version: X.Y.Z
ngx-permissions version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

rxjs_Observable.Observable.merge(...).mergeAll(...).first(...).toPromise is not a function

Hi!
I have this error after update angular version

TypeError: rxjs_Observable.Observable.merge(...).mergeAll(...).first(...).toPromise is not a function
at NgxPermissionsService.hasArrayPermission (ngx-permissions.umd.js:211)
at NgxPermissionsService.hasPermission (ngx-permissions.umd.js:115)
at NgxPermissionsDirective.validateOnlyPermissions (ngx-permissions.umd.js:471)
at SafeSubscriber._next (ngx-permissions.umd.js:433)
at SafeSubscriber.__tryOrSetError (vendor.js?v=al17c1S52F9ckakALoRfjx9ZZ0m1LMiMq-rrE1oO-GM:10843)
at SafeSubscriber.next (vendor.js?v=al17c1S52F9ckakALoRfjx9ZZ0m1LMiMq-rrE1oO-GM:10783)
at Subscriber._next (vendor.js?v=al17c1S52F9ckakALoRfjx9ZZ0m1LMiMq-rrE1oO-GM:10721)
at Subscriber.next (vendor.js?v=al17c1S52F9ckakALoRfjx9ZZ0m1LMiMq-rrE1oO-GM:10685)
at SkipSubscriber._next (skip.js:53)
at SkipSubscriber.Subscriber.next (vendor.js?v=al17c1S52F9ckakALoRfjx9ZZ0m1LMiMq-rrE1oO-GM:10685)

Have somebody any ideas to resolve this issue?

Environment


Angular version: 5.1.0-rc.1
ngx-permissions version: ^3.0.0


Browser:
- [x] Chrome (Android) version XX

Correct Implementation of load permissions after login (authentication)

I have an implementation question.
I have app, where auth.service is loading permissions (roles) after authentication.
After I call loadPermissions in every component or module, i need to check auth.
But I have feeling, that this is not correct way. You load in your example app (hardcoded) permission in app.component and I am wondering, where is correct place to load permissions, after authentication, without needed to load them every time (in every component etc) i need to check perm.
Can you please give me an advise ?

3.2.0 is not including new NgxPermissionsAllowStubDirective, NgxPermissionsRestrictStubDirective with NgxPermissionsModule.

I'm submitting a...


[X] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

Version 3.2.0 is not including new NgxPermissionsAllowStubDirective, NgxPermissionsRestrictStubDirective with the NgxPermissionsModule.

Expected behavior

I am sure you just forgot to add this?

Minimal reproduction of the problem with instructions

Environment



Browser:
- [X] Chrome (desktop) version XX
- [X] Chrome (Android) version XX
- [X] Chrome (iOS) version XX
- [X] Firefox version XX
- [X] Safari (desktop) version XX
- [X] Safari (iOS) version XX
- [X] IE version XX
- [X ] Edge version XX

*ngFor

Hi,

it seems, the directives (eg. ngxPermissionsOnly) cannot be used within an "*ngFor" loop.

Example:
...*ngFor="let child of children" ..

{{child.value}}

In the example above, {{child.value}} does not get rendered - it seems to be shadowed by your Directive.

Can you confirm?
Is it by intent?

Thx a lot,

raven

HELP : When refresh page its redirect on dashboard

i have check permission on route. its working file. thanks for your time.
my issue is i load permission list when application startup.
for ex
my current page http://localhost:4200/#/app/users. now i refresh page redirect on dashboard instead of stay on current page. but i don't know how to resolve this issue. i also try to-load-permissions-before-application-start-up
.
please help me. Thanks in advance

 component: UsersComponent,
        children: [
            {
                path: '',
                component: UsersListComponent,
                pathMatch: 'full',
                canActivate: [NgxPermissionsGuard],
                data: {
                    permissions: {
                        only: 'read_user',
                        redirectTo: ConfigConstant.DEFAULT_ROUTE
                    },
                    title: 'Users Β· Life AI'
                }
            },

Angular version:4.0.2
ngx-permissions version: ^1.0.0

Unable to get directive to work, Angular 6

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ x ] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

When following the examples from the setup guide, we are simply including NgxPermissionsModule.forRoot() in our imports inside our app.module.ts, we then have a nav menu component which we are trying to use the directives on to show and hide anchor links. We are receiving the error:

"Property binding ngxPermissionsOnly not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations"

and

"Can't bind to 'ngxPermissionsOnly' since it isn't a known property of 'a'"

Is there a step we have missed in importing/including this in our project?

Expected behavior

Desired result is that the directive works without errors

Minimal reproduction of the problem with instructions

Follow steps above in current behavior.

Environment


Angular version: 6.0.0
ngx-permissions version: 5.0.0? (whichever is newest in npm)


Browser:
- [x ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

Support for loading the role / permission during the route guard check

  • make sure you have the correct permission
  • go to a url with permission guard on it using that permission
  • refresh the page
    ==> In my use case, there is no way I can load the permission fast enough because I cannot load the permission at application start. I need a way to be able to check permission with the server using the permission guard.

I'm submitting a...


[X ] Feature request

Current behavior

Not currently possible

Expected behavior

Environment


Angular CLI: 1.7.4
Node: 9.11.1
OS: darwin x64
Angular: 5.2.10
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router
... service-worker

@angular/cli: 1.7.4
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.3.2
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.2
@schematics/angular: 0.3.2
@schematics/package-update: 0.3.2
typescript: 2.6.2
webpack: 3.11.0
ngx-permissions version: 4.1.0

can we build hierarchy?

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[x] Documentation issue or request

Expected behavior

it's possible to build hierarchical rules?

you can: 
<div *ngxPermissionsOnly="['CREATE']">
    <span class="btn">create new</span>
</div>
<div *ngxPermissionsOnly="['READ']">
    <span class="btn">view</span>
</div>
<div *ngxPermissionsOnly="['UPDATE']">
    <span class="btn">edit</span>
</div>
<div *ngxPermissionsOnly="['DELETE']">
    <span class="btn">delete</span>
</div>

which should:
show all 4 buttons in case you have DELETE role/permission - CRUD
show 3 buttons in case you have UPDATE role/permission CRU
show 2 buttons in case you have Create/Read role/permission CR
show 1 button in case you have Read role/permission R

    this.persmissionService.addPermission('READ');
    this.rolesService.addRole('CREATE', ['READ'])
    this.rolesService.addRole('UPDATE', ['CREATE'])
    this.rolesService.addRole('DELETE', ['UPDATE'])

in other words considering this hierarchy delete > update > create > read
will the div below show up if user has "DELETE" permission?

<div *ngxPermissionsOnly="['READ']">
    <span class="btn">view</span>
</div>

or it can be achieved by repeating

    this.rolesService.addRole('DELETE', ['CREATE', 'READ', 'UPDATE'])
    this.rolesService.addRole('UPDATE', ['CREATE', 'READ'])
    this.rolesService.addRole('CREATE', ['READ'])

Role based permmisions

Hai ,

I am using ngx permissions library . i create role base navigation menu but meanwhile
not able to work role based permmisons button view update is there possibility meand please explain

Override NgxGuardPermissions

Hello, everyone!

I would like to know could I override the NgxGuardPermissions? I just want to make logout if permission is denied.

Thanks!

v5.0.0-rc.0 does not work with rxjs6

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

v5.0.0-rc.0 does not work with rxjs6

Expected behavior

Minimal reproduction of the problem with instructions

Environment


Angular version: X.Y.Z
ngx-permissions version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

Permissions doesn't persist

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

Hi,Thank you all for your great job, I'm using this library for a web application that support multiple roles each role has different permissions my problem is that the permissions that i load doesn't persist in the browser a soon as i refresh the page the getPermissions function return an empty object
PS: I'm using ngx-permissions 4.0.0 instead of 5.0.0 because i get this error rxjs.merge is not a function

Expected behavior

The permissions should persist even when we change the navigation

Minimal reproduction of the problem with instructions

Environment


Angular version: 5.1.0
ngx-permissions version: 4.0.0


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

Observable.merge AOT compilation

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

If i compile project with aot (--prod) flag. I got error in browser console Observable.merge is not a function in validateExceptOnlyPermissions

Expected behavior

Minimal reproduction of the problem with instructions

Environment


Angular version: 5.2.0
ngx-permissions version: 3.2.3


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

Is there any possibility for strict roles with shared permission?

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[x] Documentation issue or request

Current behavior

Validation passes if permission is common for different roles

Expected behavior

Need to have strict permission set validation.

ROLE_A: ['perm_a', 'perm_b']
ROLE_B: ['perm_a]

Need to show element only to ROLE_A and completely hide to ROLE_B.

Minimal reproduction of the problem with instructions

Environment


Angular version: 5.1.0
ngx-permissions version: 4.1.0


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

loadPermissions not removing old permissions

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request

Current behavior

In the Multiple Permissions section of the docs it states that loadPermissions "will remove older permissions and pass only new"

Expected behavior

loadPermissions should remove older permissions and replace with the new

Minimal reproduction of the problem with instructions

this.ngxPermissionsService.loadPermissions(['admin', 'test']);
this.ngxPermissionsService.loadPermissions(['another', 'random']);
// 'admin' and 'test' permissions still exist

Ownership-based access

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[X] Documentation issue or request

Current behavior

How to implement the ownership-based access control, allowing for example only the owner to edit
a specific resource?

Expected behavior

I would allow to edit a resource

  • all the administrators
  • the specific owner (cannot filter by role, need to filter comparing the current user with the user pointed as owner from the resource)

Unauthorized Strategies

Hi, Alex! We are happy to use your library in our project!

Could you help me please with one question?
I need to disable the button when the user hasn't required permissions and now the only possibility to achieve this, as I understood, is to clone template of the button, make it disabled and pass it to elseBlock.

Is it possible to avoid such of code cloning and provide kind of predefined Strategies of actions to elements with which user has no rights to interact?

Thank you for your attention!

rxjs.merge is not a function at NgxPermissionsDirective.validateExceptOnlyPermissions (ngx-permissions.umd.js:632)

I'm submitting a...

update angular 4.2 to 5.2.8 and update ngx-permisison package but not working a

Current behavior

Got error

 rxjs.merge is not a function
    at NgxPermissionsDirective.validateExceptOnlyPermissions (ngx-permissions.umd.js:632)
    at NgxPermissionsDirective.ngOnInit (ngx-permissions.umd.js:611)
    at checkAndUpdateDirectiveInline (core.js:12411)
    at checkAndUpdateNodeInline (core.js:13935)
    at checkAndUpdateNode (core.js:13878)
    at debugCheckAndUpdateNode (core.js:14771)
    at debugCheckDirectivesFn (core.js:14712)
    at Object.eval [as updateDirectives] (AppSidenavComponent.html:22)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:14697)
    at checkAndUpdateView (core.js:13844)

Expected behavior

it should be work fine with angular 5.2.8

Environment


Angular version: 5.2.8
ngx-permissions version: X.Y.Z
 rxjs: 5.5.6

Browser:
- [ ] Chrome (desktop) version XX

redirectTo with query parameters

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[x] Documentation issue or request

Current behavior

It's not an issue, just a question : I would like to know how can I redirect on page with the redirectTo command into a routing.

Expected behavior

{
			path: 'test/:id',
			component: testComponent,
			canActivate: [NgxPermissionsGuard],
			data: {
				permissions: {
					only: ["ROLE_USER"],
					redirectTo: ['/login'] // would like to redirect to /login?not_authorized=1 
				}
			}
		},

Minimal reproduction of the problem with instructions

Environment


Angular version: 5.3.2
ngx-permissions version: 4.1.0


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

How can i use NgxPermissionsAllowStubDirective ? Can you please provide the plunker ?

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[ x ] Documentation issue or request

Current behavior

Normally it is working fine but in the unit test i am not able to bypass the directive condition. How can i bypass it

Expected behavior

Minimal reproduction of the problem with instructions

<ng-container *ngxPermissionsOnly="['SUBSCRIPTION_OWNER','USER_MANAGER']">
<i *ngIf="!userRole?.isLastOwner" class="fa fa-user-times grid-icon" >

now in unit test case i have provided the
permissionservice.Loadpermission("permissions here")

But still i am not able to get the I tag

Environment


Angular version: 5
ngx-permissions version: X.Y.Z


Browser:
- [ x] Chrome (desktop) version XX
- [ x] Chrome (Android) version XX
- [ x] Chrome (iOS) version XX
- [ x] Firefox version XX
- [ x] Safari (desktop) version XX
- [ x] Safari (iOS) version XX
- [ x] IE version XX
- [ x] Edge version XX

Always check by lower level of role

Hi, i extend my congratulations for this component. But when i have a user with role admin and role editor and want to access a functionality with role admin the user cant not access because it have a role with lower permission. thanks again

ngxPermissionsOnly not working in template

How I used -

<p ngxPermissionsOnly="GUEST">Members online</p>

Permissions set in component and added role as below -

NgxPermissionsService.loadPermissions(["A"]); NgxRolesService.addRole('ADMIN', ['A'] );

Code added in component to check role is added in permission or not -

let roles = NgxRolesService.getRoles();
NgxRolesService.roles$.subscribe((data) => { console.log(data); })

console.log returns below -

{ "ADMIN": { "name": "ADMIN", "validationFunction": [ "A" ] } }

Can you replicate this issue and let me know possible solution for this.

Tried following possibilities -

<p ngxPermissionsOnly="'GUEST'">Members online</p>
<p ngxPermissionsOnly="'[GUEST']">Members online</p>

but still GUEST permission's p tag is visible or even directive not readable in template.

Component with onpush requires detect changes

Hi,

When using the ngxPermission directives inside compoent that uses OnPush strategy
the elements are not rendered correctly, if i invoke the changeDetectorRef.detectchanges manully
than everything is fine.

The strange issue is that if i have nested levels of permission directives inside the same component
i need to invoke the changeDetectorRef.detectchanges for each nesting level.

Can you please advise how to solve this ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.