UNPKG

redux-devshare

Version:

[![NPM version][npm-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Code Climate][climate-image]][climate-url] [![Code Coverage][coverage-i

435 lines (369 loc) 15.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.resetPassword = exports.createUser = exports.logout = exports.login = exports.init = exports.createUserProfile = exports.watchUserProfile = exports.unWatchUserProfile = exports.dispatchLogin = exports.dispatchUnauthorizedError = exports.dispatchLoginError = undefined; var _get2 = require('lodash/get'); var _get3 = _interopRequireDefault(_get2); var _set2 = require('lodash/set'); var _set3 = _interopRequireDefault(_set2); var _forEach2 = require('lodash/forEach'); var _forEach3 = _interopRequireDefault(_forEach2); var _isFunction2 = require('lodash/isFunction'); var _isFunction3 = _interopRequireDefault(_isFunction2); var _isString2 = require('lodash/isString'); var _isString3 = _interopRequireDefault(_isString2); var _isArray2 = require('lodash/isArray'); var _isArray3 = _interopRequireDefault(_isArray2); var _omit2 = require('lodash/omit'); var _omit3 = _interopRequireDefault(_omit2); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _jwtDecode = require('jwt-decode'); var _jwtDecode2 = _interopRequireDefault(_jwtDecode); var _constants = require('../constants'); var _populate = require('../utils/populate'); var _auth = require('../utils/auth'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise; var SET = _constants.actionTypes.SET, SET_PROFILE = _constants.actionTypes.SET_PROFILE, LOGIN = _constants.actionTypes.LOGIN, LOGOUT = _constants.actionTypes.LOGOUT, LOGIN_ERROR = _constants.actionTypes.LOGIN_ERROR, UNAUTHORIZED_ERROR = _constants.actionTypes.UNAUTHORIZED_ERROR, AUTHENTICATION_INIT_STARTED = _constants.actionTypes.AUTHENTICATION_INIT_STARTED, AUTHENTICATION_INIT_FINISHED = _constants.actionTypes.AUTHENTICATION_INIT_FINISHED; /** * @description Dispatch login error action * @param {Function} dispatch - Action dispatch function * @param {Object} authError - Error object * @private */ var dispatchLoginError = exports.dispatchLoginError = function dispatchLoginError(dispatch, authError) { return dispatch({ type: LOGIN_ERROR, authError: authError }); }; /** * @description Dispatch login error action * @param {Function} dispatch - Action dispatch function * @param {Object} authError - Error object * @private */ var dispatchUnauthorizedError = exports.dispatchUnauthorizedError = function dispatchUnauthorizedError(dispatch, authError) { return dispatch({ type: UNAUTHORIZED_ERROR, authError: authError }); }; /** * @description Dispatch login action * @param {Function} dispatch - Action dispatch function * @param {Object} auth - Auth data object * @private */ var dispatchLogin = exports.dispatchLogin = function dispatchLogin(dispatch, auth) { return dispatch({ type: LOGIN, auth: auth, authError: null }); }; /** * @description Remove listener from user profile * @param {Object} firebase - Internal firebase object * @private */ var unWatchUserProfile = exports.unWatchUserProfile = function unWatchUserProfile(firebase) { var authUid = firebase._.authUid; var userProfile = firebase._.config.userProfile; if (firebase._.profileWatch) { firebase.database().ref().child(userProfile + '/' + authUid).off('value', firebase._.profileWatch); firebase._.profileWatch = null; } }; /** * @description Watch user profile * @param {Function} dispatch - Action dispatch function * @param {Object} firebase - Internal firebase object * @private */ var watchUserProfile = exports.watchUserProfile = function watchUserProfile(dispatch, firebase) { var authUid = firebase._.authUid; var userProfile = firebase._.config.userProfile; unWatchUserProfile(firebase); if (firebase._.config.userProfile) { firebase._.profileWatch = firebase.database().ref().child(userProfile + '/' + authUid).on('value', function (snap) { var _firebase$_$config = firebase._.config, profileParamsToPopulate = _firebase$_$config.profileParamsToPopulate, autoPopulateProfile = _firebase$_$config.autoPopulateProfile, setProfilePopulateResults = _firebase$_$config.setProfilePopulateResults; if (!profileParamsToPopulate || !(0, _isArray3.default)(profileParamsToPopulate) && !(0, _isString3.default)(profileParamsToPopulate)) { dispatch({ type: SET_PROFILE, profile: snap.val() }); } else { // Convert each populate string in array into an array of once query promises (0, _populate.promisesForPopulate)(firebase, snap.val(), profileParamsToPopulate).then(function (data) { // Dispatch action with profile combined with populated parameters // Auto Populate profile if (autoPopulateProfile) { var populates = (0, _populate.getPopulateObjs)(profileParamsToPopulate); var profile = snap.val(); (0, _forEach3.default)(populates, function (p) { (0, _set3.default)(profile, p.child, (0, _get3.default)(data, p.root + '.' + snap.val()[p.child])); }); dispatch({ type: SET_PROFILE, profile: profile }); } else { // dispatch with unpopulated profile data dispatch({ type: SET_PROFILE, profile: snap.val() }); } // Fire actions for placement of data gathered in populate into redux if (setProfilePopulateResults) { (0, _forEach3.default)(data, function (result, path) { dispatch({ type: SET, path: path, data: result, timestamp: Date.now(), requesting: false, requested: true }); }); } }); } }); } }; /** * @description Create user profile if it does not already exist. `updateProifleOnLogin: false` * can be passed to config to dsiable updating. Profile factory is applied if it exists and is a function. * @param {Function} dispatch - Action dispatch function * @param {Object} firebase - Internal firebase object * @param {Object} userData - User data object (response from authenticating) * @param {Object} profile - Profile data to place in new profile * @return {Promise} * @private */ var createUserProfile = exports.createUserProfile = function createUserProfile(dispatch, firebase, userData, profile) { if (!firebase._.config.userProfile) { return _Promise.resolve(userData); } var database = firebase.database, config = firebase._.config; if ((0, _isFunction3.default)(config.profileFactory)) { profile = config.profileFactory(userData, profile); } if ((0, _isFunction3.default)(config.profileDecorator)) { if ((0, _isFunction3.default)(console.warn)) { // eslint-disable-line no-console console.warn('profileDecorator is Depreceated and will be removed in future versions. Please use profileFactory.'); // eslint-disable-line no-console } profile = config.profileDecorator(userData, profile); } // Check for user's profile at userProfile path if provided return database().ref().child(config.userProfile + '/' + userData.uid).once('value').then(function (profileSnap) { return ( // update profile only if doesn't exist or if set by config !config.updateProfileOnLogin && profileSnap.val() !== null ? profileSnap.val() : profileSnap.ref.update(profile) // Update the profile .then(function () { return profile; }).catch(function (err) { // Error setting profile dispatchUnauthorizedError(dispatch, err); return _Promise.reject(err); }) ); }).catch(function (err) { // Error reading user profile dispatchUnauthorizedError(dispatch, err); return _Promise.reject(err); }); }; /** * @description Initialize authentication state change listener that * watches user profile and dispatches login action * @param {Function} dispatch - Action dispatch function * @private */ var init = exports.init = function init(dispatch, firebase) { dispatch({ type: AUTHENTICATION_INIT_STARTED }); firebase.auth().onAuthStateChanged(function (authData) { if (!authData) { return dispatch({ type: LOGOUT }); } firebase._.authUid = authData.uid; watchUserProfile(dispatch, firebase); dispatchLogin(dispatch, authData); // Run onAuthStateChanged if it exists in config if (firebase._.config.onAuthStateChanged) { firebase._.config.onAuthStateChanged(authData, firebase); } }); if (firebase._.config.enableRedirectHandling) { firebase.auth().getRedirectResult().then(function (authData) { if (authData && authData.user) { var user = authData.user; firebase._.authUid = user.uid; watchUserProfile(dispatch, firebase); dispatchLogin(dispatch, user); createUserProfile(dispatch, firebase, user, { email: user.email, displayName: user.providerData[0].displayName || user.email, avatarUrl: user.providerData[0].photoURL, providerData: user.providerData }); } }).catch(function (error) { dispatchLoginError(dispatch, error); return _Promise.reject(error); }); } firebase.auth().currentUser; dispatch({ type: AUTHENTICATION_INIT_FINISHED }); }; /** * @description Login with errors dispatched * @param {Function} dispatch - Action dispatch function * @param {Object} firebase - Internal firebase object * @param {Object} credentials - Login credentials * @param {Object} credentials.email - Email to login with (only needed for email login) * @param {Object} credentials.password - Password to login with (only needed for email login) * @param {Object} credentials.provider - Provider name such as google, twitter (only needed for 3rd party provider login) * @param {Object} credentials.type - Popup or redirect (only needed for 3rd party provider login) * @param {Object} credentials.token - Custom or provider token * @return {Promise} * @private */ var login = exports.login = function login(dispatch, firebase, credentials) { var _firebase$auth; dispatchLoginError(dispatch, null); var _getLoginMethodAndPar = (0, _auth.getLoginMethodAndParams)(firebase, credentials), method = _getLoginMethodAndPar.method, params = _getLoginMethodAndPar.params; return (_firebase$auth = firebase.auth())[method].apply(_firebase$auth, _toConsumableArray(params)).then(function (userData) { // Handle null response from getRedirectResult before redirect has happened if (!userData) return _Promise.resolve(null); // For email auth return uid (createUser is used for creating a profile) if (userData.email) return userData.uid; // For token auth, the user key doesn't exist. Instead, return the JWT. if (method === 'signInWithCustomToken') { // Extract the extra data in the JWT token for user object var _userData$toJSON = userData.toJSON(), accessToken = _userData$toJSON.stsTokenManager.accessToken, uid = _userData$toJSON.uid; var extraJWTData = (0, _omit3.default)((0, _jwtDecode2.default)(accessToken), _constants.defaultJWTProps); return createUserProfile(dispatch, firebase, { uid: uid }, _extends({}, extraJWTData, { uid: uid })); } // Create profile when logging in with external provider var user = userData.user; return createUserProfile(dispatch, firebase, user, { email: user.email, displayName: user.providerData[0].displayName || user.email, avatarUrl: user.providerData[0].photoURL, providerData: user.providerData }); }).catch(function (err) { dispatchLoginError(dispatch, err); return _Promise.reject(err); }); }; /** * @description Logout of firebase and dispatch logout event * @param {Function} dispatch - Action dispatch function * @param {Object} firebase - Internal firebase object * @private */ var logout = exports.logout = function logout(dispatch, firebase) { firebase.auth().signOut(); dispatch({ type: LOGOUT }); firebase._.authUid = null; unWatchUserProfile(firebase); return _Promise.resolve(firebase); }; /** * @description Create a new user in auth and add an account to userProfile root * @param {Function} dispatch - Action dispatch function * @param {Object} firebase - Internal firebase object * @param {Object} credentials - Login credentials * @return {Promise} * @private */ var createUser = exports.createUser = function createUser(dispatch, firebase, _ref, profile) { var email = _ref.email, password = _ref.password, signIn = _ref.signIn; dispatchLoginError(dispatch, null); if (!email || !password) { dispatchLoginError(dispatch, new Error('Email and Password are required to create user')); return _Promise.reject(new Error('Email and Password are Required')); } return firebase.auth().createUserWithEmailAndPassword(email, password).then(function (userData) { return ( // Login to newly created account if signIn flag is true firebase.auth().currentUser || !!signIn && signIn === false ? createUserProfile(dispatch, firebase, userData, profile) : login(dispatch, firebase, { email: email, password: password }).then(function () { return createUserProfile(dispatch, firebase, userData, profile || { email: email }); }).catch(function (err) { if (err) { switch (err.code) { case 'auth/user-not-found': dispatchLoginError(dispatch, new Error('The specified user account does not exist.')); break; default: dispatchLoginError(dispatch, err); } } return _Promise.reject(err); }) ); }).catch(function (err) { dispatchLoginError(dispatch, err); return _Promise.reject(err); }); }; /** * @description Send password reset email to provided email * @param {Function} dispatch - Action dispatch function * @param {Object} firebase - Internal firebase object * @param {String} email - Email to send recovery email to * @return {Promise} * @private */ var resetPassword = exports.resetPassword = function resetPassword(dispatch, firebase, email) { dispatchLoginError(dispatch, null); return firebase.auth().sendPasswordResetEmail(email).catch(function (err) { if (err) { switch (err.code) { case 'auth/user-not-found': dispatchLoginError(dispatch, new Error('The specified user account does not exist.')); break; default: dispatchLoginError(dispatch, err); } return _Promise.reject(err); } }); }; exports.default = { dispatchLoginError: dispatchLoginError, dispatchUnauthorizedError: dispatchUnauthorizedError, dispatchLogin: dispatchLogin, unWatchUserProfile: unWatchUserProfile, watchUserProfile: watchUserProfile, init: init, createUserProfile: createUserProfile, login: login, logout: logout, createUser: createUser, resetPassword: resetPassword };