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?
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.
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.
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.
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.
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'] }
}
]
}
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With