Skip to content

Instantly share code, notes, and snippets.

@maxbates
Forked from katowulf/module.simpleLoginTools.js
Last active January 4, 2016 21:29
Show Gist options
  • Save maxbates/8681560 to your computer and use it in GitHub Desktop.
Save maxbates/8681560 to your computer and use it in GitHub Desktop.
/**
* This module monitors angularFire's authentication and performs actions based on authentication state.
*
* See usage examples here: https://gist.github.com/katowulf/7328023
*
* This fork adds support for a 'pending' state
*/
angular.module('FirebaseWaitForAuth', [])
/**
* A service that returns a promise object, which is resolved once $firebaseSimpleLogin
* is initialized (i.e. it returns login, logout, or error)
*/
.service('waitForAuth', function($rootScope, $q, $timeout) {
var def = $q.defer(), subs = [];
subs.push($rootScope.$on('$firebaseSimpleLogin:login', fn));
subs.push($rootScope.$on('$firebaseSimpleLogin:logout', fn));
subs.push($rootScope.$on('$firebaseSimpleLogin:error', fn));
function fn(err) {
if( $rootScope.auth ) {
$rootScope.auth.error = err instanceof Error? err.toString() : null;
}
for(var i=0; i < subs.length; i++) { subs[i](); }
$timeout(function() {
// force $scope.$apply to be re-run after login resolves
def.resolve();
});
}
return def.promise;
})
/**
* A directive that hides the element from view until waitForAuth resolves
*/
.directive('ngCloakAuth', function(waitForAuth) {
return {
restrict: 'A',
compile: function(el) {
el.addClass('hide');
waitForAuth.then(function() {
el.removeClass('hide');
})
}
}
})
//needs to be an object so update reference
.value('loginState', {state : 'pending'})
//don't place in directive, because directive is instantiated lazily while run() clause is not
.run(function(loginState, $rootScope) {
$rootScope.$on("$firebaseSimpleLogin:login", function() { loginState.state = 'login' });
$rootScope.$on("$firebaseSimpleLogin:logout", function() { loginState.state = 'logout' });
$rootScope.$on("$firebaseSimpleLogin:error", function() { loginState.state = 'error' });
})
/**
* A directive that shows elements only when the given authentication state is in effect
*/
.directive('ngShowAuth', function($rootScope, loginState) {
function inList(needle, list) {
var res = false;
angular.forEach(list, function(x) {
if( x === needle ) {
res = true;
return true;
}
return false;
});
return res;
}
function assertValidState(state) {
if( !state ) {
throw new Error('ng-show-auth directive must be pending, login, logout, or error (you may use a comma-separated list)');
}
var states = (state||'').split(',');
angular.forEach(states, function(s) {
if( !inList(s, ['pending', 'login', 'logout', 'error']) ) {
throw new Error('Invalid state "'+s+'" for ng-show-auth directive, must be one of login, logout, or error');
}
});
return true;
}
return {
restrict: 'A',
compile: function(el, attr) {
assertValidState(attr.ngShowAuth);
var expState = (attr.ngShowAuth||'').split(',');
function fn(newState) {
var hide = !inList(newState, expState);
el.toggleClass('hide', hide );
}
fn(loginState);
$rootScope.$watch(function () {
return loginState.state
}, function (newval, oldval) {
fn(newval)
});
}
}
});
<style>
.hide { display: none; }
</style>
<script>
// include the waitForAuth module as a dependency
angular.module('myApp', ['waitForAuth'])
// you can use waitForAuth directly from your scripts
.controller('myController', function(waitForAuth) {
waitForAuth.then(function() {
/* do something after auth completes */
})
})
</script>
<!-- and you can use the directives in your views -->
<div ng-show-auth="pending">Waiting for Firebase data...</div>
<div ng-cloak-auth>Authentication has resolved.</div>
<div ng-show-auth="login">{{auth.user.id}} is logged in</div>
<div ng-show-auth="logout">Logged out</div>
<div ng-show-auth="error">An error occurred: {{auth.error}}</div>
<div ng-show-auth="logout,error">This appears for logout or for error condition!</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment