I have used angular2 and laravel 5.3 in my project. in laravel when user logged in server will be send the permissions of the user to handle authorization in angular. so I wrote a guard to protect routes from users that cannot access.
here is my guard class code:
export class AccessGuard implements CanActivate{
permissions;
currentRoute;
constructor(private authService:AuthService,private router:Router){
this.permissions = this.authService.getPermissions();
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
return this.checkHavePermission(state.url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){
return this.checkHavePermission(state.url);
}
private checkHavePermission(url){
switch (true) {
case url.match(/^\/panel\/users[\/.*]?/):
return this.getPermission('user.view');
case url.match(/^\/panel\/dashboard/):
return true;
case url.match(/^\/panel\/permissions/):
return this.getPermission('permissions.manager');
case url.match(/^\/panel\/candidates[\/.*]?/):
return this.getPermission('candidate.view');
}
}
getPermission(perm){
for(var i=0;i<this.permissions.length;i++){
if(this.permissions[i].name == perm ){
return true;
}
}
return false;
}
}
Now that the routes are secured I wondering that how can I access the user permission inside component class. Because sometimes user can access to a route but he can't see a specific part of dom. how can I handle this kind of situation?
You should store the permissions in the service itself instead of in the guard.
So when the use authenticates, you store the permission in a property of the Authentication Service. Then in the guard, you call the this.authService.<property>
to use the permission. In any other component, you can do the same, this.authService.<property
> to get the user's permission level
Since the service will be passed around as a singleton, all components will have access to the same property.
Based on the @Dave V response, you can implement your own "can" service which makes a little the code more readable. For example:
@Injectable()
export class UserCan {
constructor (private _auth: AuthService)
{
}
public canDoWhatever()
{
return (this._auth.roles.indexOf("Whatever") > -1);
}
}
And in your Component
s you can inject it:
export class YourComponent {
private canDoWhatever: boolean;
constructor(private _userCan: UserCan) {
this.canDoWhatever = _userCan.canDoWhatever();
}
}
And finally in your html:
<div *ngIf="canDoWhatever">
For somebody who is looking for the library, you can check out ngx-permissions. It will remove an element from DOM, lazy module compatible, isolated module compatible, else then syntax is supported.
Add library
@NgModule({
imports: [
BrowserModule,
NgxPermissionsModule.forRoot()
],
})
export class AppModule { }
Load permissions
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
<div *ngxPermissionsOnly="['ADMIN', 'GUEST']">
<div>You can see this text congrats</div>
</div>
For better documentation, visit wiki page.