Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In my Angular 4 project I would like to work with permissions, which I get from an API. Permissions are saved as array with ids. Some single elements like user or blog post have property with allowed permissions, which allow or not allow actions like edit or delete, as array with ids.

What's the best way to check and to handle permissions in Angular 4 projects? Has Angular some out of the bos solutions for permissions handling? Can somebody give me ideas for realization of permissions handling, if Angular doesn't have some out of the box solution?

like image 292
Gregor Doroschenko Avatar asked Aug 14 '17 09:08

Gregor Doroschenko


People also ask

How to deal with permissions in angular apps?

When using these two concepts to deal with permissions in your application, you’ll have duplicated code in your directive and in your guard. A good way to deal with this is to abstract everything to a service. Services are an incredible way to share relevant information among different classes in your Angular app.

What are services in angular and how to use them?

Services are an incredible way to share relevant information among different classes in your Angular app. You can inject your service using dependency injection to your guard and directive, this way having a centralized place to access your user data and calculate if the user should see the specific part of the system they are trying to access.

How does permissionservice read the permissions of the user?

When the backend sends the permissions of the logged in user to the client sides, the PermissionService will read the permissions and check whether the requested URL can be accessed by the user. For each url in our routing file the required permission is indicated.

How to hide or disable an element based on permission in angular?

To hide or disable an element based on permission, use the following code to create two directives. This will enable the Angular templates to use this syntax: Angular includes a feature to prevent navigation to a page by implementing a CanActivate guard and specifying it in the route configuration.


2 Answers

like Rahul comment says the one solution out of the box is more likely what you want are Guard ..

Remember guard are only for ROUTING .. so only to check if a user can access a route or not .. but not to display single element in a component based on roles or whatever .. for that i suggest to you to use *ngIf or show to render/display or not some UI elements ...

For one Guard based on Roles (not only if use is auth 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 like:

{
        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'] }
          }
        ]
      }
like image 130
federico scamuzzi Avatar answered Nov 16 '22 04:11

federico scamuzzi


You can try to use ngx-permissions library for controlling of permissions in your angular application. The benefits it will remove elements from DOM. Example of loading 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.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);
    })
  }
}

Usage 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>
like image 40
alexKhymenko Avatar answered Nov 16 '22 03:11

alexKhymenko