From baeb35c41f616863a34596ae48d5c8957c9e3635 Mon Sep 17 00:00:00 2001 From: doktordirk Date: Tue, 31 May 2016 12:39:25 +0200 Subject: [PATCH] feat(project): add AuthenticationStep and deprecate AuthorizeStep DEPRECATION: AuthorizeStep replaced by AuthenticationStep AuthenticationStep uses {settings:authentication:true}} of a route's configuration --- src/aurelia-authentication.js | 4 +- src/authenticateStep.js | 25 ++++++ src/authorizeStep.js | 3 + test/aurelia-authentication.spec.js | 7 +- test/authService.spec.js | 6 +- test/authenticateStep.spec.js | 133 ++++++++++++++++++++++++++++ test/setup.js | 1 - 7 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 src/authenticateStep.js create mode 100644 test/authenticateStep.spec.js diff --git a/src/aurelia-authentication.js b/src/aurelia-authentication.js index 8df5eda..4b59e98 100644 --- a/src/aurelia-authentication.js +++ b/src/aurelia-authentication.js @@ -3,6 +3,7 @@ import {Config, Rest} from 'aurelia-api'; import {AuthService} from './authService'; import {AuthorizeStep} from './authorizeStep'; +import {AuthenticateStep} from './authenticateStep'; import {BaseConfig} from './baseConfig'; import {FetchConfig} from './fetchClientConfig'; import './authFilter'; @@ -67,5 +68,6 @@ export { configure, FetchConfig, AuthService, - AuthorizeStep + AuthorizeStep, + AuthenticateStep }; diff --git a/src/authenticateStep.js b/src/authenticateStep.js new file mode 100644 index 0000000..b3946b3 --- /dev/null +++ b/src/authenticateStep.js @@ -0,0 +1,25 @@ +import {inject} from 'aurelia-dependency-injection'; +import {Authentication} from './authentication'; +import {Redirect} from 'aurelia-router'; + +@inject(Authentication) +export class AuthenticateStep { + constructor(authentication) { + this.authentication = authentication; + } + + run(routingContext, next) { + const isLoggedIn = this.authentication.isAuthenticated(); + const loginRoute = this.authentication.config.loginRoute; + + if (routingContext.getAllInstructions().some(i => i.config.settings.authenticate === true)) { + if (!isLoggedIn) { + return next.cancel(new Redirect(loginRoute)); + } + } else if (isLoggedIn && routingContext.getAllInstructions().some(i => i.fragment === loginRoute)) { + return next.cancel(new Redirect( this.authentication.config.loginRedirect )); + } + + return next(); + } +} diff --git a/src/authorizeStep.js b/src/authorizeStep.js index 3f29c26..d8db1c8 100644 --- a/src/authorizeStep.js +++ b/src/authorizeStep.js @@ -1,10 +1,13 @@ import {inject} from 'aurelia-dependency-injection'; import {Authentication} from './authentication'; import {Redirect} from 'aurelia-router'; +import * as LogManager from 'aurelia-logging'; @inject(Authentication) export class AuthorizeStep { constructor(authentication) { + LogManager.getLogger('authentication').warn('AuthorizeStep is deprecated. Use AuthenticationStep instead and add {settings: {authenticate: true}} to your router configuration.'); + this.authentication = authentication; } diff --git a/test/aurelia-authentication.spec.js b/test/aurelia-authentication.spec.js index 2f07b6b..31527dc 100644 --- a/test/aurelia-authentication.spec.js +++ b/test/aurelia-authentication.spec.js @@ -6,7 +6,8 @@ import { configure, FetchConfig, AuthService, - AuthorizeStep + AuthorizeStep, + AuthenticateStep } from '../src/aurelia-authentication'; import {BaseConfig} from '../src/baseConfig'; @@ -41,6 +42,10 @@ describe('aurelia-authentication', function() { it('Should export AuthorizeStep', function() { expect(AuthorizeStep).toBeDefined(); }); + + it('Should export AuthenticateStep', function() { + expect(AuthenticateStep).toBeDefined(); + }); }); describe('configure()', function() { diff --git a/test/authService.spec.js b/test/authService.spec.js index 63eea98..b3a824e 100644 --- a/test/authService.spec.js +++ b/test/authService.spec.js @@ -87,11 +87,11 @@ describe('AuthService', () => { describe('.updateMe() with PUT', () => { const container = getContainer(); const authService = container.get(AuthService); - + beforeEach(() => { authService.config.profileMethod = 'put'; }); - + it('without criteria', done => { authService.updateMe({data: 'some'}) .then(result => { @@ -141,7 +141,7 @@ describe('AuthService', () => { describe('.updateMe() with PATCH', () => { const container = getContainer(); const authService = container.get(AuthService); - + beforeEach(() => { authService.config.profileMethod = 'patch'; }); diff --git a/test/authenticateStep.spec.js b/test/authenticateStep.spec.js new file mode 100644 index 0000000..be7d80f --- /dev/null +++ b/test/authenticateStep.spec.js @@ -0,0 +1,133 @@ +import {Container} from 'aurelia-dependency-injection'; + +import {AuthenticateStep} from '../src/authenticateStep'; + + +const routes = { + onLoginRoute : [ + {name: 'parent', fragment: '/login', config: {settings: {}}}, + {name: 'child', fragment: 'childUrl', config: {settings: {}}} + ], + authenticateNone : [ + {name: 'parent', fragment: 'parentUrl', config: {settings: {}}}, + {name: 'child', fragment: 'childUrl', config: {settings: {}}} + ], + authenticateChild : [ + {name: 'parent', fragment: 'parentUrl', config: {settings: {}}}, + {name: 'child', fragment: 'childUrl', config: {settings: {authenticate: true}}} + ], + authenticateParent : [ + {name: 'parent', fragment: 'parentUrl', config: {settings: {authenticate: true}}}, + {name: 'child', fragment: 'childUrl', config: {settings: {}}} + ]}; + +describe('AuthenticateStep', () => { + describe('.run()', () => { + const authenticateStep = new Container().get(AuthenticateStep); + function next() {return;} + let loginRoute = authenticateStep.authentication.config.loginRoute; + + it('should not redirect when not authenticated and no route requires it', () => { + let routingContext = { + getAllInstructions: () => routes.authenticateNone + }; + + next.cancel = redirect => {throw new Error();}; + + spyOn(next, 'cancel'); + + authenticateStep.run(routingContext, next); + + expect(next.cancel).not.toHaveBeenCalled(); + }); + + it('should redirect to login when not authenticated and child route requires it', done => { + let routingContext = { + getAllInstructions: () => routes.authenticateChild + }; + + next.cancel = redirect => { + expect(redirect.url).toBe(loginRoute); + done(); + }; + + authenticateStep.run(routingContext, next); + }); + + it('should redirect to login when not authenticated and parent route requires it', done => { + let routingContext = { + getAllInstructions: () => routes.authenticateParent + }; + + next.cancel = redirect => { + expect(redirect.url).toBe(loginRoute); + done(); + }; + + authenticateStep.run(routingContext, next); + }); + + it('should not redirect to login when authenticated and no route requires it', () => { + let routingContext = { + getAllInstructions: () => routes.authenticateNone + }; + + next.cancel = redirect => {throw new Error();}; + + spyOn(next, 'cancel'); + + authenticateStep.authentication.isAuthenticated = () => true; + + authenticateStep.run(routingContext, next); + + expect(next.cancel).not.toHaveBeenCalled(); + }); + + it('should not redirect when authenticated and child route requires it', () => { + let routingContext = { + getAllInstructions: () => routes.authenticateChild + }; + + next.cancel = redirect => {throw new Error();}; + + spyOn(next, 'cancel'); + + authenticateStep.authentication.isAuthenticated = () => true; + + authenticateStep.run(routingContext, next); + + expect(next.cancel).not.toHaveBeenCalled(); + }); + + it('should not redirect when not authenticated and parent route requires it', () => { + let routingContext = { + getAllInstructions: () => routes.authenticateParent + }; + + next.cancel = redirect => {throw new Error();}; + + spyOn(next, 'cancel'); + + authenticateStep.authentication.isAuthenticated = () => true; + + authenticateStep.run(routingContext, next); + + expect(next.cancel).not.toHaveBeenCalled(); + }); + + it('should redirect when authenticated and parent route is login route', done => { + let routingContext = { + getAllInstructions: () => routes.onLoginRoute + }; + + next.cancel = redirect => { + expect(redirect.url).toBe(authenticateStep.authentication.config.loginRedirect); + done(); + }; + + authenticateStep.authentication.isAuthenticated = () => true; + + authenticateStep.run(routingContext, next); + }); + }); +}); diff --git a/test/setup.js b/test/setup.js index 18b1bbd..89bbf52 100644 --- a/test/setup.js +++ b/test/setup.js @@ -1,5 +1,4 @@ import {initialize} from 'aurelia-pal-browser'; import 'aurelia-polyfills'; -import 'fetch'; initialize();