UNPKG

@incdevco/framework

Version:
1,822 lines (1,149 loc) 41.8 kB
/* global amazon angular FB gapi localStorage moment */ angular.module('user', []) .controller('UserAuthenticationController', [ 'User', 'UserAmazon', 'UserFacebook', 'UserGoogle', '$log', '$mdDialog', '$mdToast', '$scope', '$window', function (User, Amazon, Facebook, Google, $log, $mdDialog, $mdToast, $scope, $window) { var crtl = this; this.enabled = {}; this.logins = {}; this.cancel = function () { $mdDialog.cancel(); }; this.login = function () { $mdDialog.hide(this.logins); }; this.enabled = User.getEnabledProviders(); } ]) .controller('UserDirectiveController', [ 'User', '$log', '$mdDialog', '$mdToast', '$scope', '$window', function (User, $log, $mdDialog, $mdToast, $scope, $window) { var crtl = this; this.authenticated = false; this.processing = false; this.user = null; this.loginDialog = function ($event) { console.log('loginDialog'); crtl.processing = true; User.authenticate() .catch(function (exception) { $log.error(exception); }) .finally(function () { crtl.processing = false; }); }; this.logoutDialog = function ($event) { $mdDialog.show({ clickOutsideToClose: true, controller: 'UserLogoutController', controllerAs: 'crtl', escapeToClose: true, parent: angular.element(document.body), targetEvent: $event, templateUrl: 'user/templates/logout.html' }) .finally(function () { $window.location.href = '/'; }); }; this.settingsDialog = function ($event) { $mdDialog.show({ clickOutsideToClose: true, controller: 'UserSettingsController', controllerAs: 'crtl', escapeToClose: true, locals: { LocalUser: this.user }, parent: angular.element(document.body), targetEvent: $event, templateUrl: 'user/templates/settings.html' }) .then(function (user) { crtl.user = user; }) .catch(function (exception) { $log.error(exception); }); }; $scope.$on('authenticated', function () { $log.debug('UserDirectiveController', 'authenticated'); crtl.authenticated = true; }); $scope.$on('deauthenticated', function () { crtl.authenticated = false; crtl.processing = false; crtl.user = null; }); $scope.$on('user', function ($event, user) { $log.debug('UserDirectiveController', 'user'); crtl.user = user; crtl.authenticated = true; }); } ]) .controller('UserLoginController', [ 'User', '$mdDialog', function (User, $mdDialog) { var crtl = this; this.enabled = User.getEnabledProviders(); this.logins = {}; this.cancel = function () { $mdDialog.cancel(); }; this.login = function () { $mdDialog.hide(this.logins); }; } ]) .controller('UserLogoutController', [ 'User', '$mdDialog', function (User, $mdDialog) { this.enabled = User.getEnabledProviders(); this.done = function () { $mdDialog.hide(); }; User.logout(); } ]) .controller('UserRegisterController', [ function () { } ]) .controller('UserSettingsController', [ 'LocalUser', 'User', '$log', '$mdDialog', '$mdToast', function (LocalUser, User, $log, $mdDialog, $mdToast) { this.user = angular.copy(LocalUser); console.log('UserSettingsController', this.user); this.cancel = function () { $mdDialog.cancel(); }; this.save = function () { console.log('save'); User.save(this.user) .then(function (user) { $mdToast.showSimple('User Settings Saved'); $mdDialog.hide(user); }) .catch(function (exception) { $log.error(exception); $mdToast.showSimple('Sorry, there was an error.'); }); }; } ]) .directive('user', [ function () { return { controller: 'UserDirectiveController', controllerAs: 'crtl', replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/directive.html' }; } ]) .directive('userLoginEmail', [ function () { return { replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/login/email.html' }; } ]) .directive('userLoginGithub', [ function () { return { replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/login/github.html' }; } ]) .directive('userLoginTwitter', [ function () { return { replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/login/twitter.html' }; } ]) .directive('userLoginAmazon', [ 'UserAmazon', '$log', '$mdToast', function (Amazon, $log, $mdToast) { return { link: function ($scope) { $scope.authenticated = false; $scope.user = null; $scope.loginWithAmazon = function ($event) { Amazon.login() .then(function (token) { $scope.authenticated = true; $scope.logins[Amazon.key] = token; $scope.login(); $mdToast.showSimple('Logged In With Amazon'); }, function (exception) { $log.error(exception); $mdToast.showSimple('Sorry, there was an error.'); }); }; $scope.logoutOfAmazon = function () { Amazon.logout() .then(function () { $scope.authenticated = null; $scope.user = null; $mdToast.showSimple('Logged Out Of Amazon'); }, function (exception) { $log.error(exception); $mdToast.showSimple('Sorry, there was an error.'); }); }; Amazon.getUser() .then(function (result) { $scope.user = result; }) .catch(function (exception) { //$log.debug('Amazon.getUser', exception); }); }, replace: true, restrict: 'E', scope: { login: '=', logins: '=' }, templateUrl: 'user/templates/login/amazon.html' }; } ]) .directive('userLoginFacebook', [ 'UserFacebook', '$log', '$mdToast', '$window', function (Facebook, $log, $mdToast, $window) { return { link: function ($scope, $element, $attr, $controller) { $scope.logoutOfFacebook = function () { Facebook.logout() .then(function () { $scope.user = null; $mdToast.showSimple('Logged Out Of Google'); }, function (exception) { $log.error(exception); $mdToast.showSimple('Sorry, there was an error.'); }); }; $window.facebookOnLogin = function (response) { console.log('facebookOnLogin', response); Facebook.race() .then(function (token) { $scope.logins[Facebook.key] = token; $scope.login(); }) .catch(function (exception) { $log.error(exception); }); }; console.log('facebook login'); FB.XFBML.parse(); $scope.$on('$destroy', function () { $window.facebookOnLogin = undefined; }); }, replace: true, restrict: 'E', scope: { login: '=', logins: '=' }, templateUrl: 'user/templates/login/facebook.html' }; } ]) .directive('userLoginGoogle', [ 'UserGoogle', '$log', '$mdToast', function (Google, $log, $mdToast) { return { link: function ($scope) { $scope.logoutOfGoogle = function () { Google.logout() .then(function () { $scope.user = null; $mdToast.showSimple('Logged Out Of Google'); }, function (exception) { $log.error(exception); $mdToast.showSimple('Sorry, there was an error.'); }); }; function onfailure(exception) { $log.error(exception); } function onsuccess(googleUser) { console.log('onsuccess', googleUser); Google.login(googleUser); $scope.logins[Google.key] = googleUser.getAuthResponse().id_token; $scope.login(); } gapi.signin2.render('GoogleSignIn', { onfailure: onfailure, onsuccess: onsuccess, theme: 'dark' }); }, replace: true, restrict: 'E', scope: { login: '=', logins: '=' }, templateUrl: 'user/templates/login/google.html' }; } ]) .directive('userLogoutAmazon', [ 'UserAmazon', '$log', '$mdToast', function (Amazon, $log, $mdToast) { return { link: function ($scope) { $scope.authenticated = false; $scope.user = null; $scope.logoutOfAmazon = function ($event) { Amazon.logout() .then(function () { $scope.authenticated = false; $scope.user = null; }) .catch(function (exception) { $log.error(exception); }); }; Amazon.getUser() .then(function (result) { $scope.authenticated = true; $scope.user = result; }) .catch(function (exception) { //$log.debug(exception); }); }, replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/logout/amazon.html' }; } ]) .directive('userLogoutEmail', [ function () { return { replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/logout/email.html' }; } ]) .directive('userLogoutFacebook', [ 'UserFacebook', '$log', '$mdToast', '$window', function (Facebook, $log, $mdToast, $window) { return { link: function ($scope) { $window.facebookOnLogout = function (response) { console.log('facebookOnLogout', response); $scope.$apply(function () { $scope.user = false; }); }; Facebook.render(); Facebook.getUser() .then(function (user) { $scope.user = user; }); }, replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/logout/facebook.html' }; } ]) .directive('userLogoutGithub', [ function () { return { replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/logout/github.html' }; } ]) .directive('userLogoutGoogle', [ 'UserGoogle', '$log', '$mdToast', function (Google, $log, $mdToast) { return { link: function ($scope) { $scope.logoutOfGoogle = function () { Google.logout() .then(function () { $scope.user = null; $mdToast.showSimple('Logged Out Of Google'); }, function (exception) { $log.error(exception); $mdToast.showSimple('Sorry, there was an error.'); }); }; console.log('google logout'); gapi.signin2.render('GoogleSignIn', { onfailure: function (exception) { console.log('exception', exception); }, onsuccess: function (googleUser) { $scope.$apply(function () { $scope.authenticated = true; $scope.user = { email_address: googleUser.getBasicProfile().getEmail(), first_name: googleUser.getBasicProfile().getGivenName(), full_name: googleUser.getBasicProfile().getName(), google: { id_token: googleUser.getAuthResponse().id_token, granted_scopes: googleUser.getGrantedScopes(), hosted_domain: googleUser.getHostedDomain() }, last_name: googleUser.getBasicProfile().getFamilyName(), name: googleUser.getBasicProfile().getName(), photo_url: googleUser.getBasicProfile().getImageUrl() }; console.log('onsuccess'); }); }, theme: 'dark' }); }, replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/logout/google.html' }; } ]) .directive('userLogoutTwitter', [ function () { return { replace: true, restrict: 'E', scope: true, templateUrl: 'user/templates/logout/twitter.html' }; } ]) .provider('User', [ function () { var allowUnauthenticated = false; var enabled = { amazon: false, email: false, facebook: false, google: false }; this.allowUnauthenticated = function (allow) { allowUnauthenticated = (allow) ? true : false; }; this.enable = function (provider) { enabled[provider] = true; }; function initMoment() { var sdkScript = angular.element('<script></script>'); sdkScript.attr('async', true); sdkScript.attr('defer', true); sdkScript.attr('src', 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js'); sdkScript.attr('type', 'text/javascript'); angular.element(document.body).append(sdkScript); } if (!window.moment) { initMoment(); } this.$get = [ 'COGNITO_IDENTITY_POOL_ID', 'COGNITO_IDENTITY_POOL_REGION', 'CognitoIdentity', 'CognitoSync', 'UserAmazon', 'UserFacebook', 'UserGoogle', '$injector', '$log', '$mdDialog', '$q', '$rootScope', '$timeout', function (identityPoolId, identityPoolRegion, CognitoIdentity, CognitoSync, Amazon, Facebook, Google, $injector, $log, $mdDialog, $q, $rootScope, $timeout) { var API, afterCredentialsFn, authenticatePromise, credentials, enabledProviders = [], identity, logins = {}, ready, user; function getAPI() { if (!API) { API = $injector.get('API'); } } function getCredentialsFromCognito() { console.log('logins', logins); if (!allowUnauthenticated && !Object.keys(logins).length) { return $q.reject(new Error('Not Authenticated')); } return CognitoIdentity({ IdentityId: null, IdentityPoolId: identityPoolId, Logins: logins, RoleSessionName: 'web-client' }, identityPoolRegion) .then(function (result) { credentials = result.credentials; identity = result.identity; if (afterCredentialsFn) { user = afterCredentialsFn(logins); } else { user = identity; } if (Object.keys(logins).length) { $rootScope.$broadcast('authenticated', identity); } else { $rootScope.$broadcast('anonymous', identity); } return credentials; }); } function getProviderByKey(key) { var provider; switch (key) { case Amazon.key: provider = Amazon; break; case Facebook.key: provider = Facebook; break; case Google.key: provider = Google; break; default: throw new Error('No Provider For Key: ' + key); } return provider; } function getUserDataFromProviders() { var promises = []; Object.keys(logins).forEach(function (key) { if (logins[key]) { promises.push(getProviderByKey(key).getUser()); } }); return $q.all(promises); } function getUserFromAPI(User, logins, $injector) { var API = $injector.get('API'); return API({ method: 'GET', url: '/authenticated' }) .then(function (response) { if (response) { return response; } else { return User.getUserDataFromProviders() .then(function (results) { var keys = [ 'amazon', 'email_address', 'facebook', 'first_name', 'google', 'last_name', 'name', 'name_pronunciation', 'phone_number', 'photo_url' ]; user = user || {}; console.log('results', results); results.forEach(function (result) { console.log('result', result); keys.forEach(function (key) { console.log('key', key, result[key]); if (result[key]) { user[key] = result[key]; console.log('user', key, user[key]); } }); }); return API({ data: user, method: 'POST', url: '/authenticated' }); }); } }) .then(function (response) { user = response; $rootScope.$broadcast('user', user); }); } function notExpired() { if (credentials && moment(credentials.expireTime).isAfter()) { return true; } else { return false; } } function race(fn) { var promises = []; var success = false; fn = fn || 'race'; enabledProviders.forEach(function (provider) { promises.push(provider[fn]() .then(function (token) { logins[provider.key] = token; success = true; return true; }) .catch(function (exception) { $log.debug(provider.key, exception); return false; })); }); return $q.all(promises) .then(function () { if (success) { return getCredentialsFromCognito(); } else { throw new Error('Race Failed'); } }); } var service = { authenticate: function () { if (!authenticatePromise) { authenticatePromise = race() .catch(function (exception) { $log.debug('race.catch', exception); return $mdDialog.show({ controller: 'UserLoginController', controllerAs: 'crtl', templateUrl: 'user/templates/login.html' }) .then(function (result) { logins = result; return getCredentialsFromCognito(); }); }); } return authenticatePromise; }, getAwsCredentials: function (required) { if (credentials && notExpired()) { return $q.resolve(credentials); } else if (required) { return this.authenticate() .then(function () { return credentials; }); } else { return getCredentialsFromCognito(); } }, getEnabledProviders: function () { return { amazon: (enabled.amazon) ? true : false, facebook: (enabled.facebook) ? true : false, google: (enabled.google) ? true : false }; }, getUser: function (required) { if (user && notExpired()) { return $q.resolve(user); } else if (required) { return this.authenticate() .then(function () { var deferred = $q.defer(); var deregister, handle; deregister = $rootScope.$on('user', function () { deferred.resolve(user); deregister(); $timeout.cancel(handle); }); handle = $timeout(function () { deferred.reject(new Error('Timeout')); deregister(); }); return deferred.promise; }); } }, getUserDataFromProviders: getUserDataFromProviders, afterCredentials: function (fn) { afterCredentialsFn = fn; }, logout: function () { CognitoIdentity.clearCachedId(); $rootScope.$broadcast('deauthenticated'); }, save: function (user) { getAPI(); console.log('save', user); return API({ data: user, method: 'POST', url: '/authenticated' }); }, user: user }; Object.keys(enabled).forEach(function (provider) { if (enabled[provider]) { switch (provider) { case 'amazon': enabledProviders.push(Amazon); break; case 'facebook': enabledProviders.push(Facebook); break; case 'google': enabledProviders.push(Google); break; default: } } }); return service; } ]; } ]) .provider('UserAmazon', [ function () { var clientId, enabled = false; this.configure = function (config) { clientId = config.clientId; var body = angular.element(document.body); var rootAmazon, sdkScript; enabled = true; rootAmazon = angular.element('<div></div>'); rootAmazon.attr('id', 'amazon-root'); body.append(rootAmazon); sdkScript = angular.element('<script></script>'); sdkScript.text('(function(d) {' + 'var a = d.createElement(\'script\'); a.type = \'text/javascript\';' + 'a.async = true; a.id = \'amazon-login-sdk\';' + 'a.src = \'https://api-cdn.amazon.com/sdk/login1.js\';' + 'd.getElementById(\'amazon-root\').appendChild(a);' + '})(document);'); body.append(sdkScript); }; this.$get = [ '$log', '$q', '$window', function ($log, $q, $window) { var authResponse, ready = $q.defer(), scope = 'profile profile:user_id postal_code', user; if (enabled) { $window.onAmazonLoginReady = function () { $log.debug('onAmazonLoginReady'); amazon.Login.setClientId(clientId); ready.resolve(true); }; } else { ready.reject(new Error('Not Enabled')); } ready.promise .catch(function (exception) { $log.debug(exception); }); function setUser(amazonProfile) { user = { email_address: amazonProfile.PrimaryEmail, amazon: { id: amazonProfile.CustomerId }, full_name: amazonProfile.Name, name: amazonProfile.Name, postal_code: amazonProfile.PostalCode }; } var service = { authenticate: function (interactive) { return ready.promise .then(function () { var deferred = $q.defer(); amazon.Login.authorize({ interactive: interactive || 'auto', // use cached token or new auth scope: scope }, function (response) { if (response.error) { deferred.reject(response); } else { authResponse = response; deferred.resolve(response.access_token); } }); return deferred.promise; }); }, getUser: function () { if (user) { return $q.resolve(user); } if (authResponse) { return ready.promise .then(function () { var deferred = $q.defer(); amazon.Login.retrieveProfile(authResponse.access_token, function (response) { if (response.error) { $log.error(response); deferred.reject(response); } else { setUser(response.profile); deferred.resolve(user); } }); return deferred.promise; }); } return $q.reject(new Error('Not Authenticated')); }, initial: function () { return this.authenticate('never'); }, key: 'www.amazon.com', login: function () { return this.authenticate(); }, logout: function () { amazon.Login.logout(); return $q.resolve(true); }, race: function () { return this.authenticate('never'); } }; return service; } ]; } ]) .provider('UserFacebook', [ function () { var appId, enabled = false; this.configure = function (config) { appId = config.appId; enabled = true; var fbRoot = angular.element('<div></div>'); fbRoot.id = 'fb-root'; var body = angular.element(document.body); body.append(fbRoot); var sdkScript = angular.element('<script></script>'); sdkScript.text('(function(d, s, id){\n' + 'var js, fjs = d.getElementsByTagName(s)[0];\n' + 'if (d.getElementById(id)) {return;}\n' + 'js = d.createElement(s); js.id = id;\n' + 'js.src = "//connect.facebook.net/en_US/sdk.js";\n' + 'fjs.parentNode.insertBefore(js, fjs);\n' + '}(document, \'script\', \'facebook-jssdk\'));'); body.append(sdkScript); }; this.$get = [ '$log', '$q', '$rootScope', '$window', function ($log, $q, $rootScope, $window) { var authResponse, ready = $q.defer(), scope = 'profile profile:user_id postal_code', user; if (enabled) { $log.debug('enabled'); $window.fbAsyncInit = function () { $log.debug('fbAsyncInit'); FB.init({ appId: appId, cookie: true, xfbml: true, version: 'v2.8' }); FB.AppEvents.logPageView(); FB.Event.subscribe('auth.login', function (response) { console.log('FB', 'auth.login', response); }); FB.Event.subscribe('auth.logout', function (response) { console.log('FB', 'auth.logout', response); }); ready.resolve(true); }; } else { ready.reject(new Error('Not Enabled')); } ready.promise.catch(function (exception) { $log.debug(exception); }); var service = { authenticate: function () { return ready.promise .then(function () { $log.debug('Facebook.authenticate'); var deferred = $q.defer(); FB.getLoginStatus(function (response) { if (response.status === 'connected') { authResponse = response.authResponse; deferred.resolve(response.authResponse.accessToken); } else { deferred.reject(false); } }); return deferred.promise; }); }, getUser: function () { if (user) { return $q.resolve(user); } return ready.promise .then(function () { var deferred = $q.defer(); FB.api('/me', 'get', { fields: 'email,name,picture' }, function (response) { if (!response || response.error) { deferred.reject(response); } else { user = { email_address: response.email, facebook: { id: response.id }, full_name: response.name, name: response.name, photo_url: response.picture.data.url }; deferred.resolve(user); } }); return deferred.promise; }); }, initial: function () { return this.authenticate(); }, key: 'graph.facebook.com', race: function () { return this.authenticate(); }, render: function () { var deferred = $q.defer(); FB.XFBML.parse(null, function () { deferred.resolve(true); }); return deferred.promise; } }; return service; } ]; } ]) .provider('UserGoogle', [ function () { var clientId, enabled = false; this.configure = function (config) { clientId = config.clientId; enabled = true; }; function init() { var sdkScript = angular.element('<script></script>'); sdkScript.attr('async', true); sdkScript.attr('defer', true); sdkScript.attr('onload', 'this.onload=function(){};gapiAsyncInit()'); sdkScript.attr('onreadystatechange', 'if (this.readyState === \'complete\') console.log(\'gapi onload\'); this.onload()'); sdkScript.attr('src', 'https://apis.google.com/js/platform.js'); angular.element(document.body).append(sdkScript); } this.$get = [ '$log', '$q', '$window', function ($log, $q, $window) { var auth2, authenticate = $q.defer(), authResponse, ready = $q.defer(), scope = 'profile email', user; if (enabled) { $window.gapiAsyncInit = function () { $log.debug('gapiAsyncInit'); gapi.load('auth2', function () { $log.debug('gapi.auth2.init'); gapi.auth2.init({ client_id: clientId, prompt: 'select_account', scope: 'email profile' }) .then(function (result) { auth2 = result; auth2.isSignedIn.listen(function (result) { console.log('isSignedIn.listen', result); }); auth2.currentUser.listen(function (googleUser) { console.log('currentUser.listen', googleUser); authResponse = googleUser.getAuthResponse(); setUser(googleUser); }); var result = auth2.isSignedIn.get(); console.log('auth2.isSignedIn.get()', result); if (result) { result = auth2.currentUser.get(); console.log('auth2.currentUser.get()', result); setUser(result); authenticate.resolve(result.getAuthResponse().id_token); } else { authenticate.reject(new Error('Not Authenticated')); } ready.resolve(true); }, function (exception) { $log.error(exception); ready.reject(exception); }); }); }; init(); } else { ready.reject(new Error('Not Enabled')); } ready.promise.catch(function (exception) { $log.debug(exception); }); function setUser(googleUser) { user = { email_address: googleUser.getBasicProfile().getEmail(), first_name: googleUser.getBasicProfile().getGivenName(), full_name: googleUser.getBasicProfile().getName(), google: { id_token: googleUser.getAuthResponse().id_token, granted_scopes: googleUser.getGrantedScopes(), hosted_domain: googleUser.getHostedDomain() }, last_name: googleUser.getBasicProfile().getFamilyName(), name: googleUser.getBasicProfile().getName(), photo_url: googleUser.getBasicProfile().getImageUrl() }; } var service = { getUser: function () { return $q.resolve(user); }, key: 'accounts.google.com', login: function (googleUser) { console.log('login', googleUser); setUser(googleUser); }, logout: function () { var auth2 = gapi.auth2.getAuthInstance(); return auth2.signOut(); }, race: function () { return ready.promise .then(function () { return authenticate.promise; }) /* .then(function () { var deferred = $q.defer(); auth2.signIn({ prompt: 'none', response_type: 'id_token', scope: scope, }) .then(function (googleUser) { deferred.resolve(googleUser.getAuthResponse().id_token); }, function (exception) { deferred.reject(exception); }); return deferred.promise; }) */ ; } }; return service; } ]; } ]);