Skip to content

Commit

Permalink
Remove hard dependency on local.storage service
Browse files Browse the repository at this point in the history
Storage service is now defined during configuration and then dynamically
injected when required. Tests have been updated to use local.storage for
validation. This also removes the hard dependency on ngCookies that
existed merely to satisfy local.storage service.
  • Loading branch information
justinsa committed Mar 7, 2017
1 parent d608435 commit 185805b
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 27 deletions.
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,47 @@ An authentication and authorization helper service for Angular client applicatio
##Dependencies

* AngularJS - http://angularjs.org
* Angular Cookies - ngCookies
* angular-local-storage-service - [local.storage]((https://github.com/justinsa/angular-local-storage-service))
* lodash
* Lodash - http://lodash.com

##Basic Setup

1. Add this module to your app as a dependency:
```JAVASCRIPT
var app = angular.module('yourApp', ['authentication.service']);
```
2. Inject $authentication as a parameter in declarations that require it:
2. Configure a storage service to use with the authentication provider:
```JAVASCRIPT
app.config(['$authenticationProvider', function ($authenticationProvider) {
$authenticationProvider.configure({
storageService: '$store'
});
}]);
```
3. Inject $authentication as a parameter in declarations that require it:
```JAVASCRIPT
app.controller('yourController', function($scope, $authentication){ ... });
```

The ng-authentication-service was designed in tandem with the following projects:

* https://github.com/justinsa/angular-local-storage-service

The injected storage service must support the following API:

1. ```get(key)```
2. ```has(key)```
3. ```remove(key)```
4. ```set(key, value)```

##Configuration Options

To override the default configuration options, configure the module with an options argument during application configuration and provide overrides for any of the following options.

```JAVASCRIPT
app.config(['$authenticationProvider', function ($authenticationProvider) {
$authenticationProvider.configure({
authCookieKey: null,
storageService: undefined,
authCookieKey: undefined,
profileStorageKey: 'user.profile',
onLoginRedirectPath: '/',
onLogoutRedirectPath: '/',
Expand Down
57 changes: 39 additions & 18 deletions angular-authentication-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,23 @@
if (typeof angular === 'undefined') {
factory(
typeof _ === 'undefined' ? require('lodash') : root._,
require('angular'),
require('angular-cookies'),
require('ng-local-storage-service')
require('angular')
);
} else {
factory(root._, root.angular);
}
module.exports = 'ng-authentication-service';
} else if (typeof define === 'function' && define.amd) {
define(['lodash', 'angular', 'angular-cookies', 'ng-local-storage-service'], factory);
define(['lodash', 'angular'], factory);
} else {
factory(root._, root.angular);
}
}(this, function (_, angular, ngCookies, localStorage, undefined) {
}(this, function (_, angular, undefined) {
'use strict';
angular.module('authentication.service', ['ngCookies', 'local.storage']).provider('$authentication', function () {
angular.module('authentication.service', []).provider('$authentication', function () {
var configuration = {
authCookieKey: null,
storageService: undefined,
authCookieKey: undefined,
profileStorageKey: 'user.profile',
onLoginRedirectPath: '/',
onLogoutRedirectPath: '/',
Expand Down Expand Up @@ -50,22 +49,44 @@
};

this.$get = [
'$cookieStore', '$document', '$location', '$rootScope', '$store', '$window',
function ($cookieStore, $document, $location, $rootScope, $store, $window) {
'$document', '$injector', '$location', '$log', '$rootScope', '$window',
function ($document, $injector, $location, $log, $rootScope, $window) {
var storeService;
var storageService = function () {
if (storeService === undefined) {
if (!_.isString(configuration.storageService)) {
$log.error('No storageService configuration value provided');
return undefined;
}
if (!$injector.has(configuration.storageService)) {
$log.error('No matching service registered in Angular: ', configuration.storageService);
return undefined;
}
storeService = $injector.get(configuration.storageService);
_.each(['get', 'has', 'remove', 'set'], function (methodName) {
if (!_.has(storeService, methodName)) {
$log.error('Matching service is missing method: ', methodName);
return undefined;
}
});
}
return storeService;
};

var authFunctions = {
/**
* returns true if there is a user profile in storage.
*/
isAuthenticated: function () {
if (this.isAuthCookieMissing()) {
if ($store.has(configuration.profileStorageKey)) {
if (storageService().has(configuration.profileStorageKey)) {
// The cookie is absent or expired but we still have the profile stored.
// Clear the profile and broadcast logout to ensure the app updates.
this.logoutConfirmed();
}
return false;
}
return $store.has(configuration.profileStorageKey);
return storageService().has(configuration.profileStorageKey);
},

/**
Expand All @@ -89,7 +110,7 @@
* example if you need to pass through details of the user that was logged in.
*/
loginConfirmed: function (data) {
$store.set(configuration.profileStorageKey, data);
storageService().set(configuration.profileStorageKey, data);
configuration.reauthId = setInterval(configuration.reauthFunc, configuration.reauthTimeout);
$rootScope.$broadcast('event:auth-loginConfirmed', data);
if (_.isString(configuration.onLoginRedirectPath)) {
Expand Down Expand Up @@ -119,7 +140,7 @@
* call this function to indicate that unauthentication was successful.
*/
logoutConfirmed: function () {
$store.remove(configuration.profileStorageKey);
storageService().remove(configuration.profileStorageKey);
$window.clearInterval(configuration.reauthId);
configuration.reauthId = null;
$rootScope.$broadcast('event:auth-logoutConfirmed');
Expand Down Expand Up @@ -156,10 +177,10 @@
* call this function to retrieve the existing user profile from storage.
*/
profile: function () {
var profile = $store.get(configuration.profileStorageKey);
var profile = storageService().get(configuration.profileStorageKey);
if (_.isObject(profile)) {
profile.$apply = function() {
$store.set(configuration.profileStorageKey, _.omit(this, '$apply'));
storageService().set(configuration.profileStorageKey, _.omit(this, '$apply'));
};
}
return profile;
Expand Down Expand Up @@ -195,10 +216,10 @@
*/
permit: function () {
if (this.allowed.apply(this, _.toArray(arguments))) {
$store.remove('attemptedPath');
storageService().remove('attemptedPath');
return;
}
$store.set('attemptedPath', $location.path());
storageService().set('attemptedPath', $location.path());
if (this.isAuthenticated()) {
$location.path(configuration.notPermittedRedirectPath);
} else {
Expand All @@ -210,7 +231,7 @@
* Returns the path that the user attempts to access before being redirected.
*/
getAttemptedPath: function () {
return $store.get('attemptedPath');
return storageService().get('attemptedPath');
},

/**
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng-authentication-service",
"version": "0.1.2",
"version": "0.2.0",
"author": "Justin Saunders (https://github.com/justinsa)",
"contributors": [
"Josh Mackey (https://github.com/joshmackey)",
Expand Down
9 changes: 6 additions & 3 deletions tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

describe('services', function () {
beforeEach(
module('authentication.service', function ($authenticationProvider) {
module('authentication.service', 'local.storage', function ($authenticationProvider) {
$authenticationProvider.configure({
storageService: '$store',
onLoginRedirectPath: '/dashboard',
onLogoutRedirectPath: '/home',
notPermittedRedirectPath: '/notpermitted',
Expand All @@ -29,7 +30,8 @@ describe('services', function () {
'isInAllRoles',
'isInAnyRoles',
'permit',
'getConfiguration'
'getConfiguration',
'reauth'
];
for (var i in functions) {
$authentication[functions[i]].should.be.a.function; // jshint ignore:line
Expand All @@ -40,7 +42,8 @@ describe('services', function () {
it('should have an expected configuration',
inject(function ($authentication) {
var configuration = $authentication.getConfiguration();
(configuration.authCookieKey === null).should.be.true; // jshint ignore:line
configuration.storageService.should.match('$store');
(configuration.authCookieKey === undefined).should.be.true; // jshint ignore:line
configuration.profileStorageKey.should.match('user.profile');
configuration.onLoginRedirectPath.should.match('/dashboard');
configuration.onLogoutRedirectPath.should.match('/home');
Expand Down

0 comments on commit 185805b

Please sign in to comment.