diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 2290eb69c3f6..ac19970dc635 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -131,4 +131,7 @@ export default { // Stores Workspace ID that will be tied to reimbursement account during setup REIMBURSEMENT_ACCOUNT_WORKSPACE_ID: 'reimbursementAccountWorkspaceID', + + // Notifies all tabs that they should sign out and clear storage. + SHOULD_SIGN_OUT: 'shouldSignOut', }; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 38c3639ce2ad..ce580391a5fd 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -69,6 +69,7 @@ import CardOverlay from '../../../components/CardOverlay'; import defaultScreenOptions from './defaultScreenOptions'; import * as API from '../../API'; import {setLocale} from '../../actions/App'; +import {cleanupSession} from '../../actions/Session'; import WorkspaceNew from '../../../pages/workspace/WorkspaceNew'; Onyx.connect({ @@ -249,7 +250,7 @@ class AuthScreens extends React.Component { if (this.unsubscribeGroupShortcut) { this.unsubscribeGroupShortcut(); } - NetworkConnection.stopListeningForReconnect(); + cleanupSession(); clearInterval(this.interval); this.interval = null; hasLoadedPolicies = false; diff --git a/src/libs/SignoutManager.js b/src/libs/SignoutManager.js new file mode 100644 index 000000000000..065d8249cd10 --- /dev/null +++ b/src/libs/SignoutManager.js @@ -0,0 +1,38 @@ +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '../ONYXKEYS'; + +let signoutCallback = () => {}; +let errorMessage = ''; +let shouldSignOut = false; +Onyx.connect({ + key: ONYXKEYS.SHOULD_SIGN_OUT, + callback: (val) => { + if (!shouldSignOut && val) { + signoutCallback(errorMessage); + errorMessage = ''; + Onyx.set(ONYXKEYS.SHOULD_SIGN_OUT, false); + } + + shouldSignOut = val; + }, +}); + +/** + * @param {Function} callback + */ +function registerSignoutCallback(callback) { + signoutCallback = callback; +} + +/** + * @param {String} message + */ +function signOut(message) { + errorMessage = message; + Onyx.set(ONYXKEYS.SHOULD_SIGN_OUT, true); +} + +export default { + signOut, + registerSignoutCallback, +}; diff --git a/src/libs/actions/Session.js b/src/libs/actions/Session.js index 378a0f5d65cc..a70ec279d3b3 100644 --- a/src/libs/actions/Session.js +++ b/src/libs/actions/Session.js @@ -14,9 +14,12 @@ import Navigation from '../Navigation/Navigation'; import ROUTES from '../../ROUTES'; import {translateLocal} from '../translate'; import * as Network from '../Network'; +import UnreadIndicatorUpdater from '../UnreadIndicatorUpdater'; +import Timers from '../Timers'; +import * as Pusher from '../Pusher/pusher'; +import NetworkConnection from '../NetworkConnection'; import {getUserDetails} from './User'; - let credentials = {}; Onyx.connect({ key: ONYXKEYS.CREDENTIALS, @@ -339,6 +342,19 @@ function continueSessionFromECom(accountID, validateCode, twoFactorAuthCode) { }); } +/** + * Put any logic that needs to run when we are signed out here. This can be triggered when the current tab or another tab signs out. + */ +function cleanupSession() { + // We got signed out in this tab or another so clean up any subscriptions and timers + NetworkConnection.stopListeningForReconnect(); + UnreadIndicatorUpdater.stopListeningForReportChanges(); + PushNotification.deregister(); + PushNotification.clearNotifications(); + Pusher.disconnect(); + Timers.clearAll(); +} + export { continueSessionFromECom, fetchAccountDetails, @@ -349,4 +365,5 @@ export { reopenAccount, resendValidationLink, resetPassword, + cleanupSession, }; diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index 94bf78df5a0d..95e8b862d8bc 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -1,9 +1,6 @@ import Onyx from 'react-native-onyx'; +import SignoutManager from '../SignoutManager'; import ONYXKEYS from '../../ONYXKEYS'; -import * as Pusher from '../Pusher/pusher'; -import UnreadIndicatorUpdater from '../UnreadIndicatorUpdater'; -import PushNotification from '../Notification/PushNotification'; -import Timers from '../Timers'; let currentActiveClients; Onyx.connect({ @@ -20,18 +17,9 @@ Onyx.connect({ }); /** - * Clears the Onyx store and redirects to the sign in page. - * Normally this method would live in Session.js, but that would cause a circular dependency with Network.js. - * - * @param {String} [errorMessage] error message to be displayed on the sign in page + * @param {String} errorMessage */ -function redirectToSignIn(errorMessage) { - UnreadIndicatorUpdater.stopListeningForReportChanges(); - PushNotification.deregister(); - PushNotification.clearNotifications(); - Pusher.disconnect(); - Timers.clearAll(); - +function clearStorageAndRedirect(errorMessage) { const activeClients = currentActiveClients; const preferredLocale = currentPreferredLocale; @@ -45,18 +33,21 @@ function redirectToSignIn(errorMessage) { Onyx.set(ONYXKEYS.ACTIVE_CLIENTS, activeClients); } - const session = { - // We must set the authToken to null so that signOut action is triggered across other clients - authToken: null, - }; - - if (errorMessage) { - session.error = errorMessage; - } - // `Onyx.clear` reinitialize the Onyx instance with initial values so use `Onyx.merge` instead of `Onyx.set`. - Onyx.merge(ONYXKEYS.SESSION, session); + Onyx.merge(ONYXKEYS.SESSION, {error: errorMessage}); }); } +SignoutManager.registerSignoutCallback(clearStorageAndRedirect); + +/** + * Clears the Onyx store and redirects to the sign in page. + * Normally this method would live in Session.js, but that would cause a circular dependency with Network.js. + * + * @param {String} [errorMessage] error message to be displayed on the sign in page + */ +function redirectToSignIn(errorMessage) { + SignoutManager.signOut(errorMessage); +} + export default redirectToSignIn;