What is the best way to work with permissions in Angular 4?

In my Angular 4 project, I would like to work with the permissions that I get from the API. Permissions are saved as an array with identifiers. Some elements, such as a user or blog post, have a property with permissions that allow or do not allow actions such as editing or deleting, such as an array with identifiers.

What is the best way to check and handle permissions in Angular 4 projects? Does Angular have some of the bos solutions for handling permissions? Can someone give me ideas for implementing permission processing if Angular does not have any of the ready-made solutions?

+6
source share
4 answers

as a comment Rahula says that one solution out of the box is more likely that you want a Guard ..

Remember that protection is only for ROUTING .. so that only to check whether the user can access the route or not ... but not display one element in the component based on roles or something else .. for this I suggest you use *ngIf or show mapping / mapping or some user interface elements ...

For a single Role-based Guard (not only if auth is used or not) .. you can do something like:

 import { Injectable } from "@angular/core"; import { AuthService, CurrentUserService } from "app/shared/services"; import { Router, RouterStateSnapshot, ActivatedRouteSnapshot, CanActivate } from "@angular/router"; import { AspNetUsersDTO } from "app/shared/models"; import { Observable } from "rxjs/Rx"; @Injectable() export class RoleGuard implements CanActivate { constructor(private authService: AuthService, private _currentUser: CurrentUserService, private router: Router) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> { return new Promise<boolean>((resolve, reject) => { if (!this.authService.isLoggedIn()) { resolve(false); return; } var currentUser: AspNetUsersDTO = new AspNetUsersDTO(); this._currentUser.GetCurrentUser().then((resp) => { currentUser = resp; let userRole = currentUser.roles && currentUser.roles.length > 0 ? currentUser.roles[0].toUpperCase() : ''; let roles = route && route.data["roles"] && route.data["roles"].length > 0 ? route.data["roles"].map(xx => xx.toUpperCase()) : null; if (roles == null || roles.indexOf(userRole) != -1) resolve(true); else { resolve(false); this.router.navigate(['login']); } }).catch((err) => { reject(err); this.router.navigate(['login']); }); }); } canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> { return new Promise<boolean>((resolve, reject) => { if (!this.authService.isLoggedIn()) { resolve(false); return; } var currentUser: AspNetUsersDTO = new AspNetUsersDTO(); this._currentUser.GetCurrentUser().then((resp) => { currentUser = resp; let userRole = currentUser.roles && currentUser.roles.length > 0 ? currentUser.roles[0].toUpperCase() : ''; let roles = route && route.data["roles"] && route.data["roles"].length > 0 ? route.data["roles"].map(xx => xx.toUpperCase()) : null; if (roles == null || roles.indexOf(userRole) != -1) resolve(true); else { resolve(false); this.router.navigate(['login']); } }).catch((err) => { reject(err); this.router.navigate(['login']); }); }); } } 

And then you can use in your routing, for example:

 { path: 'awards-team', component: AwardsTeamComponent, canActivateChild: [RoleGuard], children: [ { path: 'admin', component: TeamComponentsAdminComponent, data: { roles: ['super-admin', 'admin', 'utente'] } }, { path: 'user', component: TeamComponentsUserComponent, data: { roles: ['utente'] } } ] } 
+7
source

You can try using the ngx-permissions library to manage permissions in your angular app. Benefits that it will remove from the DOM. Permission loading example

 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.css'] }) 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); }) } } 

Use in templates

 <ng-template [ngxPermissionsOnly]="['ADMIN']" (permissionsAuthorized)="yourCustomAuthorizedFunction()" (permissionsUnauthorized)="yourCustomAuthorizedFunction()"> <div>You can see this text congrats</div> </ng-template> <div *ngxPermissionsOnly="['ADMIN', 'GUEST']"> <div>You can see this text congrats</div> </div> <div *ngxPermissionsExcept="['ADMIN', 'JOHNY']"> <div>All will see it except admin and Johny</div> </div> 
+4
source

From my personal point of view, getting permission from the API is the best solution for user rights. In addition to checking permission using the canActivate attribute in Router, I like to use verification in the navigation interceptor. Since when checking incorrect permissions, the URL will be saved instead of the local URL: 42000 /#/.../ permission-denied

Here is my code:

In the template

  <ng-template [ngIf]="!loading" [ngIfElse]="loadingView"> <router-outlet *ngIf="canView"></router-outlet> <app-permission-denied *ngIf="!canView"></app-permission-denied> </ng-template> <app-loading #loadingView></app-loading> 

In component

 import { Component, OnInit} from '@angular/core'; import { Router, // import as RouterEvent to avoid confusion with the DOM Event Event as RouterEvent, NavigationStart, NavigationEnd, NavigationCancel, NavigationError } from '@angular/router' import { Title } from '@angular/platform-browser'; import { DataService } from '../core/service/data.service'; import { NotificationService } from '../core/service/notification.service'; @Component({ selector: 'app-main', templateUrl: './main.component.html', styleUrls: ['./main.component.css'] }) export class MainComponent implements OnInit{ // Sets initial value on first load loading: boolean = true; canView: boolean = false; haveErr: boolean = false; constructor(private renderer: Renderer2, private router: Router, private _dataService: DataService, private titleService: Title, private _notificationService: NotificationService) { this.router.events.subscribe((event: RouterEvent) => { this.navigationInterceptor(event) }) } ngOnInit() { } navigationInterceptor(event: RouterEvent): void { if (event instanceof NavigationStart) { this.loading = true; this.canView = false; } if (event instanceof NavigationEnd) { //get permission user by pass function ID here... let functionId = this.getDataRouter(this.router, "function"); if (functionId != null) { this._dataService.get('your_api_to_check_permission_with_functionId' + functionId).subscribe( (data) => { if (data && data.CanRead) { this.canView = true; let title = this.getDataRouter(this.router, "title"); this.titleService.setTitle(title); } else { this.canView = false; this.titleService.setTitle('Permission denied'); } this.loading = false }, (err) => { this._dataService.handleError(err); }); } else { this.loading = false; this.canView = true; this._notificationService.printErrorMessage('Dev: please provide function Id to check permission'); } } // Set loading state to false in both of the below events to hide in case a request fails if (event instanceof NavigationCancel) { this.loading = false } if (event instanceof NavigationError) { this.loading = false } } getDataRouter(router, name) { var root = router.routerState.snapshot.root; while (root) { if (root.children && root.children.length) { root = root.children[0]; } else if (root.data && root.data[name]) { return root.data[name]; } else { break; } } return null; } } 

In the router module

 const mainRoutes: Routes = [ { path: 'user', loadChildren: './system/user/user.module#UserModule', data: { function: "USER" } }, { path: 'function', loadChildren: './system/function/function.module#FunctionModule', data: { function: "FUNCTION" } } ] 
0
source

The best way to offer you this is to use the Router Guard provided by Angular.

The following links may help you get started:

router security alligator

Guard Medium Router

0
source

Source: https://habr.com/ru/post/1270846/


All Articles