From my personal point of view, get permission from API is optimal solution for user rights.
In addition to checking permission by using canActivate attribute in Router, I like to use checking in navigation interceptor. Because it will keep the url when checking incorrect permissions instead of url localhost:42000/#/.../permission-denied
Here is my code:
In 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 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" } }
]