diff --git a/lib/hooks/login-hooks.js b/lib/hooks/login-hooks.js index 753340739..a7637c20b 100644 --- a/lib/hooks/login-hooks.js +++ b/lib/hooks/login-hooks.js @@ -1,168 +1,176 @@ // @flow import * as React from 'react'; +import { setDataLoadedActionType } from '../actions/client-db-store-actions.js'; import { identityLogInActionTypes, useIdentityPasswordLogIn, useIdentityWalletLogIn, } from '../actions/user-actions.js'; import { useKeyserverAuth } from '../keyserver-conn/keyserver-auth.js'; import { logInActionSources } from '../types/account-types.js'; import { authoritativeKeyserverID } from '../utils/authoritative-keyserver.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; -import { useSelector } from '../utils/redux-utils.js'; +import { useSelector, useDispatch } from '../utils/redux-utils.js'; // We can't just do everything in one async callback, since the server calls // would get bound to Redux state from before the login. In order to pick up the // updated CSAT and currentUserInfo from Redux, we break the login into two // steps. type CurrentStep = | { +step: 'inactive' } | { +step: 'identity_login_dispatched', +resolve: () => void, +reject: Error => void, }; const inactiveStep = { step: 'inactive' }; type LogInInputs = | { +accountType: 'username', +username: string, +password: string, } | { +accountType: 'ethereum', +walletAddress: string, +siweMessage: string, +siweSignature: string, }; function useLogIn(): LogInInputs => Promise { const [currentStep, setCurrentStep] = React.useState(inactiveStep); const identityPasswordLogIn = useIdentityPasswordLogIn(); const identityWalletLogIn = useIdentityWalletLogIn(); const dispatchActionPromise = useDispatchActionPromise(); const returnedFunc = React.useCallback( (logInInputs: LogInInputs) => new Promise( // eslint-disable-next-line no-async-promise-executor async (resolve, reject) => { if (currentStep.step !== 'inactive') { return; } const action = logInInputs.accountType === 'username' ? identityPasswordLogIn( logInInputs.username, logInInputs.password, ) : identityWalletLogIn( logInInputs.walletAddress, logInInputs.siweMessage, logInInputs.siweSignature, ); void dispatchActionPromise(identityLogInActionTypes, action); try { await action; setCurrentStep({ step: 'identity_login_dispatched', resolve, reject, }); } catch (e) { reject(e); } }, ), [ currentStep, dispatchActionPromise, identityPasswordLogIn, identityWalletLogIn, ], ); const keyserverAuth = useKeyserverAuth(authoritativeKeyserverID()); const isRegisteredOnIdentity = useSelector( state => !!state.commServicesAccessToken && !!state.currentUserInfo && !state.currentUserInfo.anonymous, ); const registeringOnAuthoritativeKeyserverRef = React.useRef(false); + const dispatch = useDispatch(); React.useEffect(() => { if ( !isRegisteredOnIdentity || currentStep.step !== 'identity_login_dispatched' || registeringOnAuthoritativeKeyserverRef.current ) { return; } registeringOnAuthoritativeKeyserverRef.current = true; const { resolve, reject } = currentStep; void (async () => { try { await keyserverAuth({ authActionSource: process.env.BROWSER ? logInActionSources.keyserverAuthFromWeb : logInActionSources.keyserverAuthFromNative, setInProgress: () => {}, hasBeenCancelled: () => false, doNotRegister: false, }); + dispatch({ + type: setDataLoadedActionType, + payload: { + dataLoaded: true, + }, + }); resolve(); } catch (e) { reject(e); } finally { setCurrentStep(inactiveStep); registeringOnAuthoritativeKeyserverRef.current = false; } })(); - }, [currentStep, isRegisteredOnIdentity, keyserverAuth]); + }, [currentStep, isRegisteredOnIdentity, keyserverAuth, dispatch]); return returnedFunc; } function usePasswordLogIn(): ( username: string, password: string, ) => Promise { const logIn = useLogIn(); return React.useCallback( (username: string, password: string) => logIn({ accountType: 'username', username, password, }), [logIn], ); } function useWalletLogIn(): ( walletAddress: string, siweMessage: string, siweSignature: string, ) => Promise { const logIn = useLogIn(); return React.useCallback( (walletAddress: string, siweMessage: string, siweSignature: string) => logIn({ accountType: 'ethereum', walletAddress, siweMessage, siweSignature, }), [logIn], ); } export { usePasswordLogIn, useWalletLogIn }; diff --git a/lib/reducers/data-loaded-reducer.js b/lib/reducers/data-loaded-reducer.js index 908dfd76c..0c73faeef 100644 --- a/lib/reducers/data-loaded-reducer.js +++ b/lib/reducers/data-loaded-reducer.js @@ -1,37 +1,32 @@ // @flow import { setDataLoadedActionType } from '../actions/client-db-store-actions.js'; import { - keyserverAuthActionTypes, logOutActionTypes, legacyLogInActionTypes, } from '../actions/user-actions.js'; import { setNewSessionActionType } from '../keyserver-conn/keyserver-conn-types.js'; import type { BaseAction } from '../types/redux-types.js'; import { authoritativeKeyserverID } from '../utils/authoritative-keyserver.js'; import { relyingOnAuthoritativeKeyserver } from '../utils/services-utils.js'; export default function reduceDataLoaded( state: boolean, action: BaseAction, ): boolean { if (action.type === setDataLoadedActionType) { return action.payload.dataLoaded; } else if (action.type === legacyLogInActionTypes.success) { return true; } else if ( action.type === setNewSessionActionType && action.payload.sessionChange.cookieInvalidated && action.payload.keyserverID === authoritativeKeyserverID() && relyingOnAuthoritativeKeyserver ) { return false; } else if (action.type === logOutActionTypes.started) { return false; - } else if (action.type === keyserverAuthActionTypes.success) { - if (authoritativeKeyserverID() in action.payload.updatesCurrentAsOf) { - return true; - } } return state; }