From 250aa360d27a2c20a05a4350cafcd1d76b57211c Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Mon, 2 Oct 2017 12:20:40 +0100 Subject: [PATCH] improved ecm auth guard (#2402) --- .../services/auth-guard-ecm.service.spec.ts | 198 +++++++++++++----- .../src/services/auth-guard-ecm.service.ts | 47 +++-- 2 files changed, 174 insertions(+), 71 deletions(-) diff --git a/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.spec.ts b/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.spec.ts index c6d7da6100..27cf7e9a84 100644 --- a/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.spec.ts +++ b/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.spec.ts @@ -17,67 +17,169 @@ import { async, inject, TestBed } from '@angular/core/testing'; import { Router } from '@angular/router'; -import { RouterTestingModule } from '@angular/router/testing'; +import { AlfrescoApiService } from 'ng2-alfresco-core'; -import { CookieServiceMock } from './../assets/cookie.service.mock'; -import { AlfrescoApiService } from './alfresco-api.service'; -import { AlfrescoSettingsService } from './alfresco-settings.service'; -import { AppConfigModule } from './app-config.service'; import { AuthGuardEcm } from './auth-guard-ecm.service'; -import { AuthenticationService } from './authentication.service'; -import { CookieService } from './cookie.service'; -import { LogService } from './log.service'; -import { StorageService } from './storage.service'; -import { UserPreferencesService } from './user-preferences.service'; -describe('AuthGuardService ECM', () => { +class RouterProvider { + navigate: Function = jasmine.createSpy('RouterProviderNavigate'); +} + +class AlfrescoApiServiceProvider { + private settings: any = { + validateTicket: true, + isLoggedIn: true + }; + + constructor(settings: any = {}) { + Object.assign(this.settings, settings); + } + + getInstance() { + return { + ecmAuth: this.ecmAuth + }; + } + + private get ecmAuth() { + return { + validateTicket: this.validateTicket.bind(this), + isLoggedIn: this.isLoggedIn.bind(this) + }; + } + + private validateTicket() { + const { validateTicket } = this.settings; + + return validateTicket + ? Promise.resolve('Valid!') + : Promise.reject('Invalid'); + } + + private isLoggedIn() { + return this.settings.isLoggedIn; + } +} + +class TestConfig { + router: any; + guard: any; + + private settings: any = { + validateTicket: true, + isLoggedIn: true + }; + + constructor(settings: any = {}) { + Object.assign(this.settings, settings); - beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [ - AppConfigModule, - RouterTestingModule - ], - declarations: [ - ], providers: [ - AuthGuardEcm, - AlfrescoSettingsService, - AlfrescoApiService, - AuthenticationService, - StorageService, - UserPreferencesService, - { provide: CookieService, useClass: CookieServiceMock }, - LogService + this.routerProvider, + this.alfrescoApiServiceProvider, + AuthGuardEcm ] - }).compileComponents(); - })); + }); - it('if the alfresco js api is logged in should canActivate be true', - async(inject([AuthGuardEcm, Router, AlfrescoSettingsService, StorageService, AuthenticationService], (auth, router, settingsService, storage, authService) => { - spyOn(router, 'navigate'); + inject([ AuthGuardEcm, Router ], (guard: AuthGuardEcm, router: Router) => { + this.guard = guard; + this.router = router; + })(); + } - authService.isEcmLoggedIn = () => { - return true; - }; + private get routerProvider() { + return { + provide: Router, + useValue: new RouterProvider() + }; + } - expect(auth.canActivate()).toBeTruthy(); - expect(router.navigate).not.toHaveBeenCalled(); - })) - ); + private get alfrescoApiServiceProvider () { + const { validateTicket, isLoggedIn } = this.settings; - it('if the alfresco js api is NOT logged in should canActivate be false', - async(inject([AuthGuardEcm, Router, AlfrescoSettingsService, StorageService, AuthenticationService], (auth, router, settingsService, storage, authService) => { + return { + provide: AlfrescoApiService, + useValue: new AlfrescoApiServiceProvider({ + validateTicket, + isLoggedIn + }) + }; + } - spyOn(router, 'navigate'); + get navigateSpy() { + return this.router.navigate; + } +} - authService.isEcmLoggedIn = () => { - return false; - }; +describe('CanActivateLoggedIn', () => { + describe('user is not logged in', () => { + beforeEach(async(() => { + this.test = new TestConfig({ + isLoggedIn: false + }); - expect(auth.canActivate()).toBeFalsy(); - expect(router.navigate).toHaveBeenCalled(); - })) - ); + const { guard, router } = this.test; + guard.canActivate().then((activate) => { + this.activate = activate; + this.navigateSpy = router.navigate; + }); + })); + + it('does not allow route to activate', () => { + expect(this.activate).toBe(false); + }); + + it('redirects to /login', () => { + expect(this.navigateSpy).toHaveBeenCalledWith([ '/login' ]); + }); + }); + + describe('user is logged in but ticket is invalid', () => { + beforeEach(async(() => { + this.test = new TestConfig({ + isLoggedIn: true, + validateTicket: false + }); + + const { guard, router } = this.test; + + guard.canActivate().then((activate) => { + this.activate = activate; + this.navigateSpy = router.navigate; + }); + })); + + it('does not allow route to activate', () => { + expect(this.activate).toBe(false); + }); + + it('redirects to /login', () => { + expect(this.navigateSpy).toHaveBeenCalledWith([ '/login' ]); + }); + }); + + describe('user is logged in and ticket is valid', () => { + beforeEach(async(() => { + this.test = new TestConfig({ + isLoggedIn: true, + validateTicket: true + }); + + const { guard, router } = this.test; + + guard.canActivate().then((activate) => { + this.activate = activate; + this.navigateSpy = router.navigate; + }); + })); + + it('allows route to activate', () => { + expect(this.activate).toBe(true); + }); + + it('does not redirect', () => { + expect(this.navigateSpy).not.toHaveBeenCalled(); + }); + }); }); diff --git a/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.ts b/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.ts index fad465cad4..ff30ca3382 100644 --- a/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.ts +++ b/ng2-components/ng2-alfresco-core/src/services/auth-guard-ecm.service.ts @@ -16,38 +16,39 @@ */ import { Injectable } from '@angular/core'; -import { - ActivatedRouteSnapshot, CanActivate, CanActivateChild, - Router, - RouterStateSnapshot -} from '@angular/router'; +import { CanActivate, Router } from '@angular/router'; -import { AuthenticationService } from './authentication.service'; +import { AlfrescoApiService } from './alfresco-api.service'; @Injectable() -export class AuthGuardEcm implements CanActivate, CanActivateChild { - constructor(private authService: AuthenticationService, private router: Router) {} - - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { - // let url: string = state.url; - - return this.checkLogin(); +export class AuthGuardEcm implements CanActivate { + constructor( + private apiService: AlfrescoApiService, + private router: Router) { } - canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { - return this.canActivate(route, state); + private get authApi() { + return this.apiService.getInstance().ecmAuth; } - checkLogin(): boolean { - if (this.authService.isEcmLoggedIn()) { - return true; + private isLoggedIn(): Promise { + if (!this.authApi.isLoggedIn()) { + return Promise.resolve(false); } - // Store the attempted URL for redirecting - // this.authService.redirectUrl = url; + return this.authApi + .validateTicket() + .then(() => true, () => false) + .catch(() => false); + } - // Navigate to the login page with extras - this.router.navigate(['/login']); - return false; + canActivate(): Promise { + return this.isLoggedIn().then(isLoggedIn => { + if (!isLoggedIn) { + this.router.navigate([ '/login' ]); + } + + return isLoggedIn; + }); } }