UNPKG

@taraai/read-write

Version:

Synchronous NoSQL/Firestore for React

332 lines (275 loc) 8.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.authIsReady = authIsReady; exports.createAuthIsReady = createAuthIsReady; exports.getLoginMethodAndParams = getLoginMethodAndParams; exports.getReauthenticateMethodAndParams = getReauthenticateMethodAndParams; exports.setupPresence = setupPresence; exports.updateProfileOnFirestore = updateProfileOnFirestore; exports.updateProfileOnRTDB = updateProfileOnRTDB; var _capitalize2 = _interopRequireDefault(require("lodash/capitalize")); var _constants = require("../constants"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function createAuthProvider(firebase, providerName, scopes) { const lowerCaseProviderName = providerName.toLowerCase(); if (lowerCaseProviderName === 'microsoft.com' || lowerCaseProviderName === 'apple.com' || lowerCaseProviderName === 'yahoo.com') { const provider = new firebase.auth.OAuthProvider(providerName); return provider; } const capitalProviderName = `${(0, _capitalize2.default)(providerName)}AuthProvider`; if (!firebase.auth[capitalProviderName]) { throw new Error(`${providerName} is not a valid auth provider for your firebase instance. If using react-native, use a RN specific auth library.`); } const provider = new firebase.auth[capitalProviderName](); const { customAuthParameters } = firebase._.config; if (customAuthParameters && customAuthParameters[providerName]) { provider.setCustomParameters(customAuthParameters[providerName]); } if (lowerCaseProviderName === 'twitter' || typeof provider.addScope !== 'function') { return provider; } provider.addScope('email'); if (scopes) { if (Array.isArray(scopes)) { scopes.forEach(scope => { provider.addScope(scope); }); } if (typeof scopes === 'string' || scopes instanceof String) { provider.addScope(scopes); } } return provider; } function getLoginMethodAndParams(firebase, credentials) { const { email, password, provider, type, token, scopes, phoneNumber, applicationVerifier, credential, emailLink } = credentials; if (credential) { const credentialAuth = firebase.auth().signInAndRetrieveDataWithCredential; if (credentialAuth) { return { method: 'signInAndRetrieveDataWithCredential', params: [credential] }; } return { method: 'signInWithCredential', params: [credential] }; } if (provider) { if (_constants.supportedAuthProviders.indexOf(provider.toLowerCase()) === -1) { throw new Error(`${provider} is not a valid Auth Provider`); } if (token) { throw new Error('provider with token no longer supported, use credential parameter instead'); } const authProvider = createAuthProvider(firebase, provider, scopes); if (type === 'popup') { return { method: 'signInWithPopup', params: [authProvider] }; } return { method: 'signInWithRedirect', params: [authProvider] }; } if (token) { const tokenAuth = firebase.auth().signInAndRetrieveDataWithCustomToken; if (tokenAuth) { return { method: 'signInAndRetrieveDataWithCustomToken', params: [token] }; } return { method: 'signInWithCustomToken', params: [token] }; } if (phoneNumber) { if (!applicationVerifier) { throw new Error('Application verifier is required for phone authentication'); } return { method: 'signInWithPhoneNumber', params: [phoneNumber, applicationVerifier] }; } if (emailLink && email) { return { method: 'signInWithEmailLink', params: [email, emailLink] }; } if (!firebase.auth().signInWithEmailAndPassword) { return { method: 'signInAndRetrieveDataWithEmailAndPassword', params: [email, password] }; } return { method: 'signInWithEmailAndPassword', params: [email, password] }; } function getReauthenticateMethodAndParams(firebase, credentials) { const { provider, type, scopes, phoneNumber, applicationVerifier, credential } = credentials; if (credential) { const credentialAuth = firebase.auth().reauthenticateAndRetrieveDataWithCredential; if (credentialAuth) { return { method: 'reauthenticateAndRetrieveDataWithCredential', params: [credential] }; } return { method: 'reauthenticateWithCredential', params: [credential] }; } if (provider) { if (_constants.supportedAuthProviders.indexOf(provider.toLowerCase()) === -1) { throw new Error(`${provider} is not a valid Auth Provider`); } const authProvider = createAuthProvider(firebase, provider, scopes); if (type === 'popup') { return { method: 'reauthenticateWithPopup', params: [authProvider] }; } return { method: 'reauthenticateWithRedirect', params: [authProvider] }; } if (!applicationVerifier) { throw new Error('Application verifier is required for phone authentication'); } return { method: 'reauthenticateWithPhoneNumber', params: [phoneNumber, applicationVerifier] }; } function isAuthReady(store, stateName) { const state = store.getState(); const firebaseState = stateName ? state[stateName] : state; const firebaseAuthState = firebaseState && firebaseState.auth; if (!firebaseAuthState) { throw new Error(`The Firebase auth state could not be found in the store under the attribute '${stateName ? `${stateName}.` : ''}auth'. Make sure your react-redux-firebase reducer is correctly set in the store`); } return firebaseState.auth.isLoaded; } function authIsReady(store) { let stateName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'firebase'; return new Promise(resolve => { if (isAuthReady(store, stateName)) { resolve(); } else { const unsubscribe = store.subscribe(() => { if (isAuthReady(store, stateName)) { unsubscribe(); resolve(); } }); } }); } function createAuthIsReady(store, config) { return typeof config.authIsReady === 'function' ? config.authIsReady(store, config) : authIsReady(store, config.firebaseStateName); } function updateProfileOnRTDB(firebase, profileUpdate) { const { _: { config, authUid } } = firebase; const profileRef = firebase.database().ref(`${config.userProfile}/${authUid}`); return profileRef.update(profileUpdate).then(() => profileRef.once('value')); } function updateProfileOnFirestore(firebase, profileUpdate) { let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; const { useSet = true, merge = true } = options; const { firestore, _: { config, authUid } } = firebase; const profileRef = firestore().doc(`${config.userProfile}/${authUid}`); const profileUpdatePromise = useSet ? profileRef.set(profileUpdate, { merge }) : profileRef.update(profileUpdate); return profileUpdatePromise.then(() => profileRef.get()); } function setupPresence(dispatch, firebase) { if (!firebase.database || !firebase.database.ServerValue) { return; } const ref = firebase.database().ref(); const { config: { presence, sessions }, authUid } = firebase._; const amOnline = ref.child('.info/connected'); const onlineRef = ref.child(typeof presence === 'function' ? presence(firebase.auth().currentUser, firebase) : presence).child(authUid); let sessionsRef = typeof sessions === 'function' ? sessions(firebase.auth().currentUser, firebase) : sessions; if (sessionsRef) { sessionsRef = ref.child(sessions); } amOnline.on('value', snapShot => { if (!snapShot.val()) return; if (sessionsRef) { dispatch({ type: _constants.actionTypes.SESSION_START, payload: authUid }); const session = sessionsRef.push({ startedAt: firebase.database.ServerValue.TIMESTAMP, user: authUid }); if (typeof session.setPriority === 'function') { session.setPriority(authUid); } session.child('endedAt').onDisconnect().set(firebase.database.ServerValue.TIMESTAMP, () => { dispatch({ type: _constants.actionTypes.SESSION_END }); }); } onlineRef.set(true); onlineRef.onDisconnect().remove(); }); }