diff --git a/src/App.tsx b/src/App.tsx index 9285be41a..ac6918dcb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -25,6 +25,7 @@ import UiLoader from './components/common/UiLoader'; type StateProps = { authState: GlobalState['authState']; isScreenLocked?: boolean; + hasPasscode?: boolean; }; enum AppScreens { @@ -37,6 +38,7 @@ enum AppScreens { const App: FC = ({ authState, isScreenLocked, + hasPasscode, }) => { const { disconnect } = getActions(); @@ -95,6 +97,8 @@ const App: FC = ({ } else if (hasStoredSession(true)) { page = 'main'; activeKey = AppScreens.main; + } else if (hasPasscode) { + activeKey = AppScreens.lock; } else { page = isMobile ? 'authPhoneNumber' : 'authQrCode'; activeKey = AppScreens.auth; @@ -138,6 +142,7 @@ export default withGlobal( return { authState: global.authState, isScreenLocked: global.passcode?.isScreenLocked, + hasPasscode: global.passcode?.hasPasscode, }; }, )(App); diff --git a/src/global/actions/api/initial.ts b/src/global/actions/api/initial.ts index a0fadfab6..5aa824511 100644 --- a/src/global/actions/api/initial.ts +++ b/src/global/actions/api/initial.ts @@ -166,18 +166,6 @@ addActionHandler('reset', () => { getActions().init(); }); -addActionHandler('softReset', () => { - clearStoredSession(); - - void clearLegacySessions(); - - updateAppBadge(0); - - let global = getGlobal(); - global = clearGlobalForLockScreen(global); - setGlobal(global); -}); - addActionHandler('disconnect', () => { void callApi('disconnect'); }); @@ -212,12 +200,14 @@ addActionHandler('deleteDeviceToken', (global) => { }; }); -addActionHandler('lockScreen', async (global, { softReset }) => { +addActionHandler('lockScreen', async (global) => { const sessionJson = JSON.stringify({ ...loadStoredSession(), userId: global.currentUserId }); const globalJson = serializeGlobal(); await encryptSession(sessionJson, globalJson); forgetPasscode(); + clearStoredSession(); + updateAppBadge(0); global = getGlobal(); setGlobal(updatePasscodeSettings( @@ -228,12 +218,14 @@ addActionHandler('lockScreen', async (global, { softReset }) => { }, )); + setTimeout(() => { + setGlobal(clearGlobalForLockScreen(getGlobal())); + }, LOCK_SCREEN_ANIMATION_DURATION_MS); + try { await unsubscribe(); await callApi('destroy', true); } catch (err) { // Do nothing } - - setTimeout(() => softReset(), LOCK_SCREEN_ANIMATION_DURATION_MS); }); diff --git a/src/global/actions/ui/passcode.ts b/src/global/actions/ui/passcode.ts index 8af9946ec..bf7fe0efc 100644 --- a/src/global/actions/ui/passcode.ts +++ b/src/global/actions/ui/passcode.ts @@ -1,9 +1,16 @@ import { addActionHandler, setGlobal, getGlobal } from '../../index'; import { clearPasscodeSettings, updatePasscodeSettings } from '../../reducers'; -import { loadStoredSession, storeSession } from '../../../util/sessions'; +import { clearStoredSession, loadStoredSession, storeSession } from '../../../util/sessions'; import { clearEncryptedSession, encryptSession, setupPasscode } from '../../../util/passcode'; import { serializeGlobal } from '../../cache'; +import { onBeforeUnload } from '../../../util/schedulers'; + +onBeforeUnload(() => { + if (getGlobal().passcode.hasPasscode) { + clearStoredSession(); + } +}); addActionHandler('setPasscode', async (global, actions, { passcode }) => { setGlobal(updatePasscodeSettings(global, { diff --git a/src/global/cache.ts b/src/global/cache.ts index fe40d7deb..2a39c1659 100644 --- a/src/global/cache.ts +++ b/src/global/cache.ts @@ -27,7 +27,7 @@ import { selectCurrentMessageList, selectVisibleUsers, } from './selectors'; -import { hasStoredSession, loadStoredSession } from '../util/sessions'; +import { hasStoredSession } from '../util/sessions'; import { INITIAL_STATE } from './initialState'; import { parseLocationHash } from '../util/routing'; import { isUserId } from './helpers'; @@ -73,10 +73,12 @@ export function loadCache(initialState: GlobalState): GlobalState | undefined { return undefined; } - if (hasStoredSession(true)) { + const cache = readCache(initialState); + + if (cache.passcode.hasPasscode || hasStoredSession(true)) { setupCaching(); - return readCache(initialState); + return cache; } else { clearCaching(); @@ -263,8 +265,7 @@ function updateCache() { if (hasPasscode) { if (!isScreenLocked) { - const sessionJson = JSON.stringify({ ...loadStoredSession(), userId: global.currentUserId }); - void encryptSession(sessionJson, serializedGlobal); + void encryptSession(undefined, serializedGlobal); } localStorage.setItem(GLOBAL_STATE_CACHE_KEY, JSON.stringify(clearGlobalForLockScreen(global))); diff --git a/src/global/types.ts b/src/global/types.ts index cbe778f27..4b2f9afc5 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -882,7 +882,6 @@ export interface ActionPayloads { lockScreen: never; unlockScreen: { sessionJson: string; globalJson: string }; softSignIn: never; - softReset: never; logInvalidUnlockAttempt: never; resetInvalidUnlockAttempts: never; setPasscodeError: { error: string }; diff --git a/src/util/passcode.ts b/src/util/passcode.ts index ec5c0c12c..68a948787 100644 --- a/src/util/passcode.ts +++ b/src/util/passcode.ts @@ -10,19 +10,24 @@ export async function setupPasscode(passcode: string) { currentPasscodeHash = await sha256(passcode); } -export async function encryptSession(sessionJson: string, globalJson: string) { +export async function encryptSession(sessionJson?: string, globalJson?: string) { if (!currentPasscodeHash) { throw new Error('[api/passcode] Missing current passcode'); } - const [sessionEncrypted, globalEncrypted] = await Promise.all([ - aesEncrypt(sessionJson, currentPasscodeHash), - aesEncrypt(globalJson, currentPasscodeHash), - ]); - await Promise.all([ - store('sessionEncrypted', sessionEncrypted), - store('globalEncrypted', globalEncrypted), + (async () => { + if (!sessionJson) return; + + const sessionEncrypted = await aesEncrypt(sessionJson, currentPasscodeHash); + await store('sessionEncrypted', sessionEncrypted); + })(), + (async () => { + if (!globalJson) return; + + const globalEncrypted = await aesEncrypt(globalJson, currentPasscodeHash); + await store('globalEncrypted', globalEncrypted); + })(), ]); }