Permission and roles based access control for your angular(angular 2,4,5,6,7,8+) applications(AOT, lazy modules compatible)
- This library is PROHIBITED to use with russians projects or russians or belarusians
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.
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.
You can test library in Plunker
I'm working on tutorial for the library will add more video with time. This is my first videos YouTube
If You have chance please support on patreon for more open source ideas
Some functionality is missing visit wiki-page
To install this library, run:
$ npm install ngx-permissions --save
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.
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
You can see this text congrats
<ng-template ngxPermissionsOnly="ADMIN">
You can see this text congrats
</ng-template>
<ng-template [ngxPermissionsExcept]="['JOHNY']">
All will see it except JOHNY
</ng-template>
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.
:bulb: Note
It's a good convention to start permission with a verb and combine them with resource or object, so permissions likereadDocumentsorlistSongsare meaningful and easy to understand for other programmes. Notice that they are named lowerCamelCase for easy differentiation form roles.:skull: 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!
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.
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();
});
}
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;
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');
And to get all user permissions use method getPermissions or use Observable permissions$:
var permissions = NgxPermissionsService.getPermissions();
NgxPermissionsService.permissions$.subscribe((permissions) => {
console.log(permissions)
})
Make sure you are familiar with: - Managing permissions
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.
:bulb: Note
It's a good convention to name roles with UPPER_CASE, so roles likeACCOUNTANTorADMINare easier to distinguish from permissions.
Similarly to permissions we are gonna use here RolesService that exposes addRole allowing to define custom roles used by users in your application.
```typescript [...]
NgxRolesService .addRole('ROLE_NAME', ['permissionNameA', 'permissionNameB', 'permissionNameC', ...])
NgxRolesService.addRole('Guest', () => { return this.sessio
$ claude mcp add ngx-permissions \
-- python -m otcore.mcp_server <graph>