From 49c6bc9fb23bd730def6d1aa298f6be103ccddb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Barbeau?= Date: Thu, 30 Aug 2018 12:13:58 -0400 Subject: [PATCH] feat(auth): add guards --- projects/auth/src/lib/shared/admin.guard.ts | 37 +++++++++++++++ projects/auth/src/lib/shared/auth.guard.ts | 2 +- .../auth/src/lib/shared/auth.interface.ts | 5 +++ projects/auth/src/lib/shared/auth.service.ts | 41 ++++++++++------- projects/auth/src/lib/shared/index.ts | 3 ++ projects/auth/src/lib/shared/logged.guard.ts | 36 +++++++++++++++ projects/auth/src/lib/shared/profils.guard.ts | 45 +++++++++++++++++++ 7 files changed, 151 insertions(+), 18 deletions(-) create mode 100644 projects/auth/src/lib/shared/admin.guard.ts create mode 100644 projects/auth/src/lib/shared/logged.guard.ts create mode 100644 projects/auth/src/lib/shared/profils.guard.ts diff --git a/projects/auth/src/lib/shared/admin.guard.ts b/projects/auth/src/lib/shared/admin.guard.ts new file mode 100644 index 0000000000..809540d9ff --- /dev/null +++ b/projects/auth/src/lib/shared/admin.guard.ts @@ -0,0 +1,37 @@ +import { Injectable } from '@angular/core'; +import { + CanActivate, + Router, + ActivatedRouteSnapshot, + RouterStateSnapshot +} from '@angular/router'; + +import { ConfigService } from '@igo2/core'; +import { AuthService } from './auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class AdminGuard implements CanActivate { + constructor( + private authService: AuthService, + private config: ConfigService, + private router: Router + ) {} + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + const token = this.authService.decodeToken(); + if (token && token.user && token.user.admin) { + return true; + } + + this.authService.redirectUrl = state.url; + + const authConfig = this.config.getConfig('auth'); + if (authConfig && authConfig.loginRoute) { + this.router.navigateByUrl(authConfig.loginRoute); + } + + return false; + } +} diff --git a/projects/auth/src/lib/shared/auth.guard.ts b/projects/auth/src/lib/shared/auth.guard.ts index 2573e6026b..ab0359ce3c 100644 --- a/projects/auth/src/lib/shared/auth.guard.ts +++ b/projects/auth/src/lib/shared/auth.guard.ts @@ -20,7 +20,7 @@ export class AuthGuard implements CanActivate { ) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - if (this.authService.logged) { + if (this.authService.authenticated) { return true; } diff --git a/projects/auth/src/lib/shared/auth.interface.ts b/projects/auth/src/lib/shared/auth.interface.ts index 6852fbc99f..6414ceb360 100644 --- a/projects/auth/src/lib/shared/auth.interface.ts +++ b/projects/auth/src/lib/shared/auth.interface.ts @@ -23,11 +23,16 @@ export interface AuthOptions { facebook?: AuthFacebookOptions; google?: AuthGoogleOptions; trustHosts?: string[]; + profilsGuard?: string[]; } export interface User { source?: string; sourceId?: string; email?: string; + firstName?: string; + lastName?: string; + locale?: string; + admin?: boolean; defaultContextId?: string; } diff --git a/projects/auth/src/lib/shared/auth.service.ts b/projects/auth/src/lib/shared/auth.service.ts index dddda6531c..73574b9bf2 100644 --- a/projects/auth/src/lib/shared/auth.service.ts +++ b/projects/auth/src/lib/shared/auth.service.ts @@ -5,7 +5,7 @@ import { Router } from '@angular/router'; import { Observable, BehaviorSubject, of } from 'rxjs'; import { tap } from 'rxjs/operators'; -import { ConfigService } from '@igo2/core'; +import { ConfigService, LanguageService } from '@igo2/core'; import { Base64 } from '@igo2/utils'; import { AuthOptions, User } from './auth.interface'; @@ -24,6 +24,7 @@ export class AuthService { private http: HttpClient, private tokenService: TokenService, private config: ConfigService, + private languageService: LanguageService, @Optional() private router: Router ) { this.options = this.config.getConfig('auth') || {}; @@ -39,14 +40,7 @@ export class AuthService { password: this.encodePassword(password) }); - return this.http - .post(`${this.options.url}/login`, body, { headers: myHeader }) - .pipe( - tap((data: any) => { - this.tokenService.set(data.token); - this.authenticate$.next(true); - }) - ); + return this.loginCall(body, myHeader); } loginWithToken(token: string, type: string): any { @@ -58,14 +52,7 @@ export class AuthService { typeConnection: type }); - return this.http - .post(`${this.options.url}/login`, body, { headers: myHeader }) - .pipe( - tap((data: any) => { - this.tokenService.set(data.token); - this.authenticate$.next(true); - }) - ); + return this.loginCall(body, myHeader); } loginAnonymous() { @@ -113,6 +100,10 @@ export class AuthService { return this.http.get(url); } + getProfils() { + return this.http.get(`${this.options.url}/profils`); + } + updateUser(user: User): Observable { const url = this.options.url; return this.http.patch(url, JSON.stringify(user)); @@ -122,6 +113,7 @@ export class AuthService { return Base64.encode(password); } + // authenticated or anonymous get logged(): boolean { return this.authenticated || this.isAnonymous; } @@ -133,4 +125,19 @@ export class AuthService { get authenticated(): boolean { return this.isAuthenticated(); } + + private loginCall(body, headers) { + return this.http + .post(`${this.options.url}/login`, body, { headers: headers }) + .pipe( + tap((data: any) => { + this.tokenService.set(data.token); + const tokenDecoded = this.decodeToken(); + if (tokenDecoded && tokenDecoded.user && tokenDecoded.user.locale) { + this.languageService.setLanguage(tokenDecoded.user.locale); + } + this.authenticate$.next(true); + }) + ); + } } diff --git a/projects/auth/src/lib/shared/index.ts b/projects/auth/src/lib/shared/index.ts index f79e427d53..8e95c49424 100644 --- a/projects/auth/src/lib/shared/index.ts +++ b/projects/auth/src/lib/shared/index.ts @@ -2,5 +2,8 @@ export * from './token.service'; export * from './auth.service'; export * from './auth.interface'; export * from './auth.interceptor'; +export * from './logged.guard'; export * from './auth.guard'; +export * from './admin.guard'; +export * from './profils.guard'; export * from './protected.directive'; diff --git a/projects/auth/src/lib/shared/logged.guard.ts b/projects/auth/src/lib/shared/logged.guard.ts new file mode 100644 index 0000000000..05f50fefbe --- /dev/null +++ b/projects/auth/src/lib/shared/logged.guard.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@angular/core'; +import { + CanActivate, + Router, + ActivatedRouteSnapshot, + RouterStateSnapshot +} from '@angular/router'; + +import { ConfigService } from '@igo2/core'; +import { AuthService } from './auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class LoggedGuard implements CanActivate { + constructor( + private authService: AuthService, + private config: ConfigService, + private router: Router + ) {} + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + if (this.authService.logged) { + return true; + } + + this.authService.redirectUrl = state.url; + + const authConfig = this.config.getConfig('auth'); + if (authConfig && authConfig.loginRoute) { + this.router.navigateByUrl(authConfig.loginRoute); + } + + return false; + } +} diff --git a/projects/auth/src/lib/shared/profils.guard.ts b/projects/auth/src/lib/shared/profils.guard.ts new file mode 100644 index 0000000000..2a739065ca --- /dev/null +++ b/projects/auth/src/lib/shared/profils.guard.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@angular/core'; +import { + CanActivate, + Router, + ActivatedRouteSnapshot, + RouterStateSnapshot +} from '@angular/router'; +import { map } from 'rxjs/operators'; + +import { ConfigService } from '@igo2/core'; +import { AuthService } from './auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class ProfilsGuard implements CanActivate { + constructor( + private authService: AuthService, + private config: ConfigService, + private router: Router + ) {} + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + return this.authService.getProfils().pipe( + map((profils: string[]) => { + const authConfig = this.config.getConfig('auth'); + + if ( + profils && + profils.some(v => authConfig.profilsGuard.indexOf(v) !== -1) + ) { + return true; + } + + this.authService.redirectUrl = state.url; + + if (authConfig && authConfig.loginRoute) { + this.router.navigateByUrl(authConfig.loginRoute); + } + + return false; + }) + ); + } +}