diff --git a/native/backup/use-client-backup.js b/native/backup/use-client-backup.js --- a/native/backup/use-client-backup.js +++ b/native/backup/use-client-backup.js @@ -8,10 +8,9 @@ latestBackupInfoResponseValidator, type LatestBackupInfo, } from 'lib/types/backup-types.js'; -import type { SIWEBackupSecrets } from 'lib/types/siwe-types.js'; import { assertWithValidator } from 'lib/utils/validation-utils.js'; -import { fetchNativeKeychainCredentials } from '../account/native-credentials.js'; +import { useGetBackupSecretForLoggedInUser } from './use-get-backup-secret.js'; import { commCoreModule } from '../native-modules.js'; import { useSelector } from '../redux/redux-utils.js'; @@ -20,28 +19,13 @@ +retrieveLatestBackupInfo: () => Promise, }; -async function getBackupSecret(): Promise { - const nativeCredentials = await fetchNativeKeychainCredentials(); - if (!nativeCredentials) { - throw new Error('Native credentials are missing'); - } - return nativeCredentials.password; -} - -async function getSIWEBackupSecrets(): Promise { - const siweBackupSecrets = await commCoreModule.getSIWEBackupSecrets(); - if (!siweBackupSecrets) { - throw new Error('SIWE backup message and its signature are missing'); - } - return siweBackupSecrets; -} - function useClientBackup(): ClientBackup { const currentUserID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); const currentUserInfo = useSelector(state => state.currentUserInfo); const loggedIn = useSelector(isLoggedIn); + const getBackupSecret = useGetBackupSecretForLoggedInUser(); const uploadBackupProtocol = React.useCallback(async () => { if (!loggedIn || !currentUserID) { @@ -54,12 +38,18 @@ const backupSecret = await getBackupSecret(); await commCoreModule.createNewBackup(backupSecret); } else { - const { message, signature } = await getSIWEBackupSecrets(); - await commCoreModule.createNewSIWEBackup(signature, message); + const siweBackupSecrets = await commCoreModule.getSIWEBackupSecrets(); + if (!siweBackupSecrets) { + throw new Error('SIWE backup message and its signature are missing'); + } + await commCoreModule.createNewSIWEBackup( + siweBackupSecrets.signature, + siweBackupSecrets.message, + ); } console.info('Backup uploaded.'); - }, [currentUserID, loggedIn, currentUserInfo]); + }, [loggedIn, currentUserID, currentUserInfo, getBackupSecret]); const retrieveLatestBackupInfo = React.useCallback(async () => { if (!loggedIn || !currentUserID || !currentUserInfo?.username) { @@ -85,4 +75,4 @@ ); } -export { getBackupSecret, useClientBackup }; +export { useClientBackup }; diff --git a/native/backup/use-get-backup-secret.js b/native/backup/use-get-backup-secret.js new file mode 100644 --- /dev/null +++ b/native/backup/use-get-backup-secret.js @@ -0,0 +1,37 @@ +// @flow + +import * as React from 'react'; + +import { isLoggedIn } from 'lib/selectors/user-selectors.js'; +import { accountHasPassword } from 'lib/shared/account-utils.js'; + +import { fetchNativeKeychainCredentials } from '../account/native-credentials.js'; +import { commCoreModule } from '../native-modules.js'; +import { useSelector } from '../redux/redux-utils.js'; + +function useGetBackupSecretForLoggedInUser(): () => Promise { + const currentUserInfo = useSelector(state => state.currentUserInfo); + const loggedIn = useSelector(isLoggedIn); + + return React.useCallback(async () => { + if (!loggedIn || !currentUserInfo) { + throw new Error('Attempt to get backup secret for not logged in user'); + } + + if (accountHasPassword(currentUserInfo)) { + const nativeCredentials = await fetchNativeKeychainCredentials(); + if (!nativeCredentials) { + throw new Error('Native credentials are missing'); + } + return nativeCredentials.password; + } + + const siweBackupSecrets = await commCoreModule.getSIWEBackupSecrets(); + if (!siweBackupSecrets) { + throw new Error('SIWE backup message and its signature are missing'); + } + return siweBackupSecrets.signature; + }, [loggedIn, currentUserInfo]); +} + +export { useGetBackupSecretForLoggedInUser }; diff --git a/native/profile/backup-menu.react.js b/native/profile/backup-menu.react.js --- a/native/profile/backup-menu.react.js +++ b/native/profile/backup-menu.react.js @@ -10,10 +10,8 @@ import { useDispatch } from 'lib/utils/redux-utils.js'; import type { ProfileNavigationProp } from './profile.react.js'; -import { - getBackupSecret, - useClientBackup, -} from '../backup/use-client-backup.js'; +import { useClientBackup } from '../backup/use-client-backup.js'; +import { useGetBackupSecretForLoggedInUser } from '../backup/use-get-backup-secret.js'; import Button from '../components/button.react.js'; import { commCoreModule } from '../native-modules.js'; import type { NavigationRoute } from '../navigation/route-names.js'; @@ -35,6 +33,7 @@ const colors = useColors(); const currentUserInfo = useSelector(state => state.currentUserInfo); const navigation = useNavigation(); + const getBackupSecret = useGetBackupSecretForLoggedInUser(); const isBackupEnabled = useSelector( state => state.localSettings.isBackupEnabled, @@ -71,7 +70,7 @@ console.error(message); } Alert.alert('Restore protocol result', message); - }, [retrieveLatestBackupInfo]); + }, [getBackupSecret, retrieveLatestBackupInfo]); const testLatestBackupInfo = React.useCallback(async () => { let message; diff --git a/native/profile/secondary-device-qr-code-scanner.react.js b/native/profile/secondary-device-qr-code-scanner.react.js --- a/native/profile/secondary-device-qr-code-scanner.react.js +++ b/native/profile/secondary-device-qr-code-scanner.react.js @@ -44,7 +44,7 @@ import { assertWithValidator } from 'lib/utils/validation-utils.js'; import type { ProfileNavigationProp } from './profile.react.js'; -import { getBackupSecret } from '../backup/use-client-backup.js'; +import { useGetBackupSecretForLoggedInUser } from '../backup/use-get-backup-secret.js'; import TextInput from '../components/text-input.react.js'; import { commCoreModule } from '../native-modules.js'; import HeaderRightTextButton from '../navigation/header-right-text-button.react.js'; @@ -88,6 +88,7 @@ const foreignPeerDevices = useSelector(getForeignPeerDeviceIDs); const ownPeerDevices = useSelector(getOwnPeerDevices); const keyserverDeviceID = getKeyserverDeviceID(ownPeerDevices); + const getBackupSecret = useGetBackupSecretForLoggedInUser(); const { panelForegroundTertiaryLabel } = useColors(); @@ -187,6 +188,7 @@ broadcastDeviceListUpdates, foreignPeerDevices, getAndUpdateDeviceListsForUsers, + getBackupSecret, tunnelbrokerContext, goBack, ],