Skip to content

Instantly share code, notes, and snippets.

@btroncone
Last active April 10, 2022 06:44
Show Gist options
  • Star 47 You must be signed in to star a gist
  • Fork 24 You must be signed in to fork a gist
  • Save btroncone/cebec10b89540f5501dd to your computer and use it in GitHub Desktop.
Save btroncone/cebec10b89540f5501dd to your computer and use it in GitHub Desktop.
Angular 2 application role access decorator, wrapping built in CanAccess functionality. Prevents view transitions when user roles are not appropriate.
import { Injectable } from 'angular2/core';
import { Storage } from './storage';
import { CurrentUser } from '../interfaces/common';
@Injectable()
export class Authentication{
private _storageService : Storage;
private _userKey : string = "CURRENT_USER";
constructor(storageService : Storage){
this._storageService = storageService;
}
authenticate(name : string, password: string){
return new Promise((resolve, reject) => {
setTimeout(() => {
this.currentUser = {
name,
roles : ['ADMIN']
};
resolve(true);
}, 100);
});
}
logOut(){
this._storageService.removeStorage(this._userKey);
}
get userRoles() : Array<string> {
const user = this._storageService.getStorage(this._userKey);
return user ? user.roles : [];
}
get currentUser() : CurrentUser {
return this._storageService.getStorage(this._userKey);
}
set currentUser(user : CurrentUser){
this._storageService.setStorage(this._userKey, user);
}
}
import { Component } from 'angular2/core';
import { Roles } from '../decorators/roles';
@Component({
selector: 'home',
template: `<h1>{{title}}</h1>`
})
@Roles('ADMIN')
export default class Home{
title : string = "Home View!";
}
import { Injector } from 'angular2/core';
import { CanActivate, ComponentInstruction } from 'angular2/router';
import { Authentication } from '../services/authentication';
import { Storage } from '../services/storage';
import { CurrentUser } from '../interfaces/common';
export const Roles = (...rolesAllowed : Array<string>) => {
return CanActivate((next: ComponentInstruction, prev: ComponentInstruction) => {
//this would not work if user info was not being kept in session storage
//as of now it doesn't seem possible to access same-instance application services through non-components
const injector = Injector.resolveAndCreate([Authentication, Storage]);
const authentication : Authentication = injector.get(Authentication);
const userRoles : Array<string> = authentication.userRoles;
return isAllowedAccess(rolesAllowed, userRoles);
});
};
const isAllowedAccess = (rolesAllowed: Array<string>, currentRoles: Array<string>) => {
const intersectedRoles = currentRoles.reduce((acc, curr) => {
return [
...acc,
...rolesAllowed.filter(role => role.trim().toUpperCase() === curr.trim().toUpperCase())
]
}, []);
return intersectedRoles.length > 0;
};
@yassinechabli
Copy link

can i apply the @ROLE anotation on a specifics methods not for the global component ?

@aboglioli
Copy link

I don't think so. @ROLE(..) function is returning a CanActivate object, it's applied only to Components.

@kevcalderon
Copy link

XD

@gundupatil
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment