diff --git a/lib/components/secondary-device-qr-auth-context-provider.react.js b/lib/components/secondary-device-qr-auth-context-provider.react.js --- a/lib/components/secondary-device-qr-auth-context-provider.react.js +++ b/lib/components/secondary-device-qr-auth-context-provider.react.js @@ -3,6 +3,8 @@ import invariant from 'invariant'; import * as React from 'react'; +import { useDebugLogs } from './debug-logs-context.js'; +import { setClientDBStoreActionType } from '../actions/client-db-store-actions.js'; import { qrCodeLinkURL } from '../facts/links.js'; import { useSecondaryDeviceLogIn } from '../hooks/login-hooks.js'; import { uintArrayToHexString } from '../media/data-utils.js'; @@ -10,6 +12,7 @@ import { IdentityClientContext } from '../shared/identity-client-context.js'; import { useTunnelbroker } from '../tunnelbroker/tunnelbroker-context.js'; import { platformToIdentityDeviceType } from '../types/identity-service-types.js'; +import type { IdentityAuthResult } from '../types/identity-service-types.js'; import { type TunnelbrokerToDeviceMessage, tunnelbrokerToDeviceMessageTypes, @@ -22,11 +25,13 @@ import { type QRCodeAuthMessagePayload, qrCodeAuthMessageTypes, + type QRAuthBackupData, } from '../types/tunnelbroker/qr-code-auth-message-types.js'; import { getConfig } from '../utils/config.js'; import { getContentSigningKey } from '../utils/crypto-utils.js'; import { getMessageForException } from '../utils/errors.js'; -import { useSelector } from '../utils/redux-utils.js'; +import { useDispatch, useSelector } from '../utils/redux-utils.js'; +import { fullBackupSupport } from '../utils/services-utils.js'; type Props = { +children: React.Node, @@ -103,12 +108,13 @@ const logInSecondaryDevice = useSecondaryDeviceLogIn(); const performLogIn = React.useCallback( - async (userID: string) => { + async (userID: string): Promise => { try { - await logInSecondaryDevice(userID); + return await logInSecondaryDevice(userID); } catch (err) { onLogInError(err); void openSecondaryQRAuth(); + return null; } }, [logInSecondaryDevice, onLogInError, openSecondaryQRAuth], @@ -144,6 +150,42 @@ qrAuthFinished, ]); + const dispatch = useDispatch(); + const { addLog } = useDebugLogs(); + const restoreUserData = React.useCallback( + async ( + backupData: ?QRAuthBackupData, + identityAuthResult: ?IdentityAuthResult, + ) => { + if (!fullBackupSupport) { + return; + } + try { + const { sqliteAPI } = getConfig(); + if (!identityAuthResult) { + throw new Error('Missing identityAuthResult'); + } + if (!backupData) { + throw new Error('Missing backupData'); + } + await sqliteAPI.restoreUserData(backupData, identityAuthResult); + const clientDBStore = await sqliteAPI.getClientDBStore( + identityAuthResult.userID, + ); + dispatch({ + type: setClientDBStoreActionType, + payload: clientDBStore, + }); + } catch (e) { + addLog( + 'Error when restoring User Data', + getMessageForException(e) ?? 'unknown error', + ); + } + }, + [addLog, dispatch], + ); + const tunnelbrokerMessageListener = React.useCallback( async (message: TunnelbrokerToDeviceMessage) => { invariant(identityClient, 'identity context not set'); @@ -187,8 +229,11 @@ ) { return; } - const { primaryDeviceID: receivedPrimaryDeviceID, userID } = - qrCodeAuthMessage; + const { + primaryDeviceID: receivedPrimaryDeviceID, + userID, + backupData, + } = qrCodeAuthMessage; setPrimaryDeviceID(receivedPrimaryDeviceID); try { @@ -200,18 +245,20 @@ ); } - await performLogIn(userID); + const identityAuthResult = await performLogIn(userID); + await restoreUserData(backupData, identityAuthResult); setUnauthorizedDeviceID(null); }, [ identityClient, qrData?.aesKey, socketState.isAuthorized, + loggedIn, performLogIn, + restoreUserData, setUnauthorizedDeviceID, parseTunnelbrokerQRAuthMessage, confirmMessageToTunnelbroker, - loggedIn, ], );