From ed89f9ea088b23fbedd9ec856c9177cd29758f38 Mon Sep 17 00:00:00 2001 From: Andrew Throener Date: Thu, 13 Aug 2015 12:45:38 -0500 Subject: [PATCH] Unauthorized client routing Added Auth Interceptor tests cleaned up test Update routes --- modules/core/client/app/init.js | 17 +++--- .../core/client/config/core.client.routes.js | 36 ++++++++---- .../auth.interceptor.client.service.js | 22 +++++++ .../core/client/views/400.client.view.html | 6 ++ .../core/client/views/403.client.view.html | 6 ++ .../auth.interceptor.client.tests.js | 57 +++++++++++++++++++ 6 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 modules/core/client/services/interceptors/auth.interceptor.client.service.js create mode 100644 modules/core/client/views/400.client.view.html create mode 100644 modules/core/client/views/403.client.view.html create mode 100644 modules/core/tests/client/interceptors/auth.interceptor.client.tests.js diff --git a/modules/core/client/app/init.js b/modules/core/client/app/init.js index b1c1ce085c..f7580c7678 100644 --- a/modules/core/client/app/init.js +++ b/modules/core/client/app/init.js @@ -4,13 +4,16 @@ angular.module(ApplicationConfiguration.applicationModuleName, ApplicationConfiguration.applicationModuleVendorDependencies); // Setting HTML5 Location Mode -angular.module(ApplicationConfiguration.applicationModuleName).config(['$locationProvider', - function ($locationProvider) { +angular.module(ApplicationConfiguration.applicationModuleName).config(['$locationProvider', '$httpProvider', + function ($locationProvider, $httpProvider) { $locationProvider.html5Mode(true).hashPrefix('!'); + + $httpProvider.interceptors.push('authInterceptor'); } ]); angular.module(ApplicationConfiguration.applicationModuleName).run(function ($rootScope, $state, Authentication) { + // Check authentication before changing state $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { if (toState.data && toState.data.roles && toState.data.roles.length > 0) { @@ -24,11 +27,11 @@ angular.module(ApplicationConfiguration.applicationModuleName).run(function ($ro if (!allowed) { event.preventDefault(); - $state.go('authentication.signin', {}, { - notify: false - }).then(function () { - $rootScope.$broadcast('$stateChangeSuccess', 'authentication.signin', {}, toState, toParams); - }); + if (Authentication.user !== undefined && typeof Authentication.user === 'object') { + $state.go('forbidden'); + } else { + $state.go('authentication.signin'); + } } } }); diff --git a/modules/core/client/config/core.client.routes.js b/modules/core/client/config/core.client.routes.js index ee9cc4dc45..cec96327f9 100644 --- a/modules/core/client/config/core.client.routes.js +++ b/modules/core/client/config/core.client.routes.js @@ -13,16 +13,30 @@ angular.module('core').config(['$stateProvider', '$urlRouterProvider', // Home state routing $stateProvider - .state('home', { - url: '/', - templateUrl: 'modules/core/client/views/home.client.view.html' - }) - .state('not-found', { - url: '/not-found', - templateUrl: 'modules/core/client/views/404.client.view.html', - data: { - ignoreState: true - } - }); + .state('home', { + url: '/', + templateUrl: 'modules/core/client/views/home.client.view.html' + }) + .state('not-found', { + url: '/not-found', + templateUrl: 'modules/core/client/views/404.client.view.html', + data: { + ignoreState: true + } + }) + .state('bad-request', { + url: '/bad-request', + templateUrl: 'modules/core/client/views/400.client.view.html', + data: { + ignoreState: true + } + }) + .state('forbidden', { + url: '/forbidden', + templateUrl: 'modules/core/client/views/403.client.view.html', + data: { + ignoreState: true + } + }); } ]); diff --git a/modules/core/client/services/interceptors/auth.interceptor.client.service.js b/modules/core/client/services/interceptors/auth.interceptor.client.service.js new file mode 100644 index 0000000000..d8eb8b9341 --- /dev/null +++ b/modules/core/client/services/interceptors/auth.interceptor.client.service.js @@ -0,0 +1,22 @@ +'use strict'; + +angular.module('core').factory('authInterceptor', ['$q', '$injector', + function ($q, $injector) { + return { + responseError: function(rejection) { + if (!rejection.config.ignoreAuthModule) { + switch (rejection.status) { + case 401: + $injector.get('$state').transitionTo('authentication.signin'); + break; + case 403: + $injector.get('$state').transitionTo('forbidden'); + break; + } + } + // otherwise, default behaviour + return $q.reject(rejection); + } + }; + } +]); diff --git a/modules/core/client/views/400.client.view.html b/modules/core/client/views/400.client.view.html new file mode 100644 index 0000000000..efc28045ef --- /dev/null +++ b/modules/core/client/views/400.client.view.html @@ -0,0 +1,6 @@ +

Bad Request

+ diff --git a/modules/core/client/views/403.client.view.html b/modules/core/client/views/403.client.view.html new file mode 100644 index 0000000000..151968d5e1 --- /dev/null +++ b/modules/core/client/views/403.client.view.html @@ -0,0 +1,6 @@ +

Forbidden

+ diff --git a/modules/core/tests/client/interceptors/auth.interceptor.client.tests.js b/modules/core/tests/client/interceptors/auth.interceptor.client.tests.js new file mode 100644 index 0000000000..1b1e910e33 --- /dev/null +++ b/modules/core/tests/client/interceptors/auth.interceptor.client.tests.js @@ -0,0 +1,57 @@ +'use strict'; + +(function() { + describe('authInterceptor', function() { + //Initialize global variables + var authInterceptor, + $q, + $state, + httpProvider; + + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + //Load httpProvider + beforeEach(module(function($httpProvider) { + httpProvider = $httpProvider; + })); + + beforeEach(inject(function(_authInterceptor_, _$q_, _$state_) { + authInterceptor = _authInterceptor_; + $q = _$q_; + $state = _$state_; + spyOn($q,'reject'); + spyOn($state,'transitionTo'); + })); + + it('Auth Interceptor should be object', function() { + expect( typeof authInterceptor).toEqual('object'); + }); + + it('Auth Interceptor should contain responseError function', function() { + expect( typeof authInterceptor.responseError).toEqual('function'); + }); + + it('httpProvider Interceptor should have authInterceptor', function() { + expect(httpProvider.interceptors).toContain('authInterceptor'); + }); + + describe('Forbidden Interceptor', function() { + it('should redirect to forbidden route', function () { + var response = {status:403,config:{}}; + var promise = authInterceptor.responseError(response); + expect($q.reject).toHaveBeenCalled(); + expect($state.transitionTo).toHaveBeenCalledWith('forbidden'); + }); + }); + + describe('Authorization Interceptor', function() { + it('should redirect to signIn page for unauthorized access', function () { + var response = {status:401,config:{}}; + var promise = authInterceptor.responseError(response); + expect($q.reject).toHaveBeenCalled(); + expect($state.transitionTo).toHaveBeenCalledWith('authentication.signin'); + }); + }); + }); +})();