Last active
November 20, 2019 13:31
-
-
Save dsalvagni/bdf92af98fbcb00ad3eea7d050d46fbc to your computer and use it in GitHub Desktop.
AccessRole Guard for Angular apps - https://salvagni.dev/2019/09/accessrole-guard-for-angular-apps/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { | |
ActivatedRouteSnapshot, | |
CanActivate, | |
Router, | |
RouterStateSnapshot, | |
} from '@angular/router'; | |
import { Observable } from 'rxjs'; | |
import { map } from 'rxjs/operators'; | |
import { AuthService } from '../services/auth.service'; | |
/** | |
* Implements a Route Guard that will confirm that an authenticated user | |
* has the roles informed on route data object. | |
*/ | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class AccessRoleGuard implements CanActivate { | |
constructor( | |
private router: Router, | |
private authService: AuthService | |
) { } | |
canActivate( | |
next: ActivatedRouteSnapshot, | |
state: RouterStateSnapshot): Observable<boolean> { | |
const roles = next.data && next.data.roles || []; | |
return this.authService | |
.hasSomeOfTheseRoles(roles) | |
.pipe( | |
map((response: boolean): boolean => { | |
if (response) return true; | |
this.router.navigate(['/not-authorized']); | |
return false; | |
}) | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { Observable, of } from 'rxjs'; | |
import { map } from 'rxjs/operators'; | |
/** Describe the available user roles */ | |
export enum AccessRole { | |
Admin = 'Admin', | |
Author = 'Author', | |
Member = 'Member' | |
} | |
/** | |
* Authentication service | |
* It should validate if the logged user has a given set of roles. | |
*/ | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class AuthService { | |
/** | |
* Retrieve all the available roles from the logged user. | |
*/ | |
getUserRoles(): Observable<AccessRole[]> { | |
// Return the users roles | |
// Hard-coded here for example purposes | |
return of([AccessRole.Author, AccessRole.Member]); | |
} | |
/** | |
* Verify if the user has at least one role of those passed in the argument. | |
* This is useful for Guards that accept one or more Access Role. | |
*/ | |
hasSomeOfTheseRoles(roles: AccessRole[]): Observable<boolean> { | |
return this.getUserRoles() | |
.pipe( | |
map((userRoles: AccessRole[]) => userRoles.some(role => roles.includes(role))) | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { NgModule } from '@angular/core'; | |
import { RouterModule, Routes } from '@angular/router'; | |
import { AccessRole } from './services/auth.service'; | |
import { AccessRoleGuard } from './guards/access-role.guard'; | |
import { MemberComponent } from './member.component'; | |
/** | |
* Define in the route which user access role is allowed to access this route. | |
*/ | |
const routes: Routes = [{ | |
path: '/member', | |
component: MemberComponent, | |
canActivate: [AccessRoleGuard], | |
data: { | |
roles: [AccessRole.Member, AccessRole.Author] | |
} | |
}]; | |
@NgModule({ | |
imports: [RouterModule.forChild(routes)], | |
exports: [RouterModule] | |
}) | |
export class MemberModule { } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment