├── .bowerrc ├── .editorconfig ├── .gitignore ├── .jshintrc ├── .travis.yml ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── config └── karma.js ├── index.js ├── lcov.info ├── package.json ├── release ├── angular-hitmands-auth.js ├── angular-hitmands-auth.js.map ├── angular-hitmands-auth.min.js └── hitmands-auth.config.js ├── server.js ├── specs ├── directives │ ├── auth-classes.spec.js │ ├── auth-login.spec.js │ └── auth-logout.spec.js ├── modules │ ├── $stateChangeStart.spec.js │ └── onCurrentUserUpdate.spec.js ├── provider-methods │ ├── disableAutoRoutingProtection.spec.js │ ├── parseHttpAuthData.spec.js │ ├── setLoggedUser.spec.js │ ├── setRedirectPath.spec.js │ ├── tokenizeHttp.spec.js │ ├── useBasicAuthentication.spec.js │ └── useRoutes.spec.js └── service-methods │ ├── authorize.spec.js │ ├── check.spec.js │ ├── fetch.spec.js │ ├── getAuthenticationToken.spec.js │ ├── getCurrentUser.spec.js │ ├── isUserLoggedIn.spec.js │ ├── login.spec.js │ ├── logout.spec.js │ ├── setCurrentUser.spec.js │ └── unsetCurrentUser.spec.js └── src ├── auth-directives.js ├── auth-helpers.js ├── auth-module.js ├── auth-provider.js └── sample-configuration.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory" : "./src/vendor" 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | indent_style = space 9 | end_of_line = lf 10 | charset = utf-8 11 | insert_final_newline = true 12 | 13 | # tab indentation 14 | [*.{css,scss,twig}] 15 | indent_size = 2 16 | 17 | # 2 spaces indentation for JS 18 | [*.js] 19 | indent_size = 3 20 | 21 | [*.json] 22 | indent_size = 3 23 | 24 | # 4 spaces indentation for PHP (PSR-2) 25 | [*.{php,module,inc] 26 | indent_size = 4 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .sass-cache 2 | .idea 3 | Gemfile.lock 4 | node_modules 5 | coverage/ 6 | logs 7 | *.log 8 | originalChannel 9 | media/* 10 | PSD_AI 11 | config/runtime.json 12 | 13 | # OS generated files # 14 | ###################### 15 | */.DS_Store 16 | .DS_Store 17 | .DS_Store? 18 | ._* 19 | .Spotlight-V100 20 | .Trashes 21 | ehthumbs.db 22 | Thumbs.db 23 | run.sh 24 | runTest.sh 25 | dump.rdb 26 | 27 | /bower_components/ 28 | /src/vendor 29 | /sample 30 | /server.js 31 | 32 | sample/Code coverage report for release angular-hitmands-auth.js_files 33 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef" : [ 3 | "angular", 4 | "jasmine", 5 | "describe", 6 | "xdescribe", 7 | "before", 8 | "beforeEach", 9 | "after", 10 | "afterEach", 11 | "it", 12 | "xit", 13 | "it", 14 | "inject", 15 | "expect", 16 | "spyOn" 17 | ], 18 | 19 | "passfail" : false, 20 | "maxerr" : 100, 21 | "camelcase" : true, 22 | 23 | "multistr" : false, 24 | 25 | "browser" : true, 26 | "node" : true, 27 | "rhino" : false, 28 | "couch" : false, 29 | 30 | "wsh" : true, 31 | "jquery" : false, 32 | "prototypejs" : false, 33 | "mootools" : false, 34 | 35 | "dojo" : false, 36 | 37 | "debug" : false, 38 | "devel" : true, 39 | 40 | "es3" : true, 41 | "forin" : true, 42 | "strict" : true, 43 | "globalstrict" : false, 44 | 45 | 46 | "asi" : true, 47 | "laxbreak" : true, 48 | "bitwise" : true, 49 | "boss" : false, 50 | "curly" : true, 51 | "eqeqeq" : true, 52 | "eqnull" : false, 53 | "evil" : false, 54 | "expr" : true, 55 | "immed" : true, 56 | "latedef" : true, 57 | "loopfunc" : false, 58 | "noarg" : true, 59 | "scripturl" : true, 60 | "shadow" : false, 61 | "supernew" : false, 62 | "undef" : true, 63 | "unused" : false, 64 | 65 | 66 | "newcap" : true, 67 | "noempty" : true, 68 | "nonew" : true, 69 | "nomen" : false, 70 | "onevar" : true, 71 | "plusplus" : false, 72 | "sub" : false, 73 | "trailing" : true, 74 | "white" : false 75 | } 76 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | before_script: 6 | - npm install -g istanbul 7 | - npm install -g karma 8 | - npm install -g karma-cli 9 | - npm install -g grunt-cli 10 | - npm install -g bower 11 | - npm install -g codeclimate-test-reporter 12 | 13 | script: 14 | - bower install 15 | - grunt release 16 | - karma start config/karma.js --no-auto-watch --single-run 17 | 18 | addons: 19 | code_climate: 20 | repo_token: 26927a8c0f4396bc55ee423a1c0df10cb09a6ee6bf838d4edc32df2432a069da 21 | 22 | after_script: 23 | - cat "lcov.info" | codeclimate 24 | 25 | git: 26 | depth: 10 27 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 'use strict'; 3 | require('jit-grunt')(grunt, { 4 | "ngtemplates" : "grunt-angular-templates" 5 | }); 6 | 7 | var pkg = grunt.file.readJSON('package.json'); 8 | 9 | var _banner = "/**!\n" + 10 | " * @Project: <%= pkg.name %>\n" + 11 | " * @Authors: <%= pkg.authors.join(', ') %>\n" + 12 | " * @Link: <%= pkg.homepage %>\n" + 13 | " * @License: MIT\n" + 14 | " * @Date: <%= grunt.template.today('yyyy-mm-dd') %>\n" + 15 | " * @Version: <%= pkg.version %>\n" + 16 | " * \n" + 17 | " * @ngdoc: module\n" + 18 | " * @namespace: hitmands\n" + 19 | " * @name: auth\n" + 20 | " * @module: hitmands.auth\n" + 21 | " * @description: Full Implementation of an authentication management system.\n" + 22 | "***/\n\n"; 23 | 24 | grunt.config.init({ 25 | pkg: pkg, 26 | 27 | jshint: { 28 | options: { 29 | jshintrc: './.jshintrc', 30 | force: true 31 | }, 32 | frontend: { 33 | src: [ 34 | './release/**/*.js', 35 | '!./release/**/*.min.js' 36 | ] 37 | } 38 | }, 39 | 40 | ngAnnotate: { 41 | options: { 42 | singleQuotes: true 43 | }, 44 | modules: { 45 | files: [ 46 | { 47 | src: './release/angular-hitmands-auth.js', 48 | dest: './release/angular-hitmands-auth.js' 49 | } 50 | ] 51 | }, 52 | sample: { 53 | files: [ 54 | { 55 | src: './sample/dist/application.js', 56 | dest: './sample/dist/application.js' 57 | } 58 | ] 59 | } 60 | }, 61 | 62 | ngtemplates: { 63 | sample: { 64 | options: { 65 | module: 'hitmands.auth.sample.tpls', 66 | htmlmin: { 67 | collapseBooleanAttributes: true, 68 | collapseWhitespace: true, 69 | removeAttributeQuotes: true, 70 | removeComments: true, 71 | removeEmptyAttributes: true, 72 | removeRedundantAttributes: true, 73 | removeScriptTypeAttributes: true, 74 | removeStyleLinkTypeAttributes: true 75 | }, 76 | url: function(url) { 77 | url = url.replace('./sample', ''); 78 | return url; 79 | } 80 | }, 81 | src: './sample/partials/**/*.html', 82 | dest: './sample/dist/application-tpls.js' 83 | } 84 | }, 85 | 86 | uglify: { 87 | development: { 88 | options: { 89 | mangle: false, 90 | sourceMap: true, 91 | compress: { 92 | sequences: false, 93 | unused: false 94 | }, 95 | beautify: { 96 | indent_level: 3, 97 | indent_start: 3, 98 | ascii_only: true, 99 | beautify: true, 100 | bracketize: true, 101 | semicolons: true, 102 | quote_keys: true, 103 | width: 80 104 | }, 105 | banner: "(function(window, angular) {\n 'use strict';\n", 106 | footer: '\n\n})(window, angular);', 107 | preserveComments: function(node, comment) { 108 | var whiteList = /(jshint|@ngInject|@preserve)/g; 109 | var keepComment = false; 110 | 111 | if( whiteList.test(comment.value) ) { 112 | keepComment = true; 113 | } 114 | 115 | return keepComment; 116 | } 117 | }, 118 | files: [ 119 | { 120 | src: [ 121 | './src/auth-module.js', 122 | './src/auth-helpers.js', 123 | './src/auth-provider.js', 124 | './src/auth-directives.js' 125 | ], 126 | dest: './release/angular-hitmands-auth.js' 127 | } 128 | ] 129 | }, 130 | production: { 131 | options: { 132 | mangle: { 133 | except: ['AuthCurrentUser'] 134 | }, 135 | compress: { 136 | drop_console: true, 137 | join_vars: true, 138 | unused: true 139 | }, 140 | beautify: { 141 | ascii_only: true, 142 | beautify: false 143 | }, 144 | sourceMap: false, 145 | preserveComments: false, 146 | report: 'gzip', 147 | footer: '\n' 148 | }, 149 | files: [ 150 | { 151 | src: './release/angular-hitmands-auth.js', 152 | dest: './release/angular-hitmands-auth.min.js' 153 | } 154 | ] 155 | }, 156 | sampleDev: { 157 | options: { 158 | mangle: false, 159 | sourceMap: true, 160 | compress: { 161 | sequences: false, 162 | unused: false 163 | }, 164 | beautify: { 165 | indent_level: 3, 166 | indent_start: 3, 167 | ascii_only: true, 168 | beautify: true, 169 | bracketize: true, 170 | semicolons: true, 171 | quote_keys: true, 172 | width: 80 173 | }, 174 | banner: "(function(window, angular) {\n 'use strict';\n", 175 | footer: '\n\n})(window, angular);', 176 | preserveComments: function(node, comment) { 177 | var whiteList = /(jshint|@ngInject|@preserve)/g; 178 | var keepComment = false; 179 | 180 | if( whiteList.test(comment.value) ) { 181 | keepComment = true; 182 | } 183 | 184 | return keepComment; 185 | } 186 | }, 187 | files: [ 188 | { 189 | src: [ 190 | './sample/js/application.js', 191 | './sample/js/configs/**/*.js', 192 | './sample/js/backend/backend.js', 193 | './sample/js/services/**/*.js', 194 | './sample/js/auth/**/*.js', 195 | './sample/js/pages/**/*.js', 196 | '!./sample/dist/**/*.*' 197 | ], 198 | dest: './sample/dist/application.js' 199 | } 200 | ] 201 | }, 202 | sample: { 203 | options: { 204 | mangle: { 205 | except: ['AuthCurrentUser'] 206 | }, 207 | compress: { 208 | drop_console: true, 209 | join_vars: true, 210 | unused: true 211 | }, 212 | beautify: { 213 | ascii_only: true, 214 | beautify: false 215 | }, 216 | sourceMap: false, 217 | preserveComments: false, 218 | report: 'gzip', 219 | footer: '\n' 220 | }, 221 | files: [ 222 | { 223 | src: './sample/dist/application.js', 224 | dest: './sample/dist/application.js' 225 | } 226 | ] 227 | } 228 | }, 229 | 230 | concat: { 231 | bannerize: { 232 | options: { 233 | banner: _banner 234 | }, 235 | files: [ 236 | { 237 | src: './release/angular-hitmands-auth.js', 238 | dest: './release/angular-hitmands-auth.js' 239 | }, 240 | { 241 | src: './release/angular-hitmands-auth.min.js', 242 | dest: './release/angular-hitmands-auth.min.js' 243 | }, 244 | { 245 | src: './src/sample-configuration.js', 246 | dest: './release/hitmands-auth.config.js' 247 | } 248 | ] 249 | }, 250 | mvLcov: { 251 | src: './coverage/PhantomJS 1.9.8 (Mac OS X)/lcov.info', 252 | dest : './lcov.info', 253 | nonull: true 254 | }, 255 | sample: { 256 | src: [ 257 | 'src/vendor/angular/angular.min.js', 258 | 'src/vendor/angular-ui-router/release/angular-ui-router.min.js', 259 | 'src/vendor/angular-bootstrap/ui-bootstrap.min.js', 260 | 'src/vendor/angular-bootstrap/ui-bootstrap-tpls.js', 261 | 'src/vendor/angular-mocks/angular-mocks.js', 262 | 'src/vendor/angular-sanitize/angular-sanitize.min.js', 263 | 'src/vendor/ngprogress-lite/ngprogress-lite.min.js' 264 | ], 265 | dest : 'sample/dist/application-lib.js', 266 | nonull: true 267 | } 268 | }, 269 | 270 | inline: { 271 | options:{ 272 | cssmin: true 273 | }, 274 | sample: { 275 | src: './sample/__index.html', 276 | dest: './sample/dist/index.html' 277 | } 278 | }, 279 | 280 | htmlmin: { 281 | sample: { 282 | options : { 283 | removeComments : true, 284 | collapseWhitespace : true 285 | }, 286 | files : { 287 | './sample/dist/index.html' : './sample/dist/index.html' 288 | } 289 | } 290 | }, 291 | 292 | shell: { 293 | karmaSingleRun: { 294 | command: 'karma start config/karma.js --single-run' 295 | } 296 | }, 297 | 298 | watch: { 299 | compile: { 300 | tasks: ['default'], 301 | files: ['src/**/*.js'] 302 | }, 303 | frontend: { 304 | options: { 305 | livereload: true, 306 | spawn: false 307 | }, 308 | files: [ 309 | 'sample/**/*.*', 310 | 'release/**/*.js' 311 | ] 312 | } 313 | } 314 | 315 | }); 316 | 317 | 318 | grunt.registerTask('default', 319 | [ 320 | 'newer:uglify:development', 321 | 'newer:ngAnnotate', 322 | 'newer:jshint:frontend' 323 | ] 324 | ); 325 | 326 | grunt.registerTask('release', 327 | [ 328 | 'uglify:development', 329 | 'ngAnnotate:modules', 330 | 'uglify:production', 331 | 'concat:bannerize' 332 | ] 333 | ); 334 | 335 | grunt.registerTask('sample', [ 336 | 'uglify:sampleDev', 337 | 'ngAnnotate:sample', 338 | 'uglify:sample', 339 | //'ngtemplates:sample', 340 | //'concat:sample', 341 | //'inline:sample', 342 | //'htmlmin:sample' 343 | ]); 344 | 345 | grunt.registerTask('prepareCommit', [ 346 | 'release', 347 | 'shell:karmaSingleRun', 348 | 'concat:mvLcov' 349 | ]); 350 | }; 351 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Giuseppe Mandato 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Hitmands Auth 2 | [![Build Status](https://travis-ci.org/hitmands/angular-hitmands-auth.svg?branch=master)](https://travis-ci.org/hitmands/angular-hitmands-auth) [![Code Climate](https://codeclimate.com/github/hitmands/angular-hitmands-auth/badges/gpa.svg)](https://codeclimate.com/github/hitmands/angular-hitmands-auth) [![Test Coverage](https://codeclimate.com/github/hitmands/angular-hitmands-auth/badges/coverage.svg)](https://codeclimate.com/github/hitmands/angular-hitmands-auth) 3 | 4 | #### A full implementation of an Authentication System in [AngularJS](http://angularjs.org) based Applications. 5 | DEMO: [http://hitmands.github.io/angular-hitmands-auth/](http://hitmands.github.io/angular-hitmands-auth/) 6 | ___ 7 | 8 | **Note:** *Works with IE9+ (IE9 Without method AuthServiceProvider.useBasicAuthentication: [see](#module-provider-usebasicauthentication))* 9 | 10 | **Note:** *This module requires [AngularJS ^1.3](http://angularjs.org) and [Angular UI-Router ^0.2](http://angular-ui.github.io/ui-router/).* 11 | 12 | 13 | Table of Content: 14 | * [Getting Started](#getting-started) 15 | * [Configuration](#module-config) 16 | * [Usage](#module-run) 17 | * [Events](#module-events) 18 | * [Directives](#module-directives-login) 19 | * [Login](#module-directives-login) 20 | * [Logout](#module-directives-logout) 21 | * [Classes Authentication](#module-directives-authclasses) 22 | * [API - AuthServiceProvider](#module-provider-useroutes) 23 | * [useRoutes](#module-provider-useroutes) 24 | * [tokenizeHttp](#module-provider-tokenizehttp) 25 | * [useBasicAuthentication](#module-provider-usebasicauthentication) 26 | * [parseHttpAuthData](#module-provider-parsehttpauthdata) 27 | * [setLoggedUser](#module-provider-setloggeduser) 28 | * [API - AuthService](#module-service) 29 | * [setCurrentUser](#module-service-setcurrentuser) 30 | * [unsetCurrentUser](#module-service-unsetcurrentuser) 31 | * [getCurrentUser](#module-service-getcurrentuser) 32 | * [getAuthenticationToken](#module-service-getauthenticationtoken) 33 | * [isUserLoggedIn](#module-service-isuserloggedin) 34 | * [authorize](#module-service-authorize) 35 | * [fetch](#module-service-fetch) 36 | * [login](#module-service-login) 37 | * [logout](#module-service-logout) 38 | 39 | ## Get Started 40 | ```shell 41 | $ bower install --save angular-hitmands-auth 42 | ``` 43 | 44 | 45 | ```html 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | ... 63 | 64 | 65 | ... 66 | 67 | 68 | ``` 69 | 70 | ## Configuration 71 | ```javascript 72 | 73 | angular 74 | .module('myApp') 75 | .config(function(AuthServiceProvider, $stateProvider) { 76 | 77 | 78 | // Set API ENDPOINTS 79 | AuthServiceProvider.useRoutes({ 80 | login: '/api/v1/users/login', 81 | logout: '/api/v1/users/logout', 82 | fetch: '/api/v1/users/logged-in' 83 | }); 84 | 85 | // Callback that handles the $http Response and returns the AuthData to the AuthService 86 | AuthServiceProvider.parseHttpAuthData(function(data, headers, statusCode) { 87 | 88 | return { 89 | user: data, 90 | authLevel: authLevel, // Number|Array 91 | token: headers['X-AUTH-AUTHTOKEN'] 92 | }; 93 | }); 94 | 95 | // Route Protection via data.authLevel or authLevel directly 96 | // authLevel {Number|Array|Function} 97 | // (The Function (with injectables) must return a Number or Array. 98 | $stateProvider 99 | .state({ 100 | name: 'protected', 101 | url: '/protected/', 102 | data: { 103 | authLevel: ['administrator'] 104 | } 105 | }); 106 | 107 | }); 108 | ``` 109 | 110 | ## Usage 111 | ```javascript 112 | $rootScope.currentUser = AuthService.getCurrentUser(); 113 | $rootScope.isUserLoggedIn = AuthService.isUserLoggedIn(); 114 | 115 | $rootScope.$on('hitmands.auth:update', function(event) { 116 | $rootScope.currentUser = AuthService.getCurrentUser(); 117 | $rootScope.isUserLoggedIn = AuthService.isUserLoggedIn(); 118 | }); 119 | ``` 120 | 121 | ## Events 122 | Whenever a change occurs, the module generates an event via `$rootScope.$broadcast` method. You can register a listener via `$rootScope.$on` and the callback passed will be invoked with the following params: 123 | 124 | NAME | PARAMS PASSED | Publisher 125 | ------------------------------------ | ---------------------------------------------------------- | ------------- 126 | hitmands.auth:update | event | *All methods that updating the CurrentUser Object* 127 | hitmands.auth:login.resolved | event, result | AuthService.login **success** 128 | hitmands.auth:login.rejected | event, error | AuthService.login **error** 129 | hitmands.auth:logout.resolved | event, result | AuthService.logout **success** 130 | hitmands.auth:logout.rejected | event, error | AuthService.logout **error** 131 | hitmands.auth:fetch.resolved | event, result | AuthService.fetch **success** 132 | hitmands.auth:fetch.rejected | event, error | AuthService.fetch **error** 133 | $stateChangeError | event, toState, toParams, fromState, fromParams, error | AuthService.authorize (when user try to access states without authorization) 134 | 135 | 136 | ```javascript 137 | $rootScope.$on('event-name', function(event[, data]) { 138 | // do something... 139 | }); 140 | ``` 141 | 142 | 143 | 144 | ## Login 145 | This directive requires a **FORM HTML ELEMENT**, if the `name` attribute is set, the directive performs a basic validation. You need to pass a Javascript Object to the directive, like `{username: '', password=''[, ...]}`, (The properties username and password are required if the [Basic Access Authentication](#module-provider-usebasicauthentication) is enabled). 146 | 147 | Attribute | Value 148 | ------------------------------------ | ------------------------ 149 | auth-login | {Object} credentials (the payload to send) 150 | auth-login-on-resolve | {Function} A function invoked on login.success 151 | auth-login-on-reject | {Function} A function invoked on login.success 152 | 153 | ```html 154 |
155 | Howdy, {{ currentUser.name || 'Guest' }} 156 |
157 | 164 |
165 | 166 | 167 |
168 | 169 | 170 | 171 |
172 | 173 |
174 | ``` 175 | 176 | 177 | ## Logout 178 | ```html 179 | 180 | 181 | ``` 182 | 183 | 184 | ## Authentication Classes 185 | ```html 186 | ... 187 | 188 | ``` 189 | 190 | ## AuthServiceProvider.useRoutes 191 | This method configures API endpoints for *login*, *logout*, *fetching* authentication data. 192 | 193 | PARAM | TYPE | DESCRIPTION 194 | ------------- | ------------- | ------------- 195 | newRoutes | Object | A map of strings (login, logout, fetch) that defines the routes for user authentication. 196 | 197 | ```javascript 198 | 199 | AuthServiceProvider.useRoutes({ 200 | login: '/api/v1/users/login.json', 201 | logout: '/api/v1/users/logout.json', 202 | fetch: '/api/v1/users/current.json' 203 | }); 204 | ``` 205 | 206 | 207 | ## AuthServiceProvider.parseHttpAuthData 208 | This method sets a *middleware* between the $http responses and the AuthService. 209 | 210 | PARAM | TYPE | DESCRIPTION 211 | ------------ | ------------- | ------------- 212 | Callback | Function | This callback handles the $http responses (AuthService.login, AuthService.fetch) and returns the `{user: Object, token: String, authLevel:Number/Array}` to the AuthService. 213 | 214 | 215 | ```javascript 216 | AuthServiceProvider.parseHttpAuthData(function(data, headers, statusCode) { 217 | var authenticationData = {}; 218 | 219 | /** 220 | The authenticationData Object must have the following properties: 221 | user = Object, 222 | authLevel = Number|Array, 223 | token = String 224 | The type of the authLevel property must match with the type of the authLevel 225 | property set on ui-router $state definition Object. 226 | **/ 227 | 228 | // example: 229 | authenticationData.user = data.user; // Object 230 | authenticationData.authLevel = 1000; // Number|Array 231 | authenticationData.token = headers['x-authentication-token']; // String 232 | 233 | return authenticationData; 234 | }); 235 | 236 | ``` 237 | 238 | 239 | ## AuthServiceProvider.tokenizeHttp 240 | This method enables the interceptor and hangs the **Authentication Token** to the **headers** of each **$http request**. 241 | 242 | PARAM | TYPE | DESCRIPTION 243 | ----------------------------------- | ------------- | ------------- 244 | headerKey (optional) | String | Default `'x-auth-token'`, the key-header for hanging the token as value 245 | ErrorResponseInterceptor (optional) | Function | An interceptor invoked on ErrorResponses 246 | 247 | ```javascript 248 | AuthServiceProvider.tokenizeHttp(['X-MY-CUSTOM-AUTH-KEY'][, function(ErrorResponse) {}]); 249 | ``` 250 | 251 | ## AuthServiceProvider.useBasicAuthentication 252 | This method enables the **Basic Access Authentication** for http login request. 253 | 254 | ```javascript 255 | AuthServiceProvider.useBasicAuthentication(); 256 | ``` 257 | 258 | 259 | ## AuthServiceProvider.setLoggedUser 260 | This method sets the AuthCurrentUser before your app starts to run (Angular Bootstrap Phase). 261 | 262 | PARAM | TYPE | DESCRIPTION 263 | ------------- | ------------------- | ------------- 264 | user | Object | The Object for AuthCurrentUser instance. 265 | token | String | The session token 266 | authLevel | Number or Array | The **type** of this param must match with the type of the authLevel property set on ui-router $state definition Object. 267 | 268 | ```javascript 269 | AuthServiceProvider.setLoggedUser(Object, String, Number/Array); 270 | ``` 271 | 272 | 273 | ## AuthService.setCurrentUser 274 | This method sets the AuthCurrentUser. 275 | Returns `true {Boolean}` if the AuthCurrentUser is instantiated, otherwise `false {Boolean}`. 276 | 277 | PARAM | TYPE | DESCRIPTION 278 | ------------- | ------------------- | ------------- 279 | user | Object | The Object for AuthCurrentUser instance. 280 | authLevel | Number/Array | The **type** of this param must match with the type of the authLevel property set on ui-router $state definition Object. 281 | token | String | The session token 282 | 283 | ```javascript 284 | AuthService.setCurrentUser(Object, Number/Array, String); 285 | ``` 286 | 287 | ## AuthService.unsetCurrentUser 288 | This method removes the AuthCurrentUser. 289 | Returns `true {Boolean}`. 290 | 291 | ```javascript 292 | AuthService.unsetCurrentUser(); 293 | ``` 294 | 295 | ## AuthService.getCurrentUser 296 | Returns `AuthCurrentUser {Object}` if the user is logged in, `null {Null}` otherwise. 297 | 298 | ```javascript 299 | AuthService.getCurrentUser(); 300 | ``` 301 | 302 | ## AuthService.getAuthenticationToken 303 | Returns `{String}` if the user is logged in, `null {Null}` otherwise. 304 | 305 | ```javascript 306 | AuthService.getAuthenticationToken(); 307 | ``` 308 | 309 | 310 | ## AuthService.isUserLoggedIn 311 | Returns `{Boolean}`. 312 | 313 | ```javascript 314 | AuthService.isUserLoggedIn(); 315 | ``` 316 | 317 | 318 | ## AuthService.authorize 319 | This method checks if the AuthCurrentUser is authorized, is called on each $stateChangeStart and hitmands.auth:update events. 320 | Returns `{Boolean}`. 321 | 322 | PARAM | TYPE | DESCRIPTION 323 | ------------------- | ------------------- | ------------- 324 | state | Object | The state (ui-router.$state) object. 325 | user (optional) | Object | Default `AuthCurrentUser|Null` 326 | 327 | ```javascript 328 | AuthService.authorize(State, User); 329 | ``` 330 | 331 | 332 | ## AuthService.fetch 333 | This method performs a **$http GET request** to routes.fetch, updates the AuthCurrentUser Object and triggers the 'hitmands.auth:fetch.success' or 'hitmands.auth:fetch.error' angular event. 334 | Returns `{Promise}`. 335 | 336 | ```javascript 337 | AuthService.fetch(); 338 | ``` 339 | 340 | ## AuthService.login 341 | This method performs a **$http POST request** to routes.login, updates the AuthCurrentUser Object and triggers the 'hitmands.auth:login.success' or 'hitmands.auth:login.error' angular event. This method is also invoked by [login directive](#module-directives-login). 342 | Returns `{Promise}`. 343 | 344 | PARAM | TYPE | DESCRIPTION 345 | ------------------- | ------------------- | ------------- 346 | credentials | Object | An object to send, if the Basic Access Authentication is enabled, the following properties are required: username, password. 347 | 348 | ```javascript 349 | AuthService.login(); 350 | ``` 351 | 352 | ## AuthService.logout 353 | This method performs a **$http POST request** to routes.logout, removes the AuthCurrentUser Object and triggers the 'hitmands.auth:logout.success' or 'hitmands.auth:logout.error' angular event. This method is also invoked by [logout directive](#module-directives-logout). 354 | Returns `{Promise}`. 355 | 356 | ```javascript 357 | AuthService.logout() 358 | ``` 359 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-hitmands-auth", 3 | "version": "1.1.0", 4 | "homepage": "https://github.com/hitmands/angular-hitmands-auth", 5 | "authors": [ 6 | "Giuseppe Mandato " 7 | ], 8 | "description": "Angular Module for Authentication Managements", 9 | "keywords": [ 10 | "AngularJS", 11 | "Auth", 12 | "User Authentication" 13 | ], 14 | "license": "MIT", 15 | "main": "release/angular-hitmands-auth.js", 16 | "ignore": [ 17 | "**/.*", 18 | "node_modules", 19 | "bower_components", 20 | "./src/vendor", 21 | "test", 22 | "server.js", 23 | ".gitignore", 24 | ".editorconfig", 25 | "Gruntfile.js", 26 | "config/", 27 | "package.json", 28 | "tests", 29 | "sample" 30 | ], 31 | "dependencies": { 32 | "angular": "1.3.14", 33 | "angular-ui-router": "0.2.13" 34 | }, 35 | "devDependencies": { 36 | "bootstrap": "https://github.com/angular-ui/bootstrap.git#~0.12.1", 37 | "angular-sanitize": "1.3.10", 38 | "angular-mocks": "1.3.10", 39 | "angular-bootstrap": "~0.12.1", 40 | "ngprogress-lite": "1.0.7", 41 | "angular-hitmands-auth": "master" 42 | }, 43 | "resolutions": { 44 | "angular": "1.3.14" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /config/karma.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Sun Oct 26 2014 12:21:57 GMT+0100 (CET) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '..', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['jasmine'], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | 'src/vendor/angular/angular.js', 19 | 'src/vendor/angular-mocks/angular-mocks.js', 20 | 'src/vendor/angular-ui-router/release/angular-ui-router.js', 21 | 'specs/**/*.js', 22 | 'release/angular-hitmands-auth.js' 23 | ], 24 | 25 | 26 | // list of files to exclude 27 | exclude: [ 28 | 'src/vendor/' 29 | ], 30 | 31 | 32 | // preprocess matching files before serving them to the browser 33 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 34 | preprocessors: { 35 | './release/*.js': ['coverage'] 36 | }, 37 | 38 | 39 | // test results reporter to use 40 | // possible values: 'dots', 'progress' 41 | // available reporters: 42 | reporters: ['progress', 'coverage'], 43 | coverageReporter: { 44 | type : 'lcov', 45 | dir : './coverage/' 46 | }, 47 | 48 | // web server port 49 | port: 9876, 50 | 51 | 52 | // enable / disable colors in the output (reporters and logs) 53 | colors: true, 54 | 55 | 56 | // level of logging 57 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 58 | logLevel: config.LOG_INFO, 59 | 60 | 61 | // enable / disable watching file and executing tests whenever any file changes 62 | autoWatch: true, 63 | 64 | // start these browsers 65 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 66 | browsers: ['PhantomJS'], 67 | 68 | 69 | // Continuous Integration mode 70 | // if true, Karma captures browsers, runs the tests and exits 71 | singleRun: false 72 | }); 73 | }; 74 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./release/angular-hitmands-auth.js'); 2 | module.exports = 'hitmands.auth'; 3 | -------------------------------------------------------------------------------- /lcov.info: -------------------------------------------------------------------------------- 1 | TN: 2 | SF:./release/angular-hitmands-auth.js 3 | FN:16,(anonymous_1) 4 | FN:20,AuthModuleRun 5 | FN:21,redirect 6 | FN:22,(anonymous_4) 7 | FN:27,(anonymous_5) 8 | FN:40,(anonymous_6) 9 | FN:47,_validAuthData 10 | FN:54,_authorizeLevelBased 11 | FN:59,_inArray 12 | FN:75,AuthServiceProviderFactory 13 | FN:82,AuthServiceDisableAutoRoutingProtection 14 | FN:91,AuthServiceSetRedirectPath 15 | FN:102,AuthServiceRoutesListSetter 16 | FN:114,AuthServiceTokenizeHttp 17 | FN:119,AuthServiceInterceptor 18 | FN:121,AuthServiceRequestTransform 19 | FN:138,AuthServiceUseHttpHeaderAuthorization 20 | FN:148,AuthServiceLoggedUserSetter 21 | FN:161,AuthServiceExpectDataAs 22 | FN:165,AuthServiceFactory 23 | FN:166,_setLoggedUser 24 | FN:169,(anonymous_22) 25 | FN:182,(anonymous_23) 26 | FN:193,(anonymous_24) 27 | FN:198,(anonymous_25) 28 | FN:210,(anonymous_26) 29 | FN:213,(anonymous_27) 30 | FN:218,(anonymous_28) 31 | FN:230,(anonymous_29) 32 | FN:233,(anonymous_30) 33 | FN:237,(anonymous_31) 34 | FN:249,(anonymous_32) 35 | FN:259,(anonymous_33) 36 | FN:267,(anonymous_34) 37 | FN:275,(anonymous_35) 38 | FN:284,(anonymous_36) 39 | FN:314,(anonymous_37) 40 | FN:321,(anonymous_38) 41 | FN:330,AuthLoginDirectiveFactory 42 | FN:333,(anonymous_40) 43 | FN:340,(anonymous_41) 44 | FN:354,(anonymous_42) 45 | FN:363,AuthLogoutDirectiveFactory 46 | FN:364,(anonymous_44) 47 | FN:365,(anonymous_45) 48 | FN:368,(anonymous_46) 49 | FN:376,AuthClassesDirectiveFactory 50 | FN:385,(anonymous_48) 51 | FN:386,_toggleClass 52 | FN:399,(anonymous_50) 53 | FN:426,(anonymous_51) 54 | FN:427,AuthCurrentUser 55 | FNF:52 56 | FNH:52 57 | FNDA:1,(anonymous_1) 58 | FNDA:72,AuthModuleRun 59 | FNDA:3,redirect 60 | FNDA:3,(anonymous_4) 61 | FNDA:4,(anonymous_5) 62 | FNDA:8,(anonymous_6) 63 | FNDA:61,_validAuthData 64 | FNDA:15,_authorizeLevelBased 65 | FNDA:13,_inArray 66 | FNDA:72,AuthServiceProviderFactory 67 | FNDA:1,AuthServiceDisableAutoRoutingProtection 68 | FNDA:2,AuthServiceSetRedirectPath 69 | FNDA:21,AuthServiceRoutesListSetter 70 | FNDA:6,AuthServiceTokenizeHttp 71 | FNDA:6,AuthServiceInterceptor 72 | FNDA:6,AuthServiceRequestTransform 73 | FNDA:3,AuthServiceUseHttpHeaderAuthorization 74 | FNDA:43,AuthServiceLoggedUserSetter 75 | FNDA:13,AuthServiceExpectDataAs 76 | FNDA:72,AuthServiceFactory 77 | FNDA:38,_setLoggedUser 78 | FNDA:11,(anonymous_22) 79 | FNDA:7,(anonymous_23) 80 | FNDA:5,(anonymous_24) 81 | FNDA:2,(anonymous_25) 82 | FNDA:3,(anonymous_26) 83 | FNDA:2,(anonymous_27) 84 | FNDA:1,(anonymous_28) 85 | FNDA:3,(anonymous_29) 86 | FNDA:2,(anonymous_30) 87 | FNDA:1,(anonymous_31) 88 | FNDA:18,(anonymous_32) 89 | FNDA:12,(anonymous_33) 90 | FNDA:29,(anonymous_34) 91 | FNDA:27,(anonymous_35) 92 | FNDA:27,(anonymous_36) 93 | FNDA:3,(anonymous_37) 94 | FNDA:6,(anonymous_38) 95 | FNDA:4,AuthLoginDirectiveFactory 96 | FNDA:4,(anonymous_40) 97 | FNDA:3,(anonymous_41) 98 | FNDA:1,(anonymous_42) 99 | FNDA:2,AuthLogoutDirectiveFactory 100 | FNDA:2,(anonymous_44) 101 | FNDA:1,(anonymous_45) 102 | FNDA:1,(anonymous_46) 103 | FNDA:3,AuthClassesDirectiveFactory 104 | FNDA:3,(anonymous_48) 105 | FNDA:4,_toggleClass 106 | FNDA:1,(anonymous_50) 107 | FNDA:1,(anonymous_51) 108 | FNDA:21,AuthCurrentUser 109 | DA:16,1 110 | DA:20,1 111 | DA:21,1 112 | DA:22,3 113 | DA:23,3 114 | DA:26,72 115 | DA:27,13 116 | DA:28,4 117 | DA:29,2 118 | DA:30,2 119 | DA:31,2 120 | DA:37,2 121 | DA:40,13 122 | DA:41,8 123 | DA:45,1 124 | DA:47,1 125 | DA:48,61 126 | DA:49,61 127 | DA:50,61 128 | DA:51,61 129 | DA:54,1 130 | DA:55,15 131 | DA:56,15 132 | DA:59,1 133 | DA:60,13 134 | DA:61,13 135 | DA:62,1 136 | DA:64,12 137 | DA:65,13 138 | DA:66,13 139 | DA:67,4 140 | DA:71,8 141 | DA:75,1 142 | DA:76,72 143 | DA:82,72 144 | DA:83,1 145 | DA:84,1 146 | DA:91,72 147 | DA:92,2 148 | DA:102,72 149 | DA:103,21 150 | DA:104,21 151 | DA:114,72 152 | DA:115,6 153 | DA:116,1 154 | DA:117,1 155 | DA:119,6 156 | DA:120,6 157 | DA:122,6 158 | DA:123,5 159 | DA:124,5 160 | DA:127,6 161 | DA:132,6 162 | DA:138,72 163 | DA:139,3 164 | DA:140,3 165 | DA:148,72 166 | DA:149,43 167 | DA:150,22 168 | DA:151,22 169 | DA:153,43 170 | DA:154,43 171 | DA:155,43 172 | DA:161,72 173 | DA:162,13 174 | DA:163,13 175 | DA:165,72 176 | DA:166,1 177 | DA:167,38 178 | DA:168,38 179 | DA:169,38 180 | DA:170,11 181 | DA:173,72 182 | DA:174,72 183 | DA:183,7 184 | DA:186,7 185 | DA:187,3 186 | DA:190,3 187 | DA:191,3 188 | DA:193,7 189 | DA:194,5 190 | DA:195,2 191 | DA:196,2 192 | DA:197,2 193 | DA:199,2 194 | DA:200,2 195 | DA:201,2 196 | DA:211,3 197 | DA:214,2 198 | DA:215,1 199 | DA:216,1 200 | DA:217,1 201 | DA:219,1 202 | DA:220,1 203 | DA:221,1 204 | DA:231,3 205 | DA:234,2 206 | DA:235,2 207 | DA:236,2 208 | DA:238,1 209 | DA:239,1 210 | DA:240,1 211 | DA:250,18 212 | DA:251,1 213 | DA:253,17 214 | DA:254,17 215 | DA:260,12 216 | DA:261,12 217 | DA:268,29 218 | DA:276,27 219 | DA:285,27 220 | DA:286,27 221 | DA:287,27 222 | DA:288,1 223 | DA:289,1 224 | DA:291,26 225 | DA:292,26 226 | DA:293,26 227 | DA:295,26 228 | DA:296,26 229 | DA:298,26 230 | DA:299,15 231 | DA:301,11 232 | DA:302,10 233 | DA:304,1 234 | DA:305,1 235 | DA:315,3 236 | DA:322,6 237 | DA:327,1 238 | DA:330,1 239 | DA:331,4 240 | DA:334,4 241 | DA:335,4 242 | DA:336,4 243 | DA:337,4 244 | DA:338,4 245 | DA:340,4 246 | DA:341,3 247 | DA:342,1 248 | DA:343,1 249 | DA:348,2 250 | DA:349,1 251 | DA:350,1 252 | DA:352,1 253 | DA:354,4 254 | DA:355,1 255 | DA:360,1 256 | DA:363,1 257 | DA:364,2 258 | DA:365,2 259 | DA:366,1 260 | DA:368,2 261 | DA:369,1 262 | DA:373,1 263 | DA:376,1 264 | DA:377,3 265 | DA:382,3 266 | DA:386,1 267 | DA:387,4 268 | DA:388,4 269 | DA:389,2 270 | DA:390,2 271 | DA:392,2 272 | DA:393,2 273 | DA:395,2 274 | DA:398,3 275 | DA:399,3 276 | DA:400,1 277 | DA:405,1 278 | DA:407,1 279 | DA:427,1 280 | DA:429,21 281 | DA:430,16 282 | DA:433,21 283 | DA:438,1 284 | DA:441,1 285 | LF:176 286 | LH:176 287 | BRDA:26,1,0,13 288 | BRDA:26,1,1,59 289 | BRDA:28,2,0,2 290 | BRDA:28,2,1,2 291 | BRDA:32,3,0,1 292 | BRDA:32,3,1,1 293 | BRDA:33,4,0,1 294 | BRDA:33,4,1,1 295 | BRDA:37,5,0,2 296 | BRDA:37,5,1,2 297 | BRDA:41,6,0,8 298 | BRDA:41,6,1,1 299 | BRDA:49,7,0,61 300 | BRDA:49,7,1,60 301 | BRDA:49,7,2,22 302 | BRDA:50,8,0,61 303 | BRDA:50,8,1,39 304 | BRDA:50,8,2,23 305 | BRDA:55,9,0,15 306 | BRDA:55,9,1,2 307 | BRDA:60,10,0,3 308 | BRDA:60,10,1,10 309 | BRDA:61,11,0,1 310 | BRDA:61,11,1,12 311 | BRDA:66,12,0,4 312 | BRDA:66,12,1,9 313 | BRDA:115,13,0,1 314 | BRDA:115,13,1,5 315 | BRDA:122,14,0,5 316 | BRDA:122,14,1,1 317 | BRDA:124,15,0,5 318 | BRDA:124,15,1,2 319 | BRDA:149,16,0,22 320 | BRDA:149,16,1,21 321 | BRDA:153,17,0,21 322 | BRDA:153,17,1,22 323 | BRDA:162,18,0,13 324 | BRDA:162,18,1,9 325 | BRDA:170,19,0,11 326 | BRDA:170,19,1,6 327 | BRDA:173,20,0,72 328 | BRDA:173,20,1,63 329 | BRDA:186,21,0,3 330 | BRDA:186,21,1,4 331 | BRDA:188,22,0,3 332 | BRDA:188,22,1,1 333 | BRDA:188,23,0,3 334 | BRDA:188,23,1,1 335 | BRDA:250,24,0,1 336 | BRDA:250,24,1,17 337 | BRDA:286,25,0,27 338 | BRDA:286,25,1,22 339 | BRDA:287,26,0,1 340 | BRDA:287,26,1,26 341 | BRDA:291,27,0,26 342 | BRDA:291,27,1,9 343 | BRDA:291,28,0,2 344 | BRDA:291,28,1,24 345 | BRDA:298,29,0,15 346 | BRDA:298,29,1,11 347 | BRDA:301,30,0,10 348 | BRDA:301,30,1,1 349 | BRDA:335,31,0,2 350 | BRDA:335,31,1,2 351 | BRDA:336,32,0,2 352 | BRDA:336,32,1,2 353 | BRDA:341,33,0,1 354 | BRDA:341,33,1,2 355 | BRDA:348,34,0,1 356 | BRDA:348,34,1,1 357 | BRDA:348,35,0,2 358 | BRDA:348,35,1,2 359 | BRDA:388,36,0,2 360 | BRDA:388,36,1,2 361 | BRDA:430,37,0,16 362 | BRDA:430,37,1,16 363 | BRDA:430,37,2,16 364 | BRDA:435,38,0,21 365 | BRDA:435,38,1,4 366 | BRF:79 367 | BRH:79 368 | end_of_record 369 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-hitmands-auth", 3 | "version": "1.1.0", 4 | "homepage": "https://github.com/hitmands/angular-hitmands-auth", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/hitmands/angular-hitmands-auth.git" 9 | }, 10 | "keywords": [ 11 | "AngularJS", 12 | "Auth", 13 | "User Authentication" 14 | ], 15 | "authors": [ 16 | "Giuseppe Mandato " 17 | ], 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/hitmands/angular-hitmands-auth/issues" 21 | }, 22 | "devDependencies": { 23 | "karma": "~0.12.24", 24 | "karma-jasmine": "~0.1.5", 25 | "codeclimate-test-reporter": "0.0.4", 26 | "karma-phantomjs-launcher": "~0.1.4", 27 | "karma-coverage": "~0.2.6", 28 | "grunt-shell": "~1.1.1" 29 | }, 30 | "dependencies": { 31 | "express": "^4.12.0", 32 | "grunt": "~0.4.2", 33 | "grunt-angular-templates": "^0.5.7", 34 | "grunt-contrib-concat": "~0.5.0", 35 | "grunt-contrib-htmlmin": "^0.4.0", 36 | "grunt-contrib-jshint": "~0.10.0", 37 | "grunt-contrib-symlink": "~0.3.0", 38 | "grunt-contrib-uglify": "~0.6.0", 39 | "grunt-contrib-watch": "~0.6.1", 40 | "grunt-githooks": "~0.3.1", 41 | "grunt-inline": "^0.3.4", 42 | "grunt-newer": "~0.8.0", 43 | "grunt-ng-annotate": "~0.4.0", 44 | "htmlmin": "0.0.2", 45 | "jit-grunt": "~0.9.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /release/angular-hitmands-auth.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * @Project: angular-hitmands-auth 3 | * @Authors: Giuseppe Mandato 4 | * @Link: https://github.com/hitmands/angular-hitmands-auth 5 | * @License: MIT 6 | * @Date: 2015-04-18 7 | * @Version: 1.1.0 8 | * 9 | * @ngdoc: module 10 | * @namespace: hitmands 11 | * @name: auth 12 | * @module: hitmands.auth 13 | * @description: Full Implementation of an authentication management system. 14 | ***/ 15 | 16 | (function(window, angular) { 17 | 'use strict'; 18 | 19 | /* @ngInject */ 20 | function AuthModuleRun($rootScope, AuthService, $state, $location, $timeout) { 21 | function redirect() { 22 | $timeout(function() { 23 | $location.path(routes.__redirectPath__); 24 | }, 0); 25 | } 26 | if (AUTO_ROUTING_PROTECTION) { 27 | $rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) { 28 | if (!AuthService.authorize(toState, AuthService.getCurrentUser())) { 29 | event.preventDefault(); 30 | var _isUserLoggedIn = AuthService.isUserLoggedIn(); 31 | $rootScope.$broadcast("$stateChangeError", toState, toParams, fromState, fromParams, { 32 | "statusCode": _isUserLoggedIn ? 403 : 401, 33 | "statusText": _isUserLoggedIn ? "Forbidden" : "Unauthorized", 34 | "isUserLoggedIn": _isUserLoggedIn, 35 | "publisher": "AuthService.authorize" 36 | }); 37 | fromState.name || redirect(); 38 | } 39 | }); 40 | $rootScope.$on(EVENTS.update, function(event) { 41 | AuthService.authorize($state.current, AuthService.getCurrentUser()) || redirect(); 42 | }); 43 | } 44 | } 45 | AuthModuleRun.$inject = ['$rootScope', 'AuthService', '$state', '$location', '$timeout']; 46 | 47 | function _validAuthData(userData, token) { 48 | var res = !0; 49 | (angular.isArray(userData) || !angular.isObject(userData)) && (res = !1); 50 | (!angular.isString(token) || token.length < 1) && (res = !1); 51 | return res; 52 | } 53 | 54 | function _authorizeLevelBased(stateAuthLevel, userAuthLevel) { 55 | angular.isNumber(userAuthLevel) || (userAuthLevel = 0); 56 | return userAuthLevel >= stateAuthLevel; 57 | } 58 | 59 | function _inArray(haystack, needle) { 60 | needle = angular.isArray(needle) ? needle : [ needle ]; 61 | if (haystack.length < 1) { 62 | return !0; 63 | } 64 | for (var i = 0, len = haystack.length; len > i; i++) { 65 | for (var j = 0, jLen = needle.length; jLen > j; j++) { 66 | if (angular.equals(haystack[i], needle[j])) { 67 | return !0; 68 | } 69 | } 70 | } 71 | return !1; 72 | } 73 | 74 | /* @ngInject */ 75 | function AuthServiceProviderFactory($httpProvider) { 76 | var _dataParser, self = this, isBasicAuthEnabled = !1; 77 | /** 78 | * @preserve 79 | * 80 | * Disables the auto routing protection 81 | */ 82 | self.disableAutoRoutingProtection = function AuthServiceDisableAutoRoutingProtection() { 83 | AUTO_ROUTING_PROTECTION = !1; 84 | return self; 85 | }; 86 | /** 87 | * @preserve 88 | * 89 | * Set a redirection path used by $location.path(). 90 | */ 91 | self.setRedirectPath = function AuthServiceSetRedirectPath(path) { 92 | return self.useRoutes({ 93 | "__redirectPath__": path 94 | }); 95 | }; 96 | /** 97 | * Extends Used Routes 98 | * 99 | * @preserve 100 | * @param {Object} [newRoutes = {login: String, logout: String, fetch: String}] 101 | */ 102 | self.useRoutes = function AuthServiceRoutesListSetter(newRoutes) { 103 | routes = angular.extend(routes, newRoutes); 104 | return self; 105 | }; 106 | /** 107 | * Appends Authentication Token to all $httpRequests 108 | * If a function is passed as second parameter is passed, it will be invoked for all $httpResponses with the config object 109 | * 110 | * @preserve 111 | * @param {String} [tokenKey = 'x-auth-token'] - The Name of the header Key, default x-auth-token 112 | * @param {Function} [responseErrorInterceptor] - if function passed, it will be invoked on every $httpResponseError with the config object 113 | */ 114 | self.tokenizeHttp = function AuthServiceTokenizeHttp(tokenKey, responseErrorInterceptor) { 115 | if (angular.isFunction(tokenKey)) { 116 | responseErrorInterceptor = tokenKey; 117 | tokenKey = void 0; 118 | } 119 | $httpProvider.interceptors.push(function AuthServiceInterceptor() { 120 | return { 121 | "request": function AuthServiceRequestTransform(config) { 122 | if (currentUser instanceof AuthCurrentUser) { 123 | try { 124 | config.headers[tokenKey || "x-auth-token"] = authToken; 125 | } catch (error) {} 126 | } 127 | return config; 128 | }, 129 | "responseError": responseErrorInterceptor 130 | }; 131 | }); 132 | return self; 133 | }; 134 | /** 135 | * Encrypts login requests like headers['Authorization'] = 'Basic' + ' ' + btoa(credentials.username + ':' + credentials.password) 136 | * @preserve 137 | */ 138 | self.useBasicAuthentication = function AuthServiceUseHttpHeaderAuthorization() { 139 | isBasicAuthEnabled = !0; 140 | return self; 141 | }; 142 | /** 143 | * @preserve 144 | * @param {Object|Null} [userData=null] 145 | * @param {String|Null} [authenticationToken=null] 146 | * @param {Number|Array|Null} authLevel 147 | */ 148 | self.setLoggedUser = function AuthServiceLoggedUserSetter(userData, authenticationToken, authLevel) { 149 | if (!_validAuthData(userData, authenticationToken)) { 150 | userData = null; 151 | authenticationToken = null; 152 | } 153 | currentUser = userData ? new AuthCurrentUser(userData, authLevel) : null; 154 | authToken = authenticationToken; 155 | return self; 156 | }; 157 | /** 158 | * @preserve 159 | * @param {Requester~requestCallback} callback - The callback that handles the $http response. 160 | */ 161 | self.parseHttpAuthData = function AuthServiceExpectDataAs(callback) { 162 | angular.isFunction(callback) && (_dataParser = callback); 163 | return self; 164 | }; 165 | self.$get = ['$rootScope', '$http', '$state', '$exceptionHandler', '$timeout', '$q', '$injector', function AuthServiceFactory($rootScope, $http, $state, $exceptionHandler, $timeout, $q, $injector) { 166 | function _setLoggedUser(newUserData, newAuthToken, newAuthLevel) { 167 | self.setLoggedUser(newUserData, newAuthToken, newAuthLevel); 168 | $rootScope.$broadcast(EVENTS.update); 169 | $timeout(function() { 170 | $rootScope.$$phase || $rootScope.$digest(); 171 | }, 0); 172 | } 173 | angular.isFunction(_dataParser) || $exceptionHandler("AuthServiceProvider.parseHttpAuthData", "You need to set a Callback that handles the $http response. ", "https://github.com/hitmands/angular-hitmands-auth#module-provider-parsehttpauthdata"); 174 | return { 175 | /** 176 | * Performs Login Request and sets the Auth Data 177 | * 178 | * @preserve 179 | * @param {{username: String, password: String}} credentials 180 | * @returns {ng.IPromise} 181 | */ 182 | "login": function(credentials) { 183 | var configs = { 184 | "cache": !1 185 | }; 186 | if (isBasicAuthEnabled) { 187 | configs.headers = { 188 | "Authorization": "Basic " + window.btoa((credentials.username || "") + ":" + (credentials.password || "")) 189 | }; 190 | delete credentials.username; 191 | delete credentials.password; 192 | } 193 | return $http.post(routes.login, credentials, configs).then(function(result) { 194 | var data = _dataParser(result.data, result.headers(), result.status); 195 | _setLoggedUser(data.user, data.token, data.authLevel); 196 | $rootScope.$broadcast(EVENTS.login.success, result); 197 | return result; 198 | }, function(error) { 199 | _setLoggedUser(); 200 | $rootScope.$broadcast(EVENTS.login.error, error); 201 | return $q.reject(error); 202 | }); 203 | }, 204 | /** 205 | * Updates the Auth Data 206 | * 207 | * @preserve 208 | * @returns {ng.IPromise} 209 | */ 210 | "fetch": function() { 211 | return $http.get(routes.fetch, { 212 | "cache": !1 213 | }).then(function(result) { 214 | var data = _dataParser(result.data, result.headers(), result.status); 215 | _setLoggedUser(data.user, data.token, data.authLevel); 216 | $rootScope.$broadcast(EVENTS.fetch.success, result); 217 | return result; 218 | }, function(error) { 219 | _setLoggedUser(); 220 | $rootScope.$broadcast(EVENTS.fetch.error, error); 221 | return $q.reject(error); 222 | }); 223 | }, 224 | /** 225 | * Performs Logout request 226 | * 227 | * @preserve 228 | * @returns {ng.IPromise} 229 | */ 230 | "logout": function() { 231 | return $http.post(routes.logout, null, { 232 | "cache": !1 233 | }).then(function(result) { 234 | _setLoggedUser(); 235 | $rootScope.$broadcast(EVENTS.logout.success, result); 236 | return result; 237 | }, function(error) { 238 | _setLoggedUser(); 239 | $rootScope.$broadcast(EVENTS.logout.error, error); 240 | return $q.reject(error); 241 | }); 242 | }, 243 | /** 244 | * @preserve 245 | * @param {Object} user 246 | * @param {Number|Array} authLevel 247 | * @param {String} authenticationToken 248 | */ 249 | "setCurrentUser": function(user, authLevel, authenticationToken) { 250 | if (!_validAuthData(user, authenticationToken)) { 251 | return !1; 252 | } 253 | _setLoggedUser(user, authenticationToken, authLevel); 254 | return !0; 255 | }, 256 | /** 257 | * @preserve 258 | */ 259 | "unsetCurrentUser": function() { 260 | _setLoggedUser(); 261 | return !0; 262 | }, 263 | /** 264 | * @preserve 265 | * @returns {Object|Null} - Current User Data 266 | */ 267 | "getCurrentUser": function() { 268 | return currentUser; 269 | }, 270 | /** 271 | * @preserve 272 | * Checks if the user is logged in 273 | * @returns {Boolean} 274 | */ 275 | "isUserLoggedIn": function() { 276 | return currentUser instanceof AuthCurrentUser; 277 | }, 278 | /** 279 | * @preserve 280 | * @param {Object} state 281 | * @param {Object} [user = currentUser] 282 | * @returns {Boolean} 283 | */ 284 | "authorize": function(state, user) { 285 | var userAuthLevel = 0; 286 | user = user || currentUser; 287 | if (!angular.isObject(state)) { 288 | $exceptionHandler("AuthService.authorize", "first param must be Object"); 289 | return !1; 290 | } 291 | var stateAuthLevel = (state.data ? state.data[AUTH_PROPERTY] : state[AUTH_PROPERTY]) || 0; 292 | try { 293 | userAuthLevel = user[AUTH_PROPERTY]; 294 | } catch (e) {} 295 | try { 296 | stateAuthLevel = $injector.invoke(stateAuthLevel); 297 | } catch (e) {} 298 | if (angular.isNumber(stateAuthLevel)) { 299 | return _authorizeLevelBased(stateAuthLevel, userAuthLevel); 300 | } 301 | if (angular.isArray(stateAuthLevel)) { 302 | return _inArray(stateAuthLevel, userAuthLevel); 303 | } 304 | $exceptionHandler("AuthService.authorize", "Cannot process authorization"); 305 | return !1; 306 | }, 307 | /** 308 | * @preserve 309 | * @param needle {String|Array} 310 | * @param haystack {Array} 311 | * 312 | * @returns {Boolean} 313 | */ 314 | "check": function(needle, haystack) { 315 | return _inArray(haystack, needle); 316 | }, 317 | /** 318 | * @preserve 319 | * @returns {String|Null} - The Authentication Token 320 | */ 321 | "getAuthenticationToken": function() { 322 | return authToken; 323 | } 324 | }; 325 | }]; 326 | } 327 | AuthServiceProviderFactory.$inject = ['$httpProvider']; 328 | 329 | /* @ngInject */ 330 | function AuthLoginDirectiveFactory(AuthService) { 331 | return { 332 | "restrict": "A", 333 | "link": function(iScope, iElement, iAttributes) { 334 | var _form = null, credentials = iScope[iAttributes.authLogin], resolve = iScope.$eval(iAttributes.authLoginOnResolve), reject = iScope.$eval(iAttributes.authLoginOnReject); 335 | resolve = angular.isFunction(resolve) ? resolve : angular.noop; 336 | reject = angular.isFunction(reject) ? reject : angular.noop; 337 | try { 338 | _form = iScope[iElement.attr("name")]; 339 | } catch (error) {} 340 | iElement.bind("submit", function(event) { 341 | if (!angular.isObject(credentials)) { 342 | event.preventDefault(); 343 | return reject({ 344 | "attrName": "auth-login", 345 | "attrValue": credentials 346 | }); 347 | } 348 | if (angular.isObject(_form) && _form.$invalid) { 349 | event.preventDefault(); 350 | return reject(_form.$error); 351 | } 352 | return AuthService.login(credentials).then(resolve, reject); 353 | }); 354 | iScope.$on("$destroy", function() { 355 | iElement.unbind("submit"); 356 | }); 357 | } 358 | }; 359 | } 360 | AuthLoginDirectiveFactory.$inject = ['AuthService']; 361 | 362 | /* @ngInject */ 363 | function AuthLogoutDirectiveFactory(AuthService) { 364 | return function(scope, element, attrs) { 365 | element.bind("click", function() { 366 | AuthService.logout(); 367 | }); 368 | scope.$on("$destroy", function() { 369 | element.unbind("click"); 370 | }); 371 | }; 372 | } 373 | AuthLogoutDirectiveFactory.$inject = ['AuthService']; 374 | 375 | /* @ngInject */ 376 | function AuthClassesDirectiveFactory(AuthService) { 377 | var classes = { 378 | "loggedIn": "user-is-logged-in", 379 | "notLoggedIn": "user-not-logged-in", 380 | "last": "" 381 | }; 382 | return { 383 | "restrict": "A", 384 | "scope": !1, 385 | "link": function(iScope, iElement, iAttributes) { 386 | function _toggleClass() { 387 | var newClasses = ""; 388 | if (AuthService.isUserLoggedIn()) { 389 | try { 390 | newClasses = " user-has-role-" + AuthService.getCurrentUser()[AUTH_PROPERTY].join(" user-has-role-"); 391 | } catch (e) {} 392 | iAttributes.$updateClass(classes.loggedIn + newClasses, classes.notLoggedIn); 393 | classes.last = newClasses; 394 | } else { 395 | iAttributes.$updateClass(classes.notLoggedIn, classes.loggedIn + classes.last); 396 | } 397 | } 398 | _toggleClass(); 399 | iScope.$on(EVENTS.update, function() { 400 | _toggleClass(); 401 | }); 402 | } 403 | }; 404 | } 405 | AuthClassesDirectiveFactory.$inject = ['AuthService']; 406 | 407 | var AUTO_ROUTING_PROTECTION = !0, AUTH_PROPERTY = "authLevel", currentUser = null, authToken = null, routes = { 408 | "login": "/users/login", 409 | "logout": "/users/logout", 410 | "fetch": "/users/me", 411 | "__redirectPath__": "/" 412 | }, EVENTS = { 413 | "login": { 414 | "success": "hitmands.auth:login.resolved", 415 | "error": "hitmands.auth:login.rejected" 416 | }, 417 | "logout": { 418 | "success": "hitmands.auth:logout.resolved", 419 | "error": "hitmands.auth:logout.rejected" 420 | }, 421 | "fetch": { 422 | "success": "hitmands.auth:fetch.resolved", 423 | "error": "hitmands.auth:fetch.rejected" 424 | }, 425 | "update": "hitmands.auth:update" 426 | }, AuthCurrentUser = function() { 427 | function AuthCurrentUser(userData, authLevel) { 428 | /* jshint ignore:start */ 429 | for (var k in userData) { 430 | userData.hasOwnProperty(k) && k !== AUTH_PROPERTY && (this[k] = userData[k]); 431 | } 432 | /* jshint ignore:end */ 433 | Object.defineProperty(this, AUTH_PROPERTY, { 434 | "enumerable": !0, 435 | "value": authLevel || 0 436 | }); 437 | } 438 | return AuthCurrentUser; 439 | }.call(this); 440 | 441 | angular.module("hitmands.auth", [ "ui.router" ]).provider("AuthService", AuthServiceProviderFactory).directive("authLogin", AuthLoginDirectiveFactory).directive("authLogout", AuthLogoutDirectiveFactory).directive("authClasses", AuthClassesDirectiveFactory).run(AuthModuleRun); 442 | //# sourceMappingURL=angular-hitmands-auth.js.map 443 | 444 | })(window, angular); -------------------------------------------------------------------------------- /release/angular-hitmands-auth.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"angular-hitmands-auth.js","sources":["../src/auth-module.js","../src/auth-helpers.js","../src/auth-provider.js","../src/auth-directives.js"],"names":["AuthModuleRun","$rootScope","AuthService","$state","$location","$timeout","redirect","path","routes","__redirectPath__","AUTO_ROUTING_PROTECTION","$on","event","toState","toParams","fromState","fromParams","authorize","getCurrentUser","preventDefault","_isUserLoggedIn","isUserLoggedIn","$broadcast","statusCode","statusText","publisher","name","EVENTS","update","current","_validAuthData","userData","token","res","angular","isArray","isObject","isString","length","_authorizeLevelBased","stateAuthLevel","userAuthLevel","isNumber","_inArray","haystack","needle","i","len","j","jLen","equals","AuthServiceProviderFactory","$httpProvider","_dataParser","self","this","isBasicAuthEnabled","disableAutoRoutingProtection","AuthServiceDisableAutoRoutingProtection","setRedirectPath","AuthServiceSetRedirectPath","useRoutes","AuthServiceRoutesListSetter","newRoutes","extend","tokenizeHttp","AuthServiceTokenizeHttp","tokenKey","responseErrorInterceptor","isFunction","interceptors","push","AuthServiceInterceptor","request","AuthServiceRequestTransform","config","currentUser","AuthCurrentUser","headers","authToken","error","responseError","useBasicAuthentication","AuthServiceUseHttpHeaderAuthorization","setLoggedUser","AuthServiceLoggedUserSetter","authenticationToken","authLevel","parseHttpAuthData","AuthServiceExpectDataAs","callback","$get","AuthServiceFactory","$http","$exceptionHandler","$q","$injector","_setLoggedUser","newUserData","newAuthToken","newAuthLevel","$$phase","$digest","login","credentials","configs","cache","Authorization","window","btoa","username","password","post","then","result","data","status","user","success","reject","fetch","get","logout","setCurrentUser","unsetCurrentUser","state","AUTH_PROPERTY","e","invoke","check","getAuthenticationToken","AuthLoginDirectiveFactory","restrict","link","iScope","iElement","iAttributes","_form","resolve","$eval","noop","attr","bind","attrName","attrValue","$invalid","$error","unbind","AuthLogoutDirectiveFactory","scope","element","attrs","AuthClassesDirectiveFactory","classes","loggedIn","notLoggedIn","last","_toggleClass","newClasses","join","$updateClass","k","hasOwnProperty","Object","defineProperty","enumerable","value","call","module","provider","directive","run"],"mappings":";;;;GAoDA,SAASA,cAAcC,YAAYC,aAAaC,QAAQC,WAAWC;MAChE,SAASC;SACND,SAAS;YACND,UAAUG,KAAKC,OAAOC;YACtB;;MAGN,IAAGC,yBAAyB;SACzBT,WAAWU,IAAI,qBAAqB,SAASC,OAAOC,SAASC,UAAUC,WAAWC;YAE/E,KAAKd,YAAYe,UAAUJ,SAASX,YAAYgB,mBAAoB;eACjEN,MAAMO;eACN,IAAIC,kBAAkBlB,YAAYmB;eAElCpB,WAAWqB,WAAW,qBAAqBT,SAASC,UAAUC,WAAWC;kBACtEO,cAAYH,kBAAkB,MAAM;kBACpCI,cAAYJ,kBAAkB,cAAc;kBAC5CC,kBAAgBD;kBAChBK,aAAW;;eAGTV,UAAUW,QACZpB;;;SAKTL,WAAWU,IAAIgB,OAAOC,QAAQ,SAAShB;YAC/BV,YAAYe,UAAUd,OAAO0B,SAAS3B,YAAYgB,qBACpDZ;;;;;GC1EZ,SAASwB,eAAeC,UAAUC;MAC/B,IAAIC,OAAM;OAGPC,QAAQC,QAAQJ,cAAcG,QAAQE,SAAUL,eAChDE,OAAM;QAGLC,QAAQG,SAASL,UAAUA,MAAMM,SAAS,OAC3CL,OAAM;MAGT,OAAOA;;;GAUV,SAASM,qBAAsBC,gBAAgBC;MACvCP,QAAQQ,SAASD,mBACnBA,gBAAgB;MAGnB,OAASA,iBAAiBD;;;GAU7B,SAASG,SAAUC,UAAUC;MAC1BA,SAASX,QAAQC,QAAQU,UAAUA,WAAUA;MAE7C,IAAGD,SAASN,SAAS;SAClB,QAAO;;MAGV,KAAI,IAAIQ,IAAI,GAAGC,MAAMH,SAASN,QAAYS,MAAJD,GAASA;SAC5C,KAAI,IAAIE,IAAI,GAAGC,OAAOJ,OAAOP,QAAYW,OAAJD,GAAUA;YAC5C,IAAId,QAAQgB,OAAON,SAASE,IAAID,OAAOG;eACpC,QAAO;;;;MAKhB,QAAO;;;;GC1DV,SAASG,2BAA4BC;MAClC,IAAIC,aACAC,OAAOC,MACPC,sBAAqB;;;;;;MAQzBF,KAAKG,+BAA+B,SAASC;SAC1ChD,2BAA0B;SAE1B,OAAO4C;;;;;;;MAQVA,KAAKK,kBAAkB,SAASC,2BAA2BrD;SAExD,OAAO+C,KAAKO;YAAWpD,oBAAkBF;;;;;;;;;MAU5C+C,KAAKO,YAAY,SAASC,4BAA6BC;SACpDvD,SAAS0B,QAAQ8B,OAAOxD,QAAQuD;SAEhC,OAAOT;;;;;;;;;;MAWVA,KAAKW,eAAe,SAASC,wBAAyBC,UAAUC;SAC7D,IAAGlC,QAAQmC,WAAWF,WAAW;YAC9BC,2BAA2BD;YAC3BA,WAAW;;SAEdf,cAAckB,aAAaC,KAAK,SAASC;YAEtC;eACGC,WAAS,SAASC,4BAA4BC;kBAE3C,IAAGC,uBAAuBC;qBACvB;wBACGF,OAAOG,QAASX,YAAY,kBAAmBY;uBAChD,OAAMC;;kBAGX,OAAOL;;eAEVM,iBAAeb;;;SAIrB,OAAOd;;;;;;MAOVA,KAAK4B,yBAAyB,SAASC;SACpC3B,sBAAqB;SAErB,OAAOF;;;;;;;;MASVA,KAAK8B,gBAAgB,SAASC,4BAA6BtD,UAAUuD,qBAAqBC;SACvF,KAAKzD,eAAeC,UAAUuD,sBAAuB;YAElDvD,WAAW;YACXuD,sBAAsB;;SAGzBV,cAAc,WAAa,IAAIC,gBAAgB9C,UAAUwD,aAAa;SACtER,YAAYO;SAEZ,OAAOhC;;;;;;MAOVA,KAAKkC,oBAAoB,SAASC,wBAAyBC;SACpDxD,QAAQmC,WAAWqB,cAEpBrC,cAAcqC;SAGjB,OAAOpC;;MAIVA,KAAKqC,OAAO,SAASC,mBAAmB3F,YAAY4F,OAAO1F,QAAQ2F,mBAAmBzF,UAAU0F,IAAIC;SAWjG,SAASC,eAAgBC,aAAaC,cAAcC;YACjD9C,KAAK8B,cAAec,aAAaC,cAAcC;YAC/CnG,WAAWqB,WAAWK,OAAOC;YAE7BvB,SAAS;eACFJ,WAAWoG,WACZpG,WAAWqG;eAEd;;SAlBFpE,QAAQmC,WAAWhB,gBACpByC,kBAAkB,yCAAyC,gEAAgE;SAoB9H;;;;;;;;YASGS,SAAO,SAAUC;eACd,IAAIC;kBACDC,UAAO;;eAGV,IAAGlD,oBAAoB;kBACpBiD,QAAQ3B;qBACL6B,iBAAgB,WAAWC,OAAOC,MAAML,YAAYM,YAAY,MAAM,OAAON,YAAYO,YAAY;;yBAGjGP,YAAsB;yBACtBA,YAAsB;;eAGhC,OAAOX,MACHmB,KAAKxG,OAAO+F,OAAOC,aAAaC,SAChCQ,KACD,SAAUC;kBACP,IAAIC,OAAO9D,YAAY6D,OAAOC,MAAMD,OAAOpC,WAAWoC,OAAOE;kBAE7DnB,eAAgBkB,KAAKE,MAAMF,KAAKnF,OAAOmF,KAAK5B;kBAC5CtF,WAAWqB,WAAWK,OAAO4E,MAAMe,SAASJ;kBAE5C,OAAOA;kBAEV,SAAUlC;kBACPiB;kBACAhG,WAAWqB,WAAWK,OAAO4E,MAAMvB,OAAOA;kBAE1C,OAAOe,GAAGwB,OAAOvC;;;;;;;;;YAW1BwC,SAAO;eAEJ,OAAO3B,MACH4B,IAAIjH,OAAOgH;kBAASd,UAAO;kBAC3BO,KACD,SAAUC;kBACP,IAAIC,OAAO9D,YAAY6D,OAAOC,MAAMD,OAAOpC,WAAWoC,OAAOE;kBAE7DnB,eAAgBkB,KAAKE,MAAMF,KAAKnF,OAAOmF,KAAK5B;kBAC5CtF,WAAWqB,WAAWK,OAAO6F,MAAMF,SAASJ;kBAE5C,OAAOA;kBAEV,SAAUlC;kBACPiB;kBACAhG,WAAWqB,WAAWK,OAAO6F,MAAMxC,OAAOA;kBAE1C,OAAOe,GAAGwB,OAAOvC;;;;;;;;;YAW1B0C,UAAQ;eAEL,OAAO7B,MACHmB,KAAKxG,OAAOkH,QAAQ;kBAAQhB,UAAO;kBACnCO,KACD,SAAUC;kBACPjB;kBACAhG,WAAWqB,WAAWK,OAAO+F,OAAOJ,SAASJ;kBAE7C,OAAOA;kBAEV,SAAUlC;kBACPiB;kBACAhG,WAAWqB,WAAWK,OAAO+F,OAAO1C,OAAOA;kBAE3C,OAAOe,GAAGwB,OAAOvC;;;;;;;;;YAW1B2C,kBAAgB,SAASN,MAAM9B,WAAWD;eACvC,KAAKxD,eAAeuF,MAAM/B;kBACvB,QAAO;;eAGVW,eAAgBoB,MAAM/B,qBAAqBC;eAC3C,QAAO;;;;;YAMVqC,oBAAkB;eAEf3B;eACA,QAAO;;;;;;YAOV/E,kBAAgB;eAEb,OAAO0D;;;;;;;YAQVvD,kBAAgB;eAEb,OAAQuD,uBAAuBC;;;;;;;;YASlC5D,aAAW,SAAU4G,OAAOR;eACzB,IAAI5E,gBAAgB;eACpB4E,OAAOA,QAAQzC;eAEf,KAAK1C,QAAQE,SAASyF,QAAS;kBAC5B/B,kBAAkB,yBAAyB;kBAC3C,QAAO;;eAEV,IAAItD,kBAAkBqF,MAAMV,OAAOU,MAAMV,KAAKW,iBAAiBD,MAAMC,mBAAmB;eAExF;kBACGrF,gBAAgB4E,KAAKS;iBACtB,OAAMC;eAER;kBACGvF,iBAAiBwD,UAAUgC,OAAOxF;iBACnC,OAAMuF;eAER,IAAG7F,QAAQQ,SAASF;kBACjB,OAAOD,qBAAqBC,gBAAgBC;;eAG/C,IAAGP,QAAQC,QAAQK;kBAChB,OAAOG,SAASH,gBAAgBC;;eAGnCqD,kBAAkB,yBAAyB;eAC3C,QAAO;;;;;;;;;YAUVmC,SAAO,SAASpF,QAAQD;eAErB,OAAOD,SAASC,UAAUC;;;;;;YAO7BqF,0BAAwB;eAErB,OAAOnD;;;;;;;GC5UnB,SAASoD,0BAA0BjI;MAEhC;SACGkI,YAAU;SACVC,QAAM,SAASC,QAAQC,UAAUC;YAC9B,IAAIC,QAAQ,MACRjC,cAAc8B,OAAQE,YAAuB,YAE7CE,UAAUJ,OAAOK,MAAOH,YAAgC,qBACxDjB,SAASe,OAAOK,MAAOH,YAA+B;YAC1DE,UAAUxG,QAAQmC,WAAWqE,WAAWA,UAAUxG,QAAQ0G;YAC1DrB,SAASrF,QAAQmC,WAAWkD,UAAUA,SAASrF,QAAQ0G;YAGvD;eACGH,QAAQH,OAAOC,SAASM,KAAK;cAC9B,OAAO7D;YAGTuD,SAASO,KAAK,UAAU,SAAUlI;eAE/B,KAAKsB,QAAQE,SAASoE,cAAe;kBAClC5F,MAAMO;kBACN,OAAOoG;qBAASwB,YAAU;qBAAcC,aAAWxC;;;eAGtD,IAAItE,QAAQE,SAASqG,UAAUA,MAAMQ,UAAW;kBAC7CrI,MAAMO;kBACN,OAAOoG,OAAOkB,MAAMS;;eAEvB,OAAOhJ,YAAYqG,MAAMC,aAAaS,KAAKyB,SAASnB;;YAGvDe,OAAO3H,IAAI,YAAY;eACpB4H,SAASY,OAAO;;;;;;;GAO5B,SAASC,2BAA2BlJ;MAEjC,OAAO,SAASmJ,OAAOC,SAASC;SAE7BD,QAAQR,KAAK,SAAS;YACnB5I,YAAYwH;;SAGf2B,MAAM1I,IAAI,YAAY;YACnB2I,QAAQH,OAAO;;;;;;GAOxB,SAASK,4BAA4BtJ;MAClC,IAAIuJ;SACDC,YAAU;SACVC,eAAa;SACbC,QAAM;;MAGT;SACGxB,YAAU;SACViB,UAAO;SACPhB,QAAM,SAASC,QAAQC,UAAUC;YAC9B,SAASqB;eACN,IAAIC,aAAa;eAGjB,IAAI5J,YAAYmB,kBAAmB;kBAChC;qBACGyI,aAAa,oBAAoB5J,YAAYgB,iBAAiB4G,eAAeiC,KAAK;oBACnF,OAAMhC;kBAERS,YAAYwB,aAAaP,QAAQC,WAAWI,YAAYL,QAAQE;kBAChEF,QAAQG,OAAOE;;kBAEftB,YAAYwB,aAAaP,QAAQE,aAAaF,QAAQC,WAAWD,QAAQG;;;YAK/EC;YACAvB,OAAO3H,IAAIgB,OAAOC,QAAQ;eACvBiI;;;;;;GHnFZ,IAAInJ,2BAA0B,GAC1BoH,gBAAgB,aAChBlD,cAAc,MACdG,YAAY,MACZvE;MACD+F,SAAS;MACTmB,UAAU;MACVF,SAAS;MACT/G,oBAAoB;MAEnBkB;MACD4E;SACGe,WAAS;SACTtC,SAAO;;MAEV0C;SACGJ,WAAS;SACTtC,SAAO;;MAEVwC;SACGF,WAAS;SACTtC,SAAO;;MAEVpD,UAAQ;MAGPiD,kBAAkB;MACnB,SAASA,gBAAgB9C,UAAUwD;;SAGhC,KAAI,IAAI0E,KAAKlI;YACPA,SAASmI,eAAeD,MAAMA,MAAMnC,kBACpCvE,KAAK0G,KAAKlI,SAASkI;;;SAKzBE,OAAOC,eAAe7G,MAAMuE;YACzBuC,eAAY;YACZC,SAAO/E,aAAa;;;MAI1B,OAAOV;KACP0F,KAAKhH;;GAsCRrB,QACIsI,OAAO,mBAAkB,eACzBC,SAAS,eAAetH,4BACxBuH,UAAU,aAAavC,2BACvBuC,UAAU,cAActB,4BACxBsB,UAAU,eAAelB,6BACzBmB,IAAI3K"} -------------------------------------------------------------------------------- /release/angular-hitmands-auth.min.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * @Project: angular-hitmands-auth 3 | * @Authors: Giuseppe Mandato 4 | * @Link: https://github.com/hitmands/angular-hitmands-auth 5 | * @License: MIT 6 | * @Date: 2015-04-18 7 | * @Version: 1.1.0 8 | * 9 | * @ngdoc: module 10 | * @namespace: hitmands 11 | * @name: auth 12 | * @module: hitmands.auth 13 | * @description: Full Implementation of an authentication management system. 14 | ***/ 15 | 16 | !function(a,b){"use strict";function c(a,b,c,d,e){function f(){e(function(){d.path(o.__redirectPath__)},0)}k&&(a.$on("$stateChangeStart",function(c,d,e,g,h){if(!b.authorize(d,b.getCurrentUser())){c.preventDefault();var i=b.isUserLoggedIn();a.$broadcast("$stateChangeError",d,e,g,h,{statusCode:i?403:401,statusText:i?"Forbidden":"Unauthorized",isUserLoggedIn:i,publisher:"AuthService.authorize"}),g.name||f()}}),a.$on(p.update,function(){b.authorize(c.current,b.getCurrentUser())||f()}))}function d(a,c){var d=!0;return(b.isArray(a)||!b.isObject(a))&&(d=!1),(!b.isString(c)||c.length<1)&&(d=!1),d}function e(a,c){return b.isNumber(c)||(c=0),c>=a}function f(a,c){if(c=b.isArray(c)?c:[c],a.length<1)return!0;for(var d=0,e=a.length;e>d;d++)for(var f=0,g=c.length;g>f;f++)if(b.equals(a[d],c[f]))return!0;return!1}function g(c){var g,h=this,i=!1;h.disableAutoRoutingProtection=function(){return k=!1,h},h.setRedirectPath=function(a){return h.useRoutes({__redirectPath__:a})},h.useRoutes=function(a){return o=b.extend(o,a),h},h.tokenizeHttp=function(a,d){return b.isFunction(a)&&(d=a,a=void 0),c.interceptors.push(function(){return{request:function(b){if(m instanceof AuthCurrentUser)try{b.headers[a||"x-auth-token"]=n}catch(c){}return b},responseError:d}}),h},h.useBasicAuthentication=function(){return i=!0,h},h.setLoggedUser=function(a,b,c){return d(a,b)||(a=null,b=null),m=a?new AuthCurrentUser(a,c):null,n=b,h},h.parseHttpAuthData=function(a){return b.isFunction(a)&&(g=a),h},h.$get=["$rootScope","$http","$state","$exceptionHandler","$timeout","$q","$injector",function(c,j,k,q,r,s,t){function u(a,b,d){h.setLoggedUser(a,b,d),c.$broadcast(p.update),r(function(){c.$$phase||c.$digest()},0)}return b.isFunction(g)||q("AuthServiceProvider.parseHttpAuthData","You need to set a Callback that handles the $http response. ","https://github.com/hitmands/angular-hitmands-auth#module-provider-parsehttpauthdata"),{login:function(b){var d={cache:!1};return i&&(d.headers={Authorization:"Basic "+a.btoa((b.username||"")+":"+(b.password||""))},delete b.username,delete b.password),j.post(o.login,b,d).then(function(a){var b=g(a.data,a.headers(),a.status);return u(b.user,b.token,b.authLevel),c.$broadcast(p.login.success,a),a},function(a){return u(),c.$broadcast(p.login.error,a),s.reject(a)})},fetch:function(){return j.get(o.fetch,{cache:!1}).then(function(a){var b=g(a.data,a.headers(),a.status);return u(b.user,b.token,b.authLevel),c.$broadcast(p.fetch.success,a),a},function(a){return u(),c.$broadcast(p.fetch.error,a),s.reject(a)})},logout:function(){return j.post(o.logout,null,{cache:!1}).then(function(a){return u(),c.$broadcast(p.logout.success,a),a},function(a){return u(),c.$broadcast(p.logout.error,a),s.reject(a)})},setCurrentUser:function(a,b,c){return d(a,c)?(u(a,c,b),!0):!1},unsetCurrentUser:function(){return u(),!0},getCurrentUser:function(){return m},isUserLoggedIn:function(){return m instanceof AuthCurrentUser},authorize:function(a,c){var d=0;if(c=c||m,!b.isObject(a))return q("AuthService.authorize","first param must be Object"),!1;var g=(a.data?a.data[l]:a[l])||0;try{d=c[l]}catch(h){}try{g=t.invoke(g)}catch(h){}return b.isNumber(g)?e(g,d):b.isArray(g)?f(g,d):(q("AuthService.authorize","Cannot process authorization"),!1)},check:function(a,b){return f(b,a)},getAuthenticationToken:function(){return n}}}]}function h(a){return{restrict:"A",link:function(c,d,e){var f=null,g=c[e.authLogin],h=c.$eval(e.authLoginOnResolve),i=c.$eval(e.authLoginOnReject);h=b.isFunction(h)?h:b.noop,i=b.isFunction(i)?i:b.noop;try{f=c[d.attr("name")]}catch(j){}d.bind("submit",function(c){return b.isObject(g)?b.isObject(f)&&f.$invalid?(c.preventDefault(),i(f.$error)):a.login(g).then(h,i):(c.preventDefault(),i({attrName:"auth-login",attrValue:g}))}),c.$on("$destroy",function(){d.unbind("submit")})}}}function i(a){return function(b,c){c.bind("click",function(){a.logout()}),b.$on("$destroy",function(){c.unbind("click")})}}function j(a){var b={loggedIn:"user-is-logged-in",notLoggedIn:"user-not-logged-in",last:""};return{restrict:"A",scope:!1,link:function(c,d,e){function f(){var c="";if(a.isUserLoggedIn()){try{c=" user-has-role-"+a.getCurrentUser()[l].join(" user-has-role-")}catch(d){}e.$updateClass(b.loggedIn+c,b.notLoggedIn),b.last=c}else e.$updateClass(b.notLoggedIn,b.loggedIn+b.last)}f(),c.$on(p.update,function(){f()})}}}c.$inject=["$rootScope","AuthService","$state","$location","$timeout"],g.$inject=["$httpProvider"],h.$inject=["AuthService"],i.$inject=["AuthService"],j.$inject=["AuthService"];var k=!0,l="authLevel",m=null,n=null,o={login:"/users/login",logout:"/users/logout",fetch:"/users/me",__redirectPath__:"/"},p={login:{success:"hitmands.auth:login.resolved",error:"hitmands.auth:login.rejected"},logout:{success:"hitmands.auth:logout.resolved",error:"hitmands.auth:logout.rejected"},fetch:{success:"hitmands.auth:fetch.resolved",error:"hitmands.auth:fetch.rejected"},update:"hitmands.auth:update"},AuthCurrentUser=function(){function AuthCurrentUser(a,b){for(var c in a)a.hasOwnProperty(c)&&c!==l&&(this[c]=a[c]);Object.defineProperty(this,l,{enumerable:!0,value:b||0})}return AuthCurrentUser}.call(this);b.module("hitmands.auth",["ui.router"]).provider("AuthService",g).directive("authLogin",h).directive("authLogout",i).directive("authClasses",j).run(c)}(window,angular); 17 | -------------------------------------------------------------------------------- /release/hitmands-auth.config.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * @Project: angular-hitmands-auth 3 | * @Authors: Giuseppe Mandato 4 | * @Link: https://github.com/hitmands/angular-hitmands-auth 5 | * @License: MIT 6 | * @Date: 2015-04-18 7 | * @Version: 1.1.0 8 | * 9 | * @ngdoc: module 10 | * @namespace: hitmands 11 | * @name: auth 12 | * @module: hitmands.auth 13 | * @description: Full Implementation of an authentication management system. 14 | ***/ 15 | 16 | /** 17 | * All what you need... 18 | */ 19 | angular 20 | .module('hitmands.auth') 21 | .config(['AuthServiceProvider', function(AuthServiceProvider) { 22 | 23 | AuthServiceProvider 24 | .useRoutes({ 25 | login: '/your-login-api-endpoint', 26 | logout: '/your-logout-api-endpoint', 27 | fetch: '/your-fetch-api-endpoint' 28 | }) 29 | .parseHttpAuthData(function(data, header, statusCode) { 30 | var authData = {}; 31 | 32 | authData.user = {}; // An Object representing the CurrentUser 33 | authData.token = ''; // A String representing the token for the current session 34 | authData.authLevel = []; // An Array (or Number) representing the user claim/roles (ACL). 35 | 36 | return authData; 37 | }); 38 | }]) 39 | .run(['$rootScope', 'AuthService', function($rootScope, AuthService) { 40 | $rootScope.currentUser = AuthService.getCurrentUser(); 41 | $rootScope.isUserLoggedIn = AuthService.isUserLoggedIn(); 42 | 43 | $rootScope.$on('hitmands.auth:update', function () { 44 | $rootScope.currentUser = AuthService.getCurrentUser(); 45 | $rootScope.isUserLoggedIn = AuthService.isUserLoggedIn(); 46 | }); 47 | 48 | $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) { 49 | 50 | if(error.publisher === 'AuthService.authorize') { 51 | console.log('Route Protected', error); 52 | } 53 | }); 54 | }]); 55 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | "use strict"; 3 | /*jshint es5: true */ 4 | 5 | var 6 | path = require('path'), 7 | bodyParser = require('body-parser'), 8 | express = require('express'), 9 | fs = require('fs'), 10 | isStatic = /(assets|images|partials|bower_components)/, 11 | app = express(); 12 | 13 | app 14 | .set('port', 3000 ) 15 | .use('/images', express.static(__dirname + '/sample/images') ) 16 | .use('/partials', express.static(__dirname + '/sample/partials') ) 17 | .use('/assets', express.static(__dirname + '/sample') ) 18 | .use('/vendor', express.static(__dirname + '/src/vendor') ) 19 | .use('/build', express.static(__dirname + '/release') ) 20 | .use( bodyParser.json() ) 21 | .use( bodyParser.urlencoded( {extended: true} ) ) 22 | 23 | 24 | .get('*', function( request, response ) { 25 | 26 | if(isStatic.test(request.originalUrl) && !fs.exists(request.originalUrl)) { 27 | return response.status(404).send('Not Found'); 28 | } 29 | 30 | return response.sendFile( 31 | 'sample/index.html', { root: __dirname } 32 | ); 33 | }); 34 | 35 | 36 | var 37 | serverPort = app.get('port'), 38 | server = app.listen(serverPort, function() { 39 | console.info('angular.hitmands.auth, server listening on port:', serverPort); 40 | }); 41 | 42 | 43 | })(); 44 | -------------------------------------------------------------------------------- /specs/directives/auth-classes.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.directives.authClasses', function() { 2 | 'use strict'; 3 | var $compile, $rootScope, AuthServiceProvider; 4 | var element = '
'; 5 | 6 | beforeEach(function() { 7 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 8 | AuthServiceProvider = _AuthServiceProvider_; 9 | $exceptionHandlerProvider.mode('log'); 10 | }); 11 | }); 12 | 13 | 14 | beforeEach(angular.mock.inject( 15 | function(_$compile_, _$rootScope_) { 16 | $rootScope = _$rootScope_; 17 | $compile = _$compile_; 18 | } 19 | )); 20 | 21 | 22 | it('classList when user is logged in', angular.mock.inject( 23 | function(AuthService) { 24 | spyOn(AuthService, 'isUserLoggedIn').andReturn(true); 25 | spyOn(AuthService, 'getCurrentUser').andReturn({ 26 | authLevel: ['admin', 'editor'] 27 | }); 28 | 29 | var $scope = $rootScope.$new(); 30 | var el = $compile(element)($scope); 31 | $scope.$digest(); 32 | 33 | expect(el.attr('class')).toContain('user-is-logged-in'); 34 | expect(el.attr('class')).toContain('user-has-role-admin'); 35 | expect(el.attr('class')).toContain('user-has-role-admin'); 36 | expect(AuthService.isUserLoggedIn).toHaveBeenCalled(); 37 | expect(AuthService.getCurrentUser).toHaveBeenCalled(); 38 | } 39 | )); 40 | 41 | it('classList when user is NOT logged in', angular.mock.inject( 42 | function(AuthService) { 43 | spyOn(AuthService, 'isUserLoggedIn').andReturn(false); 44 | spyOn(AuthService, 'getCurrentUser').andReturn({ 45 | authLevel: ['admin', 'editor'] 46 | }); 47 | 48 | var $scope = $rootScope.$new(); 49 | var el = $compile(element)($scope); 50 | $scope.$digest(); 51 | 52 | 53 | expect(el.attr('class')).toContain('user-not-logged-in'); 54 | 55 | expect(el.attr('class')).not.toContain('user-is-logged-in'); 56 | expect(el.attr('class')).not.toContain('user-has-role-admin'); 57 | expect(el.attr('class')).not.toContain('user-has-role-admin'); 58 | 59 | expect(AuthService.isUserLoggedIn).toHaveBeenCalled(); 60 | expect(AuthService.getCurrentUser).not.toHaveBeenCalled(); 61 | } 62 | )); 63 | 64 | 65 | it('test on hitmands.auth:update', angular.mock.inject( 66 | function(AuthService) { 67 | spyOn(AuthService, 'isUserLoggedIn').andCallThrough(); 68 | spyOn(AuthService, 'getCurrentUser').andCallThrough(); 69 | 70 | var $scope = $rootScope.$new(); 71 | var el = $compile(element)($scope); 72 | $scope.$digest(); 73 | expect(el.attr('class')).toContain('user-not-logged-in'); 74 | expect(el.attr('class')).not.toContain('user-is-logged-in'); 75 | 76 | AuthService.setCurrentUser({ 77 | username: 'test' 78 | }, 1000, 'authTokenTest'); 79 | $scope.$digest(); 80 | 81 | 82 | expect(el.attr('class')).toContain('user-is-logged-in'); 83 | expect(el.attr('class')).not.toContain('user-not-logged-in'); 84 | 85 | expect(AuthService.isUserLoggedIn).toHaveBeenCalled(); 86 | expect(AuthService.getCurrentUser).toHaveBeenCalled(); 87 | } 88 | )); 89 | 90 | afterEach(function() { 91 | }) 92 | }); 93 | 94 | -------------------------------------------------------------------------------- /specs/directives/auth-login.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.directives.authLogin', function() { 2 | 'use strict'; 3 | var $compile, $rootScope, AuthServiceProvider; 4 | var loginForm = '
' + 5 | '' + 6 | '' + 7 | '' + 8 | '
'; 9 | 10 | beforeEach(function() { 11 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 12 | AuthServiceProvider = _AuthServiceProvider_; 13 | $exceptionHandlerProvider.mode('log'); 14 | }); 15 | }); 16 | 17 | 18 | beforeEach(angular.mock.inject( 19 | function(_$compile_, _$rootScope_) { 20 | $rootScope = _$rootScope_; 21 | $compile = _$compile_; 22 | } 23 | )); 24 | 25 | 26 | it('Invalid Attrs', angular.mock.inject( 27 | function(AuthService) { 28 | spyOn(AuthService, 'login'); 29 | var $scope = $rootScope.$new(); 30 | $scope.fields = null; 31 | $scope.onLogin = {}; 32 | $scope.onLogout = true; 33 | var el = $compile(loginForm)($scope); 34 | $scope.$digest(); 35 | 36 | el.triggerHandler('submit'); 37 | $scope.$digest(); 38 | 39 | expect(AuthService.login).not.toHaveBeenCalled(); 40 | } 41 | )); 42 | 43 | it('Valid Attrs and invalid form', angular.mock.inject( 44 | function(AuthService, $q) { 45 | spyOn(AuthService, 'login').andReturn($q.when()); 46 | var $scope = $rootScope.$new(); 47 | $scope.fields = {}; 48 | $scope.onLogin = function(result) {}; 49 | $scope.onLogout = function(rejection) {}; 50 | var el = $compile(loginForm)($scope); 51 | $scope.$digest(); 52 | 53 | el.triggerHandler('submit'); 54 | $scope.$digest(); 55 | expect($scope['loginForm'].$invalid).toBeTruthy(); 56 | expect(AuthService.login).not.toHaveBeenCalled(); 57 | } 58 | )); 59 | 60 | it('Valid Attrs and valid form', angular.mock.inject( 61 | function(AuthService, $q) { 62 | spyOn(AuthService, 'login').andReturn($q.when()); 63 | var $scope = $rootScope.$new(); 64 | $scope.fields = { 65 | username: 'test', 66 | password: 'test' 67 | }; 68 | $scope.onLogin = function(result) {}; 69 | $scope.onLogout = function(rejection) {}; 70 | var el = $compile(loginForm)($scope); 71 | $scope.$digest(); 72 | 73 | el.triggerHandler('submit'); 74 | $scope.$digest(); 75 | expect($scope['loginForm'].$valid).toBeTruthy(); 76 | expect(AuthService.login).toHaveBeenCalled(); 77 | } 78 | )); 79 | 80 | it('unbind on $destroy', angular.mock.inject( 81 | function(AuthService, $q) { 82 | spyOn(AuthService, 'login').andReturn($q.when()); 83 | var $scope = $rootScope.$new(); 84 | $scope.fields = { 85 | username: 'test', 86 | password: 'test' 87 | }; 88 | var el = $compile(loginForm)($scope); 89 | 90 | $scope.$digest(); 91 | 92 | $scope.$destroy(); 93 | $scope.$digest(); 94 | 95 | el.triggerHandler('submit'); 96 | $scope.$digest(); 97 | 98 | expect(AuthService.login).not.toHaveBeenCalled(); 99 | } 100 | )); 101 | 102 | afterEach(function() { 103 | }) 104 | }); 105 | 106 | -------------------------------------------------------------------------------- /specs/directives/auth-logout.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.directives.authLogout', function() { 2 | 'use strict'; 3 | var $compile, $rootScope, AuthServiceProvider; 4 | var logoutBtn = ''; 5 | 6 | beforeEach(function() { 7 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 8 | AuthServiceProvider = _AuthServiceProvider_; 9 | $exceptionHandlerProvider.mode('log'); 10 | }); 11 | }); 12 | 13 | 14 | beforeEach(angular.mock.inject( 15 | function(_$compile_, _$rootScope_) { 16 | $rootScope = _$rootScope_; 17 | $compile = _$compile_; 18 | } 19 | )); 20 | 21 | 22 | 23 | it('Logout', angular.mock.inject( 24 | function(AuthService, $q) { 25 | spyOn(AuthService, 'logout'); 26 | var $scope = $rootScope.$new(); 27 | 28 | var el = $compile(logoutBtn)($scope); 29 | $scope.$digest(); 30 | 31 | el.triggerHandler('click'); 32 | $scope.$digest(); 33 | 34 | expect(AuthService.logout).toHaveBeenCalled(); 35 | } 36 | )); 37 | 38 | it('unbind on $destroy', angular.mock.inject( 39 | function(AuthService, $q) { 40 | spyOn(AuthService, 'logout'); 41 | var $scope = $rootScope.$new(); 42 | var el = $compile(logoutBtn)($scope); 43 | 44 | $scope.$digest(); 45 | 46 | $scope.$destroy(); 47 | $scope.$digest(); 48 | 49 | el.triggerHandler('click'); 50 | $scope.$digest(); 51 | 52 | expect(AuthService.logout).not.toHaveBeenCalled(); 53 | } 54 | )); 55 | 56 | afterEach(function() { 57 | }) 58 | }); 59 | 60 | -------------------------------------------------------------------------------- /specs/modules/$stateChangeStart.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceRun.on.$stateChangeStart', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthService, $state, $compile, $rootScope, $timeout; 4 | 5 | beforeEach(function() { 6 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider, $stateProvider) { 7 | $exceptionHandlerProvider.mode('log'); 8 | 9 | $stateProvider 10 | .state('public', { 11 | url: '/public', 12 | authLevel: 0 13 | }) 14 | .state('admin', { 15 | url: '/admin', 16 | authLevel: ['admin'] 17 | }); 18 | }); 19 | }); 20 | 21 | beforeEach(angular.mock.inject( 22 | function(_$compile_, _$rootScope_, _$httpBackend_, _$state_, _AuthService_, _$timeout_) { 23 | $rootScope = _$rootScope_; 24 | $compile = _$compile_; 25 | $httpBackend = _$httpBackend_; 26 | $state = _$state_; 27 | AuthService = _AuthService_; 28 | AuthService.unsetCurrentUser(); 29 | $timeout = _$timeout_; 30 | } 31 | )); 32 | 33 | it('$stateChangeStart Not Prevented', function() { 34 | $state.go('public').then(function(currentState) { 35 | expect(currentState.name).toEqual('public'); 36 | }); 37 | 38 | }); 39 | 40 | it('$stateChangeStart Unauthorized', function() { 41 | $state.go('admin').catch(function(error) { 42 | expect(error.message).toEqual('transition prevented'); 43 | }); 44 | 45 | }); 46 | 47 | it('$stateChangeStart Forbidden', function() { 48 | expect(AuthService.setCurrentUser({username: 'test'}, 'author', 'tokentest')).toBeTruthy(); 49 | 50 | $state.go('admin').catch(function(error) { 51 | expect(error.message).toEqual('transition prevented'); 52 | }); 53 | 54 | }); 55 | 56 | afterEach(function() { 57 | $httpBackend.verifyNoOutstandingExpectation(); 58 | $httpBackend.verifyNoOutstandingRequest(); 59 | $timeout.flush(); 60 | }) 61 | }); 62 | 63 | -------------------------------------------------------------------------------- /specs/modules/onCurrentUserUpdate.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceRun.on.hitmands.auth:update', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthService, $state, $compile, $rootScope, $timeout, $location; 4 | 5 | beforeEach(function() { 6 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider, $stateProvider) { 7 | $exceptionHandlerProvider.mode('log'); 8 | 9 | $stateProvider 10 | .state('public', { 11 | url: '/public', 12 | authLevel: 0 13 | }) 14 | .state('admin', { 15 | url: '/admin', 16 | authLevel: ['admin'] 17 | }); 18 | }); 19 | }); 20 | 21 | beforeEach(angular.mock.inject( 22 | function(_$compile_, _$rootScope_, _$httpBackend_, _$state_, _AuthService_, _$timeout_, _$location_) { 23 | $rootScope = _$rootScope_; 24 | $compile = _$compile_; 25 | $httpBackend = _$httpBackend_; 26 | $state = _$state_; 27 | AuthService = _AuthService_; 28 | $timeout = _$timeout_; 29 | $location = _$location_; 30 | 31 | AuthService.unsetCurrentUser(); 32 | } 33 | )); 34 | 35 | it('hitmands.auth.update', function() { 36 | expect(AuthService.setCurrentUser({username: 'test'}, 'admin', 'tokentest')).toBeTruthy(); 37 | $rootScope.$digest(); 38 | 39 | $state 40 | .go('admin') 41 | .then(function(currentState) { 42 | expect($state.current.name).toEqual('admin'); 43 | AuthService.unsetCurrentUser(); 44 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 45 | return $timeout.flush(); 46 | }) 47 | .then(function() { 48 | expect($location.path()).not.toEqual('/admin'); 49 | }); 50 | 51 | 52 | }); 53 | 54 | afterEach(function() { 55 | $httpBackend.verifyNoOutstandingExpectation(); 56 | $httpBackend.verifyNoOutstandingRequest(); 57 | }) 58 | }); 59 | 60 | -------------------------------------------------------------------------------- /specs/provider-methods/disableAutoRoutingProtection.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceProvider.disableAutoRoutingProtection', function() { 2 | 'use strict'; 3 | var AuthServiceProvider; 4 | 5 | describe('no call $stateChangeError', function() { 6 | beforeEach(function() { 7 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider, $stateProvider) { 8 | $exceptionHandlerProvider.mode('log'); 9 | AuthServiceProvider = _AuthServiceProvider_ ; 10 | AuthServiceProvider.disableAutoRoutingProtection(); 11 | $stateProvider.state('admin', { 12 | url: '/admin/', 13 | authLevel: ['admin'] 14 | }); 15 | }); 16 | }); 17 | 18 | 19 | 20 | 21 | it('go to protected state admin', angular.mock.inject( 22 | function(AuthService, $state) { 23 | spyOn(AuthService, 'authorize'); 24 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 25 | 26 | $state.go('admin').then(function() { 27 | console.log('resolved') 28 | }); 29 | 30 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 31 | expect(AuthService.authorize).not.toHaveBeenCalled(); 32 | } 33 | )); 34 | }); 35 | 36 | afterEach(function() { 37 | }) 38 | }); 39 | 40 | -------------------------------------------------------------------------------- /specs/provider-methods/parseHttpAuthData.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceProvider.parseHttpAuthData', function() { 2 | 'use strict'; 3 | 4 | describe('MIDDLEWARE NOT SET', function() { 5 | beforeEach(function() { 6 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 7 | $exceptionHandlerProvider.mode('log'); 8 | }); 9 | }); 10 | 11 | 12 | 13 | 14 | it('$exceptionHandler should have a AuthServiceProvider Exception', angular.mock.inject( 15 | function(AuthService, $exceptionHandler) { 16 | 17 | expect($exceptionHandler.errors.shift()).toContain('AuthServiceProvider.parseHttpAuthData'); 18 | } 19 | )); 20 | }); 21 | 22 | describe('MIDDLEWARE AS STRING', function() { 23 | 24 | beforeEach(function() { 25 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 26 | $exceptionHandlerProvider.mode('log'); 27 | AuthServiceProvider.parseHttpAuthData( 'invalid argument' ); 28 | }); 29 | }); 30 | 31 | 32 | 33 | 34 | it('$exceptionHandler should be empty', angular.mock.inject( 35 | function(AuthService, $exceptionHandler) { 36 | expect($exceptionHandler.errors.shift()).toContain('AuthServiceProvider.parseHttpAuthData'); 37 | } 38 | )); 39 | }); 40 | 41 | describe('MIDDLEWARE AS NUMBER', function() { 42 | 43 | beforeEach(function() { 44 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 45 | $exceptionHandlerProvider.mode('log'); 46 | AuthServiceProvider.parseHttpAuthData( 1 ); 47 | }); 48 | }); 49 | 50 | 51 | 52 | 53 | it('$exceptionHandler should be empty', angular.mock.inject( 54 | function(AuthService, $exceptionHandler) { 55 | expect($exceptionHandler.errors.shift()).toContain('AuthServiceProvider.parseHttpAuthData'); 56 | } 57 | )); 58 | }); 59 | 60 | describe('MIDDLEWARE AS OBJECT', function() { 61 | 62 | beforeEach(function() { 63 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 64 | $exceptionHandlerProvider.mode('log'); 65 | AuthServiceProvider.parseHttpAuthData( {} ); 66 | }); 67 | }); 68 | 69 | 70 | 71 | 72 | it('$exceptionHandler should be empty', angular.mock.inject( 73 | function(AuthService, $exceptionHandler) { 74 | expect($exceptionHandler.errors.shift()).toContain('AuthServiceProvider.parseHttpAuthData'); 75 | } 76 | )); 77 | }); 78 | 79 | describe('MIDDLEWARE AS ARRAY', function() { 80 | 81 | beforeEach(function() { 82 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 83 | $exceptionHandlerProvider.mode('log'); 84 | AuthServiceProvider.parseHttpAuthData( [] ); 85 | }); 86 | }); 87 | 88 | 89 | 90 | 91 | it('$exceptionHandler should be empty', angular.mock.inject( 92 | function(AuthService, $exceptionHandler) { 93 | expect($exceptionHandler.errors.shift()).toContain('AuthServiceProvider.parseHttpAuthData'); 94 | } 95 | )); 96 | }); 97 | 98 | describe('MIDDLEWARE SET', function() { 99 | 100 | beforeEach(function() { 101 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 102 | 103 | $exceptionHandlerProvider.mode('log'); 104 | AuthServiceProvider.parseHttpAuthData(function() { 105 | return {}; 106 | }); 107 | }); 108 | }); 109 | 110 | 111 | 112 | 113 | it('$exceptionHandler should be empty', angular.mock.inject( 114 | function(AuthService, $exceptionHandler) { 115 | expect($exceptionHandler.errors.length).toEqual(0); 116 | } 117 | )); 118 | }); 119 | 120 | afterEach(function() { 121 | }) 122 | }); 123 | 124 | -------------------------------------------------------------------------------- /specs/provider-methods/setLoggedUser.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceProvider.setLoggedUser', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | 5 | beforeEach(function() { 6 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 7 | $exceptionHandlerProvider.mode('log'); 8 | AuthServiceProvider = _AuthServiceProvider_; 9 | }); 10 | }); 11 | 12 | 13 | 14 | 15 | 16 | it('No AuthCurrentUser Instance', angular.mock.inject( 17 | function(AuthService) { 18 | AuthServiceProvider.setLoggedUser(); 19 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 20 | } 21 | )); 22 | 23 | it('No AuthCurrentUser Instance (Wrong Params)', angular.mock.inject( 24 | function(AuthService) { 25 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 26 | AuthServiceProvider.setLoggedUser([]); 27 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 28 | } 29 | )); 30 | 31 | it('No AuthCurrentUser Instance (Wrong Params)', angular.mock.inject( 32 | function(AuthService) { 33 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 34 | AuthServiceProvider.setLoggedUser({}, ''); 35 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 36 | } 37 | )); 38 | 39 | it('Create AuthCurrentUser Instance', angular.mock.inject( 40 | function(AuthService) { 41 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 42 | AuthServiceProvider.setLoggedUser({}, 'string'); 43 | expect(AuthService.isUserLoggedIn()).toBeTruthy(); 44 | } 45 | )); 46 | 47 | it('Destroy AuthCurrentUser Instance', angular.mock.inject( 48 | function(AuthService) { 49 | expect(AuthService.isUserLoggedIn()).toBeTruthy(); 50 | AuthServiceProvider.setLoggedUser(); 51 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 52 | } 53 | )); 54 | 55 | 56 | afterEach(function() { 57 | 58 | }) 59 | }); 60 | 61 | -------------------------------------------------------------------------------- /specs/provider-methods/setRedirectPath.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceProvider.setRedirectPath', function() { 2 | 'use strict'; 3 | var REDIRECT = '/auth/login'; 4 | var AuthServiceProvider; 5 | 6 | beforeEach(function() { 7 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider, $stateProvider) { 8 | AuthServiceProvider = _AuthServiceProvider_; 9 | $exceptionHandlerProvider.mode('log'); 10 | 11 | AuthServiceProvider 12 | .setRedirectPath(REDIRECT) 13 | ; 14 | $stateProvider 15 | .state('admin', { 16 | url: 'admin/', 17 | authLevel: 1000 18 | }) 19 | .state('login', { 20 | url: 'auth/login', 21 | authLevel: 0 22 | }) 23 | ; 24 | }); 25 | }); 26 | 27 | it('Test redirect', angular.mock.inject( 28 | function(AuthService, $exceptionHandler, $state, $location, $rootScope, $timeout) { 29 | 30 | $state.go('admin').finally(function() { 31 | $timeout.flush(); 32 | }); 33 | $rootScope.$digest(); 34 | 35 | } 36 | )); 37 | 38 | 39 | afterEach(function() { 40 | AuthServiceProvider 41 | .setRedirectPath('/') 42 | ; 43 | }) 44 | }); 45 | 46 | -------------------------------------------------------------------------------- /specs/provider-methods/tokenizeHttp.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceProvider.tokenizeHttp', function() { 2 | 'use strict'; 3 | var $httpBackend; 4 | 5 | describe('DEFAULT TOKEN', function() { 6 | beforeEach(function() { 7 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 8 | $exceptionHandlerProvider.mode('log'); 9 | 10 | AuthServiceProvider.tokenizeHttp(); 11 | }); 12 | }); 13 | 14 | 15 | beforeEach(function() { 16 | angular.mock.inject(function(_$httpBackend_) { 17 | $httpBackend = _$httpBackend_; 18 | }); 19 | }); 20 | 21 | it('No token when no user logged in', angular.mock.inject( 22 | function(AuthService, $http) { 23 | AuthService.unsetCurrentUser(); 24 | 25 | $httpBackend 26 | .expectGET('/api/test/token-default') 27 | .respond(function(method, url, data, headers) { 28 | expect('x-auth-token' in headers).toBeFalsy(); 29 | return [200]; 30 | }); 31 | 32 | $http 33 | .get('/api/test/token-default'); 34 | 35 | $httpBackend.flush(); 36 | } 37 | )); 38 | 39 | 40 | it('Token and Default Header Key', angular.mock.inject( 41 | function(AuthService, $http) { 42 | 43 | var TOKEN = 'custom-auth-token'; 44 | AuthService.setCurrentUser({ 45 | username: 'test' 46 | }, 100, TOKEN); 47 | 48 | $httpBackend 49 | .expectGET('/api/test/token-default') 50 | .respond(function(method, url, data, headers) { 51 | expect('x-auth-token' in headers).toBeTruthy(); 52 | expect(headers['x-auth-token']).toEqual(TOKEN); 53 | 54 | return [200]; 55 | }); 56 | 57 | $http 58 | .get('/api/test/token-default'); 59 | 60 | $httpBackend.flush(); 61 | } 62 | )); 63 | 64 | }); 65 | 66 | 67 | describe('CUSTOM TOKEN', function() { 68 | beforeEach(function() { 69 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 70 | $exceptionHandlerProvider.mode('log'); 71 | 72 | AuthServiceProvider.tokenizeHttp('custom-auth-token-key'); 73 | }); 74 | }); 75 | 76 | beforeEach(function() { 77 | angular.mock.inject(function(_$httpBackend_) { 78 | $httpBackend = _$httpBackend_; 79 | }); 80 | }); 81 | 82 | it('Token and Custom Header Key', angular.mock.inject( 83 | function(AuthService, $http) { 84 | 85 | var TOKEN = 'custom-auth-token'; 86 | AuthService.setCurrentUser({ 87 | username: 'test' 88 | }, 100, TOKEN); 89 | 90 | $httpBackend 91 | .expectGET('/api/test/token-default') 92 | .respond(function(method, url, data, headers) { 93 | expect('custom-auth-token-key' in headers).toBeTruthy(); 94 | expect(headers['custom-auth-token-key']).toEqual(TOKEN); 95 | 96 | return [200]; 97 | }); 98 | 99 | $http 100 | .get('/api/test/token-default'); 101 | 102 | $httpBackend.flush(); 103 | } 104 | )); 105 | }); 106 | 107 | 108 | describe('CUSTOM TOKEN AND RESPONSE ERROR INTERCEPTOR', function() { 109 | var responseError = null; 110 | beforeEach(function() { 111 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider, $injector) { 112 | $exceptionHandlerProvider.mode('log'); 113 | 114 | AuthServiceProvider.tokenizeHttp('custom-auth-token-key', function(config) { 115 | 116 | responseError = config; 117 | }); 118 | }); 119 | }); 120 | 121 | beforeEach(function() { 122 | angular.mock.inject(function(_$httpBackend_) { 123 | $httpBackend = _$httpBackend_; 124 | }); 125 | }); 126 | 127 | it('Interceptor can set responseError variable. Should have Token and Custom Header Key', angular.mock.inject( 128 | function(AuthService, $http, $exceptionHandler) { 129 | 130 | var TOKEN = 'custom-auth-token'; 131 | AuthService.setCurrentUser({ 132 | username: 'test' 133 | }, 100, TOKEN); 134 | 135 | $httpBackend 136 | .expectGET('/api/test/token-default') 137 | .respond(function(method, url, data, headers) { 138 | expect('custom-auth-token-key' in headers).toBeTruthy(); 139 | expect(headers['custom-auth-token-key']).toEqual(TOKEN); 140 | 141 | return [401, 'error', {}, 'unauthorized']; 142 | }); 143 | 144 | $http 145 | .get('/api/test/token-default'); 146 | 147 | $httpBackend.flush(); 148 | 149 | expect(responseError).not.toBeNull(); 150 | expect(responseError.status).toEqual(401); 151 | responseError = null; 152 | } 153 | )); 154 | 155 | it('Interceptor not called in resolved promises. Should have Token and Custom Header Key', angular.mock.inject( 156 | function(AuthService, $http) { 157 | 158 | var TOKEN = 'custom-auth-token'; 159 | AuthService.setCurrentUser({ 160 | username: 'test' 161 | }, 100, TOKEN); 162 | 163 | $httpBackend 164 | .expectGET('/api/test/token-default') 165 | .respond(function(method, url, data, headers) { 166 | expect('custom-auth-token-key' in headers).toBeTruthy(); 167 | expect(headers['custom-auth-token-key']).toEqual(TOKEN); 168 | 169 | return [200]; 170 | }); 171 | 172 | $http 173 | .get('/api/test/token-default'); 174 | 175 | $httpBackend.flush(); 176 | 177 | expect(responseError).toBeNull(); 178 | responseError = null; 179 | } 180 | )); 181 | 182 | }); 183 | 184 | describe('DEFAULT TOKEN AND RESPONSE ERROR INTERCEPTOR', function() { 185 | var responseError = null; 186 | beforeEach(function() { 187 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 188 | $exceptionHandlerProvider.mode('log'); 189 | 190 | AuthServiceProvider.tokenizeHttp(function(config) { 191 | responseError = config; 192 | }); 193 | }); 194 | }); 195 | 196 | beforeEach(function() { 197 | angular.mock.inject(function(_$httpBackend_) { 198 | $httpBackend = _$httpBackend_; 199 | }); 200 | }); 201 | 202 | it('Interceptor can set responseError variable. Should have Token and Default Header Key', angular.mock.inject( 203 | function(AuthService, $http) { 204 | 205 | var TOKEN = 'custom-auth-token'; 206 | AuthService.setCurrentUser({ 207 | username: 'test' 208 | }, 100, TOKEN); 209 | 210 | $httpBackend 211 | .expectGET('/api/test/token-default') 212 | .respond(function(method, url, data, headers) { 213 | expect('x-auth-token' in headers).toBeTruthy(); 214 | expect(headers['x-auth-token']).toEqual(TOKEN); 215 | 216 | return [401, 'error', {}, 'unauthorized']; 217 | }); 218 | 219 | $http 220 | .get('/api/test/token-default'); 221 | 222 | $httpBackend.flush(); 223 | 224 | expect(responseError).not.toBeNull(); 225 | expect(responseError.status).toEqual(401); 226 | responseError = null; 227 | } 228 | )); 229 | 230 | }); 231 | 232 | 233 | afterEach(function() { 234 | $httpBackend.verifyNoOutstandingExpectation(); 235 | $httpBackend.verifyNoOutstandingRequest(); 236 | }) 237 | }); 238 | 239 | -------------------------------------------------------------------------------- /specs/provider-methods/useBasicAuthentication.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceProvider.useBasicAuthentication', function() { 2 | 'use strict'; 3 | var $httpBackend; 4 | var loginData = {param1: 'test1', param2: 'test2', username: 'test', password: 'test'}; 5 | 6 | describe('no basic authentication', function() { 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider 11 | .useRoutes({login: '/api/test/login'}) 12 | ; 13 | }); 14 | }); 15 | 16 | 17 | 18 | 19 | it('no Authentication in headers', angular.mock.inject( 20 | function(AuthService, $exceptionHandler, _$httpBackend_) { 21 | $httpBackend = _$httpBackend_; 22 | $httpBackend 23 | .expectPOST('/api/test/login') 24 | .respond(function(method, url, data, headers) { 25 | data = angular.fromJson(data); 26 | expect('Authorization' in headers).toBeFalsy(); 27 | expect(data.username).toBeDefined(); 28 | expect(data.password).toBeDefined(); 29 | return [200]; 30 | }); 31 | 32 | AuthService.login(angular.copy(loginData)); 33 | 34 | $httpBackend.flush(); 35 | } 36 | )); 37 | }); 38 | 39 | describe('with basic authentication', function() { 40 | beforeEach(function() { 41 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 42 | $exceptionHandlerProvider.mode('log'); 43 | AuthServiceProvider 44 | .useRoutes({login: '/api/test/login'}) 45 | .useBasicAuthentication() 46 | ; 47 | }); 48 | }); 49 | 50 | 51 | 52 | 53 | it('with auth in header', angular.mock.inject( 54 | function(AuthService, $exceptionHandler, _$httpBackend_) { 55 | $httpBackend = _$httpBackend_; 56 | $httpBackend 57 | .expectPOST('/api/test/login') 58 | .respond(function(method, url, data, headers) { 59 | data = angular.fromJson(data); 60 | 61 | expect('Authorization' in headers).toBeTruthy(); 62 | var _auth = headers['Authorization'].split(' '); 63 | var authMethod = _auth.shift(); 64 | var credentials = _auth.pop(); 65 | 66 | expect(authMethod).toEqual('Basic'); 67 | expect(credentials).toEqual(window.btoa(loginData.username + ':' + loginData.password)); 68 | 69 | expect(data.username).toBeUndefined(); 70 | expect(data.password).toBeUndefined(); 71 | return [200]; 72 | }); 73 | 74 | AuthService.login(angular.copy(loginData)); 75 | 76 | $httpBackend.flush(); 77 | } 78 | )); 79 | }); 80 | 81 | 82 | 83 | afterEach(function() { 84 | $httpBackend.verifyNoOutstandingExpectation(); 85 | $httpBackend.verifyNoOutstandingRequest(); 86 | }) 87 | }); 88 | 89 | -------------------------------------------------------------------------------- /specs/provider-methods/useRoutes.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthServiceProvider.userRoutes', function() { 2 | 'use strict'; 3 | var $httpBackend; 4 | 5 | beforeEach(function() { 6 | angular.mock.module( 'ui.router', 'hitmands.auth', function(AuthServiceProvider, $exceptionHandlerProvider) { 7 | $exceptionHandlerProvider.mode('log'); 8 | AuthServiceProvider 9 | .useRoutes({login: '/api/test/login'}) 10 | .useRoutes({logout: '/api/test/logout'}) 11 | .useRoutes({fetch: '/api/test/fetch'}) 12 | ; 13 | }); 14 | }); 15 | 16 | 17 | 18 | 19 | it('Test login Route', angular.mock.inject( 20 | function(AuthService, $exceptionHandler, _$httpBackend_) { 21 | $httpBackend = _$httpBackend_; 22 | $httpBackend 23 | .expectPOST('/api/test/login') 24 | .respond(); 25 | 26 | AuthService.login(); 27 | 28 | $httpBackend.flush(); 29 | } 30 | )); 31 | 32 | it('Test logout Route', angular.mock.inject( 33 | function(AuthService, $exceptionHandler, _$httpBackend_) { 34 | $httpBackend = _$httpBackend_; 35 | $httpBackend 36 | .expectPOST('/api/test/logout') 37 | .respond(); 38 | 39 | AuthService.logout(); 40 | 41 | $httpBackend.flush(); 42 | } 43 | )); 44 | 45 | it('Test fetch Route', angular.mock.inject( 46 | function(AuthService, $exceptionHandler, _$httpBackend_) { 47 | $httpBackend = _$httpBackend_; 48 | $httpBackend 49 | .expectGET('/api/test/fetch') 50 | .respond(); 51 | 52 | AuthService.fetch(); 53 | 54 | $httpBackend.flush(); 55 | } 56 | )); 57 | 58 | 59 | afterEach(function() { 60 | $httpBackend.verifyNoOutstandingExpectation(); 61 | $httpBackend.verifyNoOutstandingRequest(); 62 | }) 63 | }); 64 | 65 | -------------------------------------------------------------------------------- /specs/service-methods/authorize.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.authorize', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | 5 | 6 | beforeEach(function() { 7 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 8 | $exceptionHandlerProvider.mode('log'); 9 | AuthServiceProvider = _AuthServiceProvider_; 10 | }); 11 | }); 12 | 13 | beforeEach(function() { 14 | angular.mock.inject(function(_$httpBackend_) { 15 | $httpBackend = _$httpBackend_; 16 | }); 17 | }); 18 | 19 | it('authorize, bad parameter passed', angular.mock.inject( 20 | function(AuthService, $exceptionHandler, $timeout) { 21 | var $state = 'test'; 22 | expect(AuthService.authorize($state)).toBeFalsy(); 23 | expect($exceptionHandler.errors.pop()).toContain('AuthService.authorize'); 24 | } 25 | )); 26 | 27 | it('authorize, bad parameter passed', angular.mock.inject( 28 | function(AuthService, $exceptionHandler, $timeout) { 29 | var $state = { 30 | authLevel: '1000' 31 | }; 32 | expect(AuthService.authorize($state)).toBeFalsy(); 33 | expect($exceptionHandler.errors.pop()).toContain('AuthService.authorize'); 34 | } 35 | )); 36 | 37 | 38 | it('authorize should return false, authlevel {Function} and returns {Number}', angular.mock.inject( 39 | function(AuthService, $exceptionHandler, $timeout) { 40 | var $state = { 41 | authLevel: function() { 42 | return 1000; 43 | } 44 | }; 45 | expect(AuthService.authorize($state)).toBeFalsy(); 46 | } 47 | )); 48 | 49 | 50 | it('Test Injectables on authorize when authLevel is Function', angular.mock.inject( 51 | function(_AuthService_, $exceptionHandler, $timeout) { 52 | var $state = { 53 | authLevel: function($rootScope, AuthService) { 54 | 55 | expect($rootScope).toBeDefined(); 56 | expect(AuthService).toEqual(_AuthService_); 57 | return 0; 58 | } 59 | }; 60 | 61 | expect(_AuthService_.authorize($state)).toBeTruthy(); 62 | } 63 | )); 64 | 65 | 66 | it('authorize should return false, authlevel {Function} and returns {Array}', angular.mock.inject( 67 | function(AuthService, $exceptionHandler, $timeout) { 68 | var $state = { 69 | authLevel: function() { 70 | return ['Array Returned']; 71 | } 72 | }; 73 | expect(AuthService.authorize($state)).toBeFalsy(); 74 | } 75 | )); 76 | 77 | it('authorize should return false, authlevel {Number}', angular.mock.inject( 78 | function(AuthService, $exceptionHandler, $timeout) { 79 | var $state = { 80 | authLevel: 1000 81 | }; 82 | expect(AuthService.authorize($state)).toBeFalsy(); 83 | } 84 | )); 85 | 86 | it('authorize should return false, data.authlevel {Number}', angular.mock.inject( 87 | function(AuthService, $exceptionHandler, $timeout) { 88 | var $state = { 89 | data: { 90 | authLevel: 1000 91 | } 92 | }; 93 | expect(AuthService.authorize($state)).toBeFalsy(); 94 | } 95 | )); 96 | 97 | it('authorize should return true, no authlevel {default: 0}', angular.mock.inject( 98 | function(AuthService, $exceptionHandler, $timeout) { 99 | var $state = {}; 100 | expect(AuthService.authorize($state)).toBeTruthy(); 101 | } 102 | )); 103 | 104 | it('authorize should return true', angular.mock.inject( 105 | function(AuthService, $exceptionHandler, $timeout) { 106 | var $state = { 107 | authLevel: 1000 108 | }; 109 | AuthService.setCurrentUser({}, 1000, 'test'); 110 | expect(AuthService.authorize($state)).toBeTruthy(); 111 | } 112 | )); 113 | 114 | it('authorize should return false', angular.mock.inject( 115 | function(AuthService, $exceptionHandler, $timeout) { 116 | var $state = { 117 | authLevel: 1000 118 | }; 119 | AuthService.setCurrentUser({}, 100, 'test'); 120 | expect(AuthService.authorize($state)).toBeFalsy(); 121 | } 122 | )); 123 | 124 | 125 | it('authorize should return false, authlevel {Array}', angular.mock.inject( 126 | function(AuthService, $exceptionHandler, $timeout) { 127 | var $state = { 128 | authLevel: ['public'] 129 | }; 130 | expect(AuthService.authorize($state)).toBeFalsy(); 131 | } 132 | )); 133 | 134 | it('authorize should return false, data.authlevel {Array}', angular.mock.inject( 135 | function(AuthService, $exceptionHandler, $timeout) { 136 | var $state = { 137 | data: { 138 | authLevel: ['public'] 139 | } 140 | }; 141 | expect(AuthService.authorize($state)).toBeFalsy(); 142 | } 143 | )); 144 | 145 | // TODO: define the behaviour when authLevel is Empty Array 146 | it('authorize should return true, no authlevel {EmptyArray}', angular.mock.inject( 147 | function(AuthService, $exceptionHandler, $timeout) { 148 | var $state = { 149 | authLevel: [] 150 | }; 151 | expect(AuthService.authorize($state)).toBeTruthy(); 152 | } 153 | )); 154 | 155 | it('authorize should return true', angular.mock.inject( 156 | function(AuthService, $exceptionHandler, $timeout) { 157 | var $state = { 158 | authLevel: ['test'] 159 | }; 160 | AuthService.setCurrentUser({}, ['test'], 'test'); 161 | expect(AuthService.authorize($state)).toBeTruthy(); 162 | } 163 | )); 164 | 165 | it('authorize should return false', angular.mock.inject( 166 | function(AuthService, $exceptionHandler, $timeout) { 167 | var $state = { 168 | authLevel: ['test:write', 'test:read'] 169 | }; 170 | AuthService.setCurrentUser({}, ['test'], 'test'); 171 | expect(AuthService.authorize($state)).toBeFalsy(); 172 | } 173 | )); 174 | 175 | afterEach(function() { 176 | $httpBackend.verifyNoOutstandingExpectation(); 177 | $httpBackend.verifyNoOutstandingRequest(); 178 | }) 179 | 180 | }); 181 | 182 | -------------------------------------------------------------------------------- /specs/service-methods/check.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.check', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var logoutRoute = '/logout'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | }); 12 | }); 13 | 14 | beforeEach(function() { 15 | angular.mock.inject(function(_$httpBackend_) { 16 | $httpBackend = _$httpBackend_; 17 | }); 18 | }); 19 | 20 | it('check should return false', angular.mock.inject( 21 | function(AuthService, $exceptionHandler, $timeout) { 22 | var haystack = ['itemA']; 23 | var needle = 'test'; 24 | expect(AuthService.check(needle, haystack)).toBeFalsy(); 25 | } 26 | )); 27 | 28 | it('check should return true', angular.mock.inject( 29 | function(AuthService, $exceptionHandler, $timeout) { 30 | var haystack = ['itemA']; 31 | var needle = 'itemA'; 32 | expect(AuthService.check(needle, haystack)).toBeTruthy(); 33 | } 34 | )); 35 | 36 | it('check should return true', angular.mock.inject( 37 | function(AuthService, $exceptionHandler, $timeout) { 38 | var haystack = ['itemA']; 39 | var needle = ['itemA']; 40 | expect(AuthService.check(needle, haystack)).toBeTruthy(); 41 | } 42 | )); 43 | 44 | 45 | afterEach(function() { 46 | $httpBackend.verifyNoOutstandingExpectation(); 47 | $httpBackend.verifyNoOutstandingRequest(); 48 | }) 49 | 50 | }); 51 | 52 | -------------------------------------------------------------------------------- /specs/service-methods/fetch.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.fetch', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var fetchRoute = '/user/me'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | AuthServiceProvider 12 | .parseHttpAuthData(function(data, header, statusCode) { 13 | return { 14 | user: data.user, 15 | token: data.token 16 | }; 17 | }) 18 | .useRoutes({ fetch: fetchRoute }); 19 | }); 20 | }); 21 | 22 | beforeEach(function() { 23 | angular.mock.inject(function(_$httpBackend_) { 24 | $httpBackend = _$httpBackend_; 25 | }); 26 | }); 27 | 28 | it('Resolve Request', angular.mock.inject( 29 | function(AuthService, $exceptionHandler, $timeout) { 30 | $httpBackend 31 | .expectGET(fetchRoute) 32 | .respond(function(method, url, data, headers) { 33 | 34 | expect(url).toEqual(fetchRoute); 35 | 36 | 37 | return [201, { user: { username: 'test' }, token: 'test' }, {}, '']; 38 | }); 39 | 40 | AuthService 41 | .fetch() 42 | .then( 43 | function(res) { 44 | $timeout.flush(); 45 | expect(AuthService.isUserLoggedIn()).toBeTruthy(); 46 | }, 47 | function(err) { 48 | } 49 | ); 50 | 51 | $httpBackend.flush(); 52 | } 53 | )); 54 | 55 | it('Reject Request', angular.mock.inject( 56 | function(AuthService, $exceptionHandler) { 57 | $httpBackend 58 | .expectGET(fetchRoute) 59 | .respond(function(method, url, data, headers) { 60 | 61 | expect(url).toEqual(fetchRoute); 62 | 63 | 64 | return [401, {}, '']; 65 | }); 66 | 67 | AuthService 68 | .fetch() 69 | .then( 70 | function(res) { 71 | }, 72 | function(err) { 73 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 74 | } 75 | ); 76 | 77 | $httpBackend.flush(); 78 | } 79 | )); 80 | 81 | 82 | afterEach(function() { 83 | $httpBackend.verifyNoOutstandingExpectation(); 84 | $httpBackend.verifyNoOutstandingRequest(); 85 | }) 86 | 87 | }); 88 | 89 | -------------------------------------------------------------------------------- /specs/service-methods/getAuthenticationToken.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.getAuthenticationToken', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var logoutRoute = '/logout'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | }); 12 | }); 13 | 14 | beforeEach(function() { 15 | angular.mock.inject(function(_$httpBackend_) { 16 | $httpBackend = _$httpBackend_; 17 | }); 18 | }); 19 | 20 | it('getAuthenticationToken should return Null', angular.mock.inject( 21 | function(AuthService, $exceptionHandler, $timeout) { 22 | var token = '12312'; 23 | var user = { username: 'test' }; 24 | var authLevel = []; 25 | expect(AuthService.getAuthenticationToken()).toBeNull(); 26 | } 27 | )); 28 | 29 | it('getAuthenticationToken should return String', angular.mock.inject( 30 | function(AuthService, $exceptionHandler, $timeout) { 31 | var token = '12312'; 32 | var user = { username: 'test' }; 33 | var authLevel = []; 34 | AuthService.setCurrentUser(user, authLevel, token); 35 | 36 | expect(AuthService.getAuthenticationToken()).toEqual(token); 37 | } 38 | )); 39 | 40 | 41 | afterEach(function() { 42 | $httpBackend.verifyNoOutstandingExpectation(); 43 | $httpBackend.verifyNoOutstandingRequest(); 44 | }) 45 | 46 | }); 47 | 48 | -------------------------------------------------------------------------------- /specs/service-methods/getCurrentUser.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.getCurrentUser', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var logoutRoute = '/logout'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | }); 12 | }); 13 | 14 | beforeEach(function() { 15 | angular.mock.inject(function(_$httpBackend_, AuthService) { 16 | $httpBackend = _$httpBackend_; 17 | AuthService.unsetCurrentUser(); 18 | }); 19 | }); 20 | 21 | it('get Current User should return null', angular.mock.inject( 22 | function(AuthService, $exceptionHandler, $timeout) { 23 | var token = '12312'; 24 | var user = { username: 'test' }; 25 | var authLevel = []; 26 | expect(AuthService.getCurrentUser()).toBeNull(); 27 | } 28 | )); 29 | 30 | it('get Current User should return an object', angular.mock.inject( 31 | function(AuthService, $exceptionHandler, $timeout) { 32 | var token = '12312'; 33 | var user = { username: 'test' }; 34 | var authLevel = []; 35 | AuthService.setCurrentUser(user, authLevel, token); 36 | 37 | expect(AuthService.getCurrentUser()).not.toBeNull(); 38 | expect(AuthService.getCurrentUser().authLevel).toBeDefined(); 39 | expect(AuthService.getCurrentUser().username).toEqual(user.username); 40 | } 41 | )); 42 | 43 | 44 | afterEach(function() { 45 | $httpBackend.verifyNoOutstandingExpectation(); 46 | $httpBackend.verifyNoOutstandingRequest(); 47 | }) 48 | 49 | }); 50 | 51 | -------------------------------------------------------------------------------- /specs/service-methods/isUserLoggedIn.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.isUserLoggedIn', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var logoutRoute = '/logout'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | }); 12 | }); 13 | 14 | beforeEach(function() { 15 | angular.mock.inject(function(_$httpBackend_, AuthService) { 16 | $httpBackend = _$httpBackend_; 17 | AuthService.unsetCurrentUser(); 18 | }); 19 | }); 20 | 21 | it('isUserLoggedIn should return false', angular.mock.inject( 22 | function(AuthService, $exceptionHandler, $timeout) { 23 | var token = '12312'; 24 | var user = { username: 'test' }; 25 | var authLevel = []; 26 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 27 | } 28 | )); 29 | 30 | it('isUserLoggedIn should return true', angular.mock.inject( 31 | function(AuthService, $exceptionHandler, $timeout) { 32 | var token = '12312'; 33 | var user = { username: 'test' }; 34 | var authLevel = []; 35 | AuthService.setCurrentUser(user, authLevel, token); 36 | 37 | expect(AuthService.isUserLoggedIn()).toBeTruthy(); 38 | } 39 | )); 40 | 41 | 42 | afterEach(function() { 43 | $httpBackend.verifyNoOutstandingExpectation(); 44 | $httpBackend.verifyNoOutstandingRequest(); 45 | }) 46 | 47 | }); 48 | 49 | -------------------------------------------------------------------------------- /specs/service-methods/login.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.login', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var loginRoute = '/login'; 5 | 6 | describe('Login without Basic Auth', function() { 7 | 8 | beforeEach(function() { 9 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 10 | $exceptionHandlerProvider.mode('log'); 11 | AuthServiceProvider = _AuthServiceProvider_; 12 | AuthServiceProvider 13 | .parseHttpAuthData(function(data, header, statusCode) { 14 | return { 15 | user: data.user, 16 | token: data.token 17 | }; 18 | }) 19 | .useRoutes({ login: loginRoute }); 20 | }); 21 | }); 22 | 23 | beforeEach(function() { 24 | angular.mock.inject(function(_$httpBackend_) { 25 | $httpBackend = _$httpBackend_; 26 | }); 27 | }); 28 | 29 | it('Resolve Request', angular.mock.inject( 30 | function(AuthService, $exceptionHandler, $timeout) { 31 | $httpBackend 32 | .expectPOST(loginRoute) 33 | .respond(function(method, url, data, headers) { 34 | 35 | expect(url).toEqual(loginRoute); 36 | 37 | 38 | return [201, { user: { username: 'test' }, token: 'test' }, {}, '']; 39 | }); 40 | 41 | AuthService 42 | .login({field1: 'test', field2: 'test'}) 43 | .then( 44 | function(res) { 45 | $timeout.flush(); 46 | expect(AuthService.isUserLoggedIn()).toBeTruthy(); 47 | }, 48 | function(err) { 49 | } 50 | ); 51 | 52 | $httpBackend.flush(); 53 | } 54 | )); 55 | 56 | it('Reject Request', angular.mock.inject( 57 | function(AuthService, $exceptionHandler) { 58 | $httpBackend 59 | .expectPOST(loginRoute) 60 | .respond(function(method, url, data, headers) { 61 | 62 | expect(url).toEqual(loginRoute); 63 | 64 | 65 | return [401, {}, '']; 66 | }); 67 | 68 | AuthService 69 | .login({field1: 'test', field2: 'test'}) 70 | .then( 71 | function(res) { 72 | }, 73 | function(err) { 74 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 75 | } 76 | ); 77 | 78 | $httpBackend.flush(); 79 | } 80 | )); 81 | 82 | 83 | afterEach(function() { 84 | $httpBackend.verifyNoOutstandingExpectation(); 85 | $httpBackend.verifyNoOutstandingRequest(); 86 | }) 87 | }); 88 | 89 | describe('Login with Basic Auth', function() { 90 | 91 | beforeEach(function() { 92 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 93 | $exceptionHandlerProvider.mode('log'); 94 | AuthServiceProvider = _AuthServiceProvider_; 95 | AuthServiceProvider 96 | .useBasicAuthentication() 97 | .parseHttpAuthData(function(data, header, statusCode) { 98 | return { 99 | user: data.user, 100 | token: data.token 101 | }; 102 | }) 103 | .useRoutes({ login: loginRoute }); 104 | }); 105 | }); 106 | 107 | beforeEach(function() { 108 | angular.mock.inject(function(_$httpBackend_) { 109 | $httpBackend = _$httpBackend_; 110 | }); 111 | }); 112 | 113 | it('Resolve Request', angular.mock.inject( 114 | function(AuthService, $exceptionHandler, $timeout) { 115 | $httpBackend 116 | .expectPOST(loginRoute) 117 | .respond(function(method, url, data, headers) { 118 | data = angular.fromJson(data); 119 | expect(url).toEqual(loginRoute); 120 | expect(data).toEqual({}); 121 | expect('Authorization' in headers).toBeTruthy(); 122 | var _method = headers.Authorization.split(' '); 123 | var credentials = _method.pop(); 124 | expect(_method.shift()).toEqual('Basic'); 125 | expect(credentials).toEqual(btoa('test' + ':' + 'testpwd')); 126 | 127 | 128 | 129 | return [201, { user: { username: 'test' }, token: 'test' }, {}, '']; 130 | }); 131 | 132 | AuthService 133 | .login({username: 'test', password: 'testpwd'}) 134 | .then( 135 | function(res) { 136 | $timeout.flush(); 137 | expect(AuthService.isUserLoggedIn()).toBeTruthy(); 138 | }, 139 | function(err) { 140 | } 141 | ); 142 | 143 | $httpBackend.flush(); 144 | } 145 | )); 146 | 147 | it('Reject Request', angular.mock.inject( 148 | function(AuthService, $exceptionHandler) { 149 | $httpBackend 150 | .expectPOST(loginRoute) 151 | .respond(function(method, url, data, headers) { 152 | 153 | 154 | 155 | return [401, {}, '']; 156 | }); 157 | 158 | AuthService 159 | .login({field1: undefined, field2: null}) 160 | .then( 161 | function(res) { 162 | }, 163 | function(err) { 164 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 165 | } 166 | ); 167 | 168 | $httpBackend.flush(); 169 | } 170 | )); 171 | 172 | 173 | afterEach(function() { 174 | $httpBackend.verifyNoOutstandingExpectation(); 175 | $httpBackend.verifyNoOutstandingRequest(); 176 | }) 177 | }); 178 | }); 179 | 180 | -------------------------------------------------------------------------------- /specs/service-methods/logout.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.logout', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var logoutRoute = '/logout'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | AuthServiceProvider 12 | .parseHttpAuthData(function(data, header, statusCode) { 13 | return { 14 | user: data.user, 15 | token: data.token 16 | }; 17 | }) 18 | .useRoutes({ logout: logoutRoute }); 19 | }); 20 | }); 21 | 22 | beforeEach(function() { 23 | angular.mock.inject(function(_$httpBackend_) { 24 | $httpBackend = _$httpBackend_; 25 | }); 26 | }); 27 | 28 | it('Resolve Request', angular.mock.inject( 29 | function(AuthService, $exceptionHandler, $timeout) { 30 | $httpBackend 31 | .expectPOST(logoutRoute) 32 | .respond(function(method, url, data, headers) { 33 | 34 | expect(url).toEqual(logoutRoute); 35 | 36 | 37 | return [201, { user: { username: 'test' }, token: 'test' }, {}, '']; 38 | }); 39 | 40 | AuthService 41 | .logout() 42 | .then( 43 | function(res) { 44 | $timeout.flush(); 45 | expect(AuthService.isUserLoggedIn()).not.toBeTruthy(); 46 | }, 47 | function(err) { 48 | } 49 | ); 50 | 51 | $httpBackend.flush(); 52 | } 53 | )); 54 | 55 | it('Reject Request', angular.mock.inject( 56 | function(AuthService, $exceptionHandler) { 57 | $httpBackend 58 | .expectPOST(logoutRoute) 59 | .respond(function(method, url, data, headers) { 60 | 61 | expect(url).toEqual(logoutRoute); 62 | 63 | 64 | return [401, {}, '']; 65 | }); 66 | 67 | AuthService 68 | .logout() 69 | .then( 70 | function(res) { 71 | }, 72 | function(err) { 73 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 74 | } 75 | ); 76 | 77 | $httpBackend.flush(); 78 | } 79 | )); 80 | 81 | 82 | afterEach(function() { 83 | $httpBackend.verifyNoOutstandingExpectation(); 84 | $httpBackend.verifyNoOutstandingRequest(); 85 | }) 86 | 87 | }); 88 | 89 | -------------------------------------------------------------------------------- /specs/service-methods/setCurrentUser.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.setCurrentUser', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var logoutRoute = '/logout'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | }); 12 | }); 13 | 14 | beforeEach(function() { 15 | angular.mock.inject(function(_$httpBackend_) { 16 | $httpBackend = _$httpBackend_; 17 | }); 18 | }); 19 | 20 | it('Set Current User', angular.mock.inject( 21 | function(AuthService, $exceptionHandler, $timeout) { 22 | var token = '12312'; 23 | var user = { username: 'test' }; 24 | var authLevel = []; 25 | expect(AuthService.getCurrentUser()).toBeNull(); 26 | 27 | expect(AuthService.setCurrentUser(user, authLevel, token)).toBeTruthy(); 28 | 29 | expect(AuthService.getCurrentUser()).not.toBeNull(); 30 | expect(AuthService.getCurrentUser().authLevel).toBeDefined(); 31 | expect(AuthService.getCurrentUser().username).toEqual(user.username); 32 | expect(AuthService.getCurrentUser().authLevel).toEqual(authLevel); 33 | 34 | expect(AuthService.getAuthenticationToken()).toEqual(token); 35 | 36 | AuthService.unsetCurrentUser(); 37 | } 38 | )); 39 | 40 | 41 | it('Not-Set Current User', angular.mock.inject( 42 | function(AuthService, $exceptionHandler, $timeout) { 43 | var token = '12312'; 44 | var user = { username: 'test' }; 45 | var authLevel = []; 46 | expect(AuthService.getCurrentUser()).toBeNull(); 47 | 48 | expect(AuthService.setCurrentUser()).toBeFalsy(); 49 | 50 | expect(AuthService.getCurrentUser()).toBeNull(); 51 | expect(AuthService.getAuthenticationToken()).toBeNull(); 52 | } 53 | )); 54 | 55 | afterEach(function() { 56 | $httpBackend.verifyNoOutstandingExpectation(); 57 | $httpBackend.verifyNoOutstandingRequest(); 58 | }) 59 | 60 | }); 61 | 62 | -------------------------------------------------------------------------------- /specs/service-methods/unsetCurrentUser.spec.js: -------------------------------------------------------------------------------- 1 | describe('hitmands.auth.AuthService.unsetCurrentUser', function() { 2 | 'use strict'; 3 | var $httpBackend, AuthServiceProvider; 4 | var logoutRoute = '/logout'; 5 | 6 | 7 | beforeEach(function() { 8 | angular.mock.module( 'ui.router', 'hitmands.auth', function(_AuthServiceProvider_, $exceptionHandlerProvider) { 9 | $exceptionHandlerProvider.mode('log'); 10 | AuthServiceProvider = _AuthServiceProvider_; 11 | }); 12 | }); 13 | 14 | beforeEach(function() { 15 | angular.mock.inject(function(_$httpBackend_) { 16 | $httpBackend = _$httpBackend_; 17 | }); 18 | }); 19 | 20 | it('Unset Current User', angular.mock.inject( 21 | function(AuthService, $exceptionHandler, $timeout) { 22 | var token = '12312'; 23 | var user = { username: 'test' }; 24 | var authLevel = []; 25 | expect(AuthService.getCurrentUser()).toBeNull(); 26 | 27 | expect(AuthService.setCurrentUser(user, authLevel, token)).toBeTruthy(); 28 | expect(AuthService.getCurrentUser()).not.toBeNull(); 29 | expect(AuthService.getCurrentUser().username).toEqual(user.username); 30 | expect(AuthService.getCurrentUser().authLevel).toEqual(authLevel); 31 | expect(AuthService.getAuthenticationToken()).toEqual(token); 32 | 33 | 34 | expect(AuthService.unsetCurrentUser()).toBeTruthy(); 35 | expect(AuthService.getCurrentUser()).toBeNull(); 36 | expect(AuthService.isUserLoggedIn()).toBeFalsy(); 37 | expect(AuthService.getAuthenticationToken()).toBeNull(); 38 | } 39 | )); 40 | 41 | 42 | afterEach(function() { 43 | $httpBackend.verifyNoOutstandingExpectation(); 44 | $httpBackend.verifyNoOutstandingRequest(); 45 | }) 46 | 47 | }); 48 | 49 | -------------------------------------------------------------------------------- /src/auth-directives.js: -------------------------------------------------------------------------------- 1 | /* @ngInject */ 2 | function AuthLoginDirectiveFactory(AuthService) { 3 | 4 | return { 5 | restrict: 'A', 6 | link: function(iScope, iElement, iAttributes) { 7 | var _form = null; 8 | var credentials = iScope[ iAttributes['authLogin'] ]; 9 | 10 | var resolve = iScope.$eval( iAttributes['authLoginOnResolve'] ); 11 | var reject = iScope.$eval( iAttributes['authLoginOnReject'] ); 12 | resolve = angular.isFunction(resolve) ? resolve : angular.noop; 13 | reject = angular.isFunction(reject) ? reject : angular.noop; 14 | 15 | 16 | try { 17 | _form = iScope[iElement.attr('name')]; 18 | } catch (error) {} 19 | 20 | 21 | iElement.bind('submit', function( event ) { 22 | 23 | if( !angular.isObject(credentials) ) { 24 | event.preventDefault(); 25 | return reject({ attrName: 'auth-login', attrValue: credentials }); 26 | } 27 | 28 | if( angular.isObject(_form) && _form.$invalid ) { 29 | event.preventDefault(); 30 | return reject(_form.$error); 31 | } 32 | return AuthService.login(credentials).then(resolve, reject); 33 | }); 34 | 35 | iScope.$on('$destroy', function() { 36 | iElement.unbind('submit'); 37 | }); 38 | } 39 | }; 40 | } 41 | 42 | /* @ngInject */ 43 | function AuthLogoutDirectiveFactory(AuthService) { 44 | 45 | return function(scope, element, attrs) { 46 | 47 | element.bind('click', function() { 48 | AuthService.logout(); 49 | }); 50 | 51 | scope.$on('$destroy', function() { 52 | element.unbind('click'); 53 | }); 54 | }; 55 | } 56 | 57 | 58 | /* @ngInject */ 59 | function AuthClassesDirectiveFactory(AuthService) { 60 | var classes = { 61 | loggedIn: 'user-is-logged-in', 62 | notLoggedIn: 'user-not-logged-in', 63 | last: '' 64 | }; 65 | 66 | return { 67 | restrict: 'A', 68 | scope: false, 69 | link: function(iScope, iElement, iAttributes) { 70 | function _toggleClass() { 71 | var newClasses = ''; 72 | 73 | 74 | if( AuthService.isUserLoggedIn() ) { 75 | try { 76 | newClasses = ' user-has-role-' + AuthService.getCurrentUser()[AUTH_PROPERTY].join(' user-has-role-'); 77 | } catch(e) { } 78 | 79 | iAttributes.$updateClass(classes.loggedIn + newClasses, classes.notLoggedIn); 80 | classes.last = newClasses; 81 | } else { 82 | iAttributes.$updateClass(classes.notLoggedIn, classes.loggedIn + classes.last); 83 | } 84 | 85 | } 86 | 87 | _toggleClass(); 88 | iScope.$on(EVENTS.update, function() { 89 | _toggleClass(); 90 | }); 91 | 92 | } 93 | }; 94 | } 95 | -------------------------------------------------------------------------------- /src/auth-helpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @param userData 4 | * @param token 5 | * @returns {Boolean} 6 | * @private 7 | */ 8 | function _validAuthData(userData, token) { 9 | var res = true; 10 | 11 | 12 | if(angular.isArray(userData) || !angular.isObject( userData )) { 13 | res = false; 14 | } 15 | 16 | if(!angular.isString(token) || token.length < 1) { 17 | res = false; 18 | } 19 | 20 | return res; 21 | } 22 | 23 | /** 24 | * 25 | * @param {Number} stateAuthLevel 26 | * @param {Number} userAuthLevel 27 | * @returns {Boolean} 28 | * @private 29 | */ 30 | function _authorizeLevelBased( stateAuthLevel, userAuthLevel ) { 31 | if( !angular.isNumber(userAuthLevel) ) { 32 | userAuthLevel = 0; 33 | } 34 | 35 | return ( userAuthLevel >= stateAuthLevel ); 36 | } 37 | 38 | /** 39 | * 40 | * @param {Array} haystack 41 | * @param {Array} needle 42 | * @returns {Boolean} 43 | * @private 44 | */ 45 | function _inArray( haystack, needle ) { 46 | needle = angular.isArray(needle) ? needle : [needle]; 47 | 48 | if(haystack.length < 1) { 49 | return true; 50 | } 51 | 52 | for(var i = 0, len = haystack.length; i < len; i++) { 53 | for(var j = 0, jLen = needle.length; j < jLen; j++) { 54 | if( angular.equals(haystack[i], needle[j]) ) { 55 | return true; 56 | } 57 | } 58 | } 59 | 60 | return false; 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/auth-module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc module 3 | * @name hitmands.auth 4 | * @module hitmands.auth 5 | **/ 6 | var AUTO_ROUTING_PROTECTION = true; 7 | var AUTH_PROPERTY = 'authLevel'; 8 | var currentUser = null; 9 | var authToken = null; 10 | var routes = { 11 | "login": '/users/login', 12 | "logout": '/users/logout', 13 | "fetch": '/users/me', 14 | "__redirectPath__": '/' 15 | }; 16 | var EVENTS = { 17 | login: { 18 | success: 'hitmands.auth:login.resolved', 19 | error: 'hitmands.auth:login.rejected' 20 | }, 21 | logout: { 22 | success: 'hitmands.auth:logout.resolved', 23 | error: 'hitmands.auth:logout.rejected' 24 | }, 25 | fetch: { 26 | success: 'hitmands.auth:fetch.resolved', 27 | error: 'hitmands.auth:fetch.rejected' 28 | }, 29 | update: 'hitmands.auth:update' 30 | }; 31 | 32 | var AuthCurrentUser = (function() { 33 | function AuthCurrentUser(userData, authLevel) { 34 | 35 | /* jshint ignore:start */ 36 | for(var k in userData) { 37 | if(userData.hasOwnProperty(k) && k !== AUTH_PROPERTY) { 38 | this[k] = userData[k]; 39 | } 40 | } 41 | /* jshint ignore:end */ 42 | 43 | Object.defineProperty(this, AUTH_PROPERTY, { 44 | enumerable: true, 45 | value: authLevel || 0 46 | }); 47 | } 48 | 49 | return AuthCurrentUser; 50 | }).call(this); 51 | 52 | /* @ngInject */ 53 | function AuthModuleRun($rootScope, AuthService, $state, $location, $timeout) { 54 | function redirect() { 55 | $timeout(function() { 56 | $location.path(routes.__redirectPath__); 57 | }, 0); 58 | } 59 | 60 | if(AUTO_ROUTING_PROTECTION) { 61 | $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { 62 | 63 | if( !AuthService.authorize(toState, AuthService.getCurrentUser()) ) { 64 | event.preventDefault(); 65 | var _isUserLoggedIn = AuthService.isUserLoggedIn(); 66 | 67 | $rootScope.$broadcast('$stateChangeError', toState, toParams, fromState, fromParams, { 68 | statusCode: _isUserLoggedIn ? 403 : 401, 69 | statusText: _isUserLoggedIn ? 'Forbidden' : 'Unauthorized', 70 | isUserLoggedIn: _isUserLoggedIn, 71 | publisher: 'AuthService.authorize' 72 | }); 73 | 74 | if( !fromState.name ) { 75 | redirect(); 76 | } 77 | } 78 | }); 79 | 80 | $rootScope.$on(EVENTS.update, function(event) { 81 | if( !AuthService.authorize($state.current, AuthService.getCurrentUser()) ) { 82 | redirect(); 83 | } 84 | }); 85 | } 86 | } 87 | 88 | angular 89 | .module('hitmands.auth', ['ui.router']) 90 | .provider('AuthService', AuthServiceProviderFactory) 91 | .directive('authLogin', AuthLoginDirectiveFactory) 92 | .directive('authLogout', AuthLogoutDirectiveFactory) 93 | .directive('authClasses', AuthClassesDirectiveFactory) 94 | .run(AuthModuleRun); 95 | -------------------------------------------------------------------------------- /src/auth-provider.js: -------------------------------------------------------------------------------- 1 | /* @ngInject */ 2 | function AuthServiceProviderFactory( $httpProvider ) { 3 | var _dataParser; 4 | var self = this; 5 | var isBasicAuthEnabled = false; 6 | 7 | 8 | /** 9 | * @preserve 10 | * 11 | * Disables the auto routing protection 12 | */ 13 | self.disableAutoRoutingProtection = function AuthServiceDisableAutoRoutingProtection() { 14 | AUTO_ROUTING_PROTECTION = false; 15 | 16 | return self; 17 | }; 18 | 19 | /** 20 | * @preserve 21 | * 22 | * Set a redirection path used by $location.path(). 23 | */ 24 | self.setRedirectPath = function AuthServiceSetRedirectPath(path) { 25 | 26 | return self.useRoutes({__redirectPath__: path}); 27 | }; 28 | 29 | 30 | /** 31 | * Extends Used Routes 32 | * 33 | * @preserve 34 | * @param {Object} [newRoutes = {login: String, logout: String, fetch: String}] 35 | */ 36 | self.useRoutes = function AuthServiceRoutesListSetter( newRoutes ) { 37 | routes = angular.extend(routes, newRoutes); 38 | 39 | return self; 40 | }; 41 | 42 | /** 43 | * Appends Authentication Token to all $httpRequests 44 | * If a function is passed as second parameter is passed, it will be invoked for all $httpResponses with the config object 45 | * 46 | * @preserve 47 | * @param {String} [tokenKey = 'x-auth-token'] - The Name of the header Key, default x-auth-token 48 | * @param {Function} [responseErrorInterceptor] - if function passed, it will be invoked on every $httpResponseError with the config object 49 | */ 50 | self.tokenizeHttp = function AuthServiceTokenizeHttp( tokenKey, responseErrorInterceptor ) { 51 | if(angular.isFunction(tokenKey)) { 52 | responseErrorInterceptor = tokenKey; 53 | tokenKey = void(0); 54 | } 55 | $httpProvider.interceptors.push(function AuthServiceInterceptor() { 56 | 57 | return { 58 | request: function AuthServiceRequestTransform(config) { 59 | 60 | if(currentUser instanceof AuthCurrentUser) { 61 | try { 62 | config.headers[(tokenKey || 'x-auth-token')] = authToken; 63 | } catch(error) {} 64 | } 65 | 66 | return config; 67 | }, 68 | responseError: responseErrorInterceptor 69 | }; 70 | }); 71 | 72 | return self; 73 | }; 74 | 75 | /** 76 | * Encrypts login requests like headers['Authorization'] = 'Basic' + ' ' + btoa(credentials.username + ':' + credentials.password) 77 | * @preserve 78 | */ 79 | self.useBasicAuthentication = function AuthServiceUseHttpHeaderAuthorization() { 80 | isBasicAuthEnabled = true; 81 | 82 | return self; 83 | }; 84 | 85 | /** 86 | * @preserve 87 | * @param {Object|Null} [userData=null] 88 | * @param {String|Null} [authenticationToken=null] 89 | * @param {Number|Array|Null} authLevel 90 | */ 91 | self.setLoggedUser = function AuthServiceLoggedUserSetter( userData, authenticationToken, authLevel ) { 92 | if( !_validAuthData(userData, authenticationToken) ) { 93 | 94 | userData = null; 95 | authenticationToken = null; 96 | } 97 | 98 | currentUser = (userData) ? new AuthCurrentUser(userData, authLevel) : null; 99 | authToken = authenticationToken; 100 | 101 | return self; 102 | }; 103 | 104 | /** 105 | * @preserve 106 | * @param {Requester~requestCallback} callback - The callback that handles the $http response. 107 | */ 108 | self.parseHttpAuthData = function AuthServiceExpectDataAs( callback ) { 109 | if( angular.isFunction(callback) ) { 110 | 111 | _dataParser = callback; 112 | } 113 | 114 | return self; 115 | }; 116 | 117 | 118 | self.$get = function AuthServiceFactory($rootScope, $http, $state, $exceptionHandler, $timeout, $q, $injector) { 119 | if(!angular.isFunction(_dataParser)) { 120 | $exceptionHandler('AuthServiceProvider.parseHttpAuthData', 'You need to set a Callback that handles the $http response. ', 'https://github.com/hitmands/angular-hitmands-auth#module-provider-parsehttpauthdata'); 121 | } 122 | 123 | /** 124 | * @param {Object|null} [newUserData] 125 | * @param {String|null} [newAuthToken] 126 | * @param {Number|null} [newAuthLevel] 127 | * @private 128 | */ 129 | function _setLoggedUser( newUserData, newAuthToken, newAuthLevel ) { 130 | self.setLoggedUser( newUserData, newAuthToken, newAuthLevel ); 131 | $rootScope.$broadcast(EVENTS.update); 132 | 133 | $timeout(function() { 134 | if(!$rootScope.$$phase) { 135 | $rootScope.$digest(); 136 | } 137 | }, 0); 138 | } 139 | 140 | return { 141 | 142 | /** 143 | * Performs Login Request and sets the Auth Data 144 | * 145 | * @preserve 146 | * @param {{username: String, password: String}} credentials 147 | * @returns {ng.IPromise} 148 | */ 149 | login: function( credentials ) { 150 | var configs = { 151 | cache: false 152 | }; 153 | 154 | if(isBasicAuthEnabled) { 155 | configs.headers = { 156 | Authorization : 'Basic ' + window.btoa((credentials.username || '') + ':' + (credentials.password || '')) 157 | }; 158 | 159 | delete credentials['username']; 160 | delete credentials['password']; 161 | } 162 | 163 | return $http 164 | .post(routes.login, credentials, configs) 165 | .then( 166 | function( result ) { 167 | var data = _dataParser(result.data, result.headers(), result.status); 168 | 169 | _setLoggedUser( data.user, data.token, data.authLevel ); 170 | $rootScope.$broadcast(EVENTS.login.success, result); 171 | 172 | return result; 173 | }, 174 | function( error ) { 175 | _setLoggedUser( ); 176 | $rootScope.$broadcast(EVENTS.login.error, error); 177 | 178 | return $q.reject(error); 179 | } 180 | ); 181 | }, 182 | 183 | /** 184 | * Updates the Auth Data 185 | * 186 | * @preserve 187 | * @returns {ng.IPromise} 188 | */ 189 | fetch: function() { 190 | 191 | return $http 192 | .get(routes.fetch, { cache: false }) 193 | .then( 194 | function( result ) { 195 | var data = _dataParser(result.data, result.headers(), result.status); 196 | 197 | _setLoggedUser( data.user, data.token, data.authLevel ); 198 | $rootScope.$broadcast(EVENTS.fetch.success, result); 199 | 200 | return result; 201 | }, 202 | function( error ) { 203 | _setLoggedUser( ); 204 | $rootScope.$broadcast(EVENTS.fetch.error, error); 205 | 206 | return $q.reject(error); 207 | } 208 | ); 209 | }, 210 | 211 | /** 212 | * Performs Logout request 213 | * 214 | * @preserve 215 | * @returns {ng.IPromise} 216 | */ 217 | logout: function() { 218 | 219 | return $http 220 | .post(routes.logout, null, { cache: false }) 221 | .then( 222 | function( result ) { 223 | _setLoggedUser( ); 224 | $rootScope.$broadcast(EVENTS.logout.success, result); 225 | 226 | return result; 227 | }, 228 | function( error ) { 229 | _setLoggedUser( ); 230 | $rootScope.$broadcast(EVENTS.logout.error, error); 231 | 232 | return $q.reject(error); 233 | } 234 | ); 235 | }, 236 | 237 | /** 238 | * @preserve 239 | * @param {Object} user 240 | * @param {Number|Array} authLevel 241 | * @param {String} authenticationToken 242 | */ 243 | setCurrentUser: function(user, authLevel, authenticationToken) { 244 | if( !_validAuthData(user, authenticationToken) ) { 245 | return false; 246 | } 247 | 248 | _setLoggedUser( user, authenticationToken, authLevel ); 249 | return true; 250 | }, 251 | 252 | /** 253 | * @preserve 254 | */ 255 | unsetCurrentUser: function() { 256 | 257 | _setLoggedUser( ); 258 | return true; 259 | }, 260 | 261 | /** 262 | * @preserve 263 | * @returns {Object|Null} - Current User Data 264 | */ 265 | getCurrentUser: function() { 266 | 267 | return currentUser; 268 | }, 269 | 270 | /** 271 | * @preserve 272 | * Checks if the user is logged in 273 | * @returns {Boolean} 274 | */ 275 | isUserLoggedIn: function() { 276 | 277 | return (currentUser instanceof AuthCurrentUser); 278 | }, 279 | 280 | /** 281 | * @preserve 282 | * @param {Object} state 283 | * @param {Object} [user = currentUser] 284 | * @returns {Boolean} 285 | */ 286 | authorize: function( state, user ) { 287 | var userAuthLevel = 0; 288 | user = user || currentUser; 289 | 290 | if( !angular.isObject(state) ) { 291 | $exceptionHandler('AuthService.authorize', 'first param must be Object'); 292 | return false; 293 | } 294 | var stateAuthLevel = (state.data ? state.data[AUTH_PROPERTY] : state[AUTH_PROPERTY]) || 0; 295 | 296 | try { 297 | userAuthLevel = user[AUTH_PROPERTY]; 298 | } catch(e) {} 299 | 300 | try { 301 | stateAuthLevel = $injector.invoke(stateAuthLevel); 302 | } catch(e) {} 303 | 304 | if(angular.isNumber(stateAuthLevel)) { 305 | return _authorizeLevelBased(stateAuthLevel, userAuthLevel); 306 | } 307 | 308 | if(angular.isArray(stateAuthLevel)) { 309 | return _inArray(stateAuthLevel, userAuthLevel); 310 | } 311 | 312 | $exceptionHandler('AuthService.authorize', 'Cannot process authorization'); 313 | return false; 314 | }, 315 | 316 | /** 317 | * @preserve 318 | * @param needle {String|Array} 319 | * @param haystack {Array} 320 | * 321 | * @returns {Boolean} 322 | */ 323 | check: function(needle, haystack) { 324 | 325 | return _inArray(haystack, needle); 326 | }, 327 | 328 | /** 329 | * @preserve 330 | * @returns {String|Null} - The Authentication Token 331 | */ 332 | getAuthenticationToken: function() { 333 | 334 | return authToken; 335 | } 336 | 337 | }; 338 | }; 339 | } 340 | -------------------------------------------------------------------------------- /src/sample-configuration.js: -------------------------------------------------------------------------------- 1 | /** 2 | * All what you need... 3 | */ 4 | angular 5 | .module('hitmands.auth') 6 | .config(['AuthServiceProvider', function(AuthServiceProvider) { 7 | 8 | AuthServiceProvider 9 | .useRoutes({ 10 | login: '/your-login-api-endpoint', 11 | logout: '/your-logout-api-endpoint', 12 | fetch: '/your-fetch-api-endpoint' 13 | }) 14 | .parseHttpAuthData(function(data, header, statusCode) { 15 | var authData = {}; 16 | 17 | authData.user = {}; // An Object representing the CurrentUser 18 | authData.token = ''; // A String representing the token for the current session 19 | authData.authLevel = []; // An Array (or Number) representing the user claim/roles (ACL). 20 | 21 | return authData; 22 | }); 23 | }]) 24 | .run(['$rootScope', 'AuthService', function($rootScope, AuthService) { 25 | $rootScope.currentUser = AuthService.getCurrentUser(); 26 | $rootScope.isUserLoggedIn = AuthService.isUserLoggedIn(); 27 | 28 | $rootScope.$on('hitmands.auth:update', function () { 29 | $rootScope.currentUser = AuthService.getCurrentUser(); 30 | $rootScope.isUserLoggedIn = AuthService.isUserLoggedIn(); 31 | }); 32 | 33 | $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) { 34 | 35 | if(error.publisher === 'AuthService.authorize') { 36 | console.log('Route Protected', error); 37 | } 38 | }); 39 | }]); 40 | --------------------------------------------------------------------------------