diff --git a/lib/utils/config.js b/lib/utils/config.js --- a/lib/utils/config.js +++ b/lib/utils/config.js @@ -9,6 +9,7 @@ import type { OlmAPI } from '../types/crypto-types.js'; import type { PlatformDetails } from '../types/device-types.js'; import type { SQLiteAPI } from '../types/sqlite-types.js'; +import type { CurrentUserInfo } from '../types/user-types.js'; import type { DispatchActionPromise } from '../utils/redux-promise-utils.js'; export type Config = { @@ -29,6 +30,9 @@ +authoritativeKeyserverID: string, +olmAPI: OlmAPI, +sqliteAPI: SQLiteAPI, + +createBackupCompaction?: ( + currentUserInfo: ?CurrentUserInfo, + ) => Promise, }; let registeredConfig: ?Config = null; diff --git a/lib/utils/migration-utils.js b/lib/utils/migration-utils.js --- a/lib/utils/migration-utils.js +++ b/lib/utils/migration-utils.js @@ -6,6 +6,7 @@ import { getConfig } from './config.js'; import type { TranslatedThreadMessageInfos } from './message-ops-utils.js'; import { entries } from './objects.js'; +import { backupEnabledByDefault } from './services-utils.js'; import { convertRawMessageInfoToNewIDSchema, convertRawThreadInfoToNewIDSchema, @@ -252,7 +253,7 @@ return state; } - const { state: newState } = await runMigrations( + const { state: newState, schemaChanged } = await runMigrations( legacyMigrations, migrations, state, @@ -262,6 +263,16 @@ handleException, ); + if ( + schemaChanged && + state.currentUserInfo && + !state.currentUserInfo.anonymous && + backupEnabledByDefault + ) { + await getConfig().olmAPI.initializeCryptoAccount(); + await getConfig().createBackupCompaction?.(state.currentUserInfo); + } + return newState; }; } diff --git a/lib/utils/services-utils.js b/lib/utils/services-utils.js --- a/lib/utils/services-utils.js +++ b/lib/utils/services-utils.js @@ -18,6 +18,12 @@ // an authoritative keyserver for things like DMs. const relyingOnAuthoritativeKeyserver = true; +// Currently, the backup can only be performed when a switch in dev menu is +// enabled. At some point we will remove the switch and start performing +// the backup for all the primary devices. If this flag is true, we're assuming +// that all the primary devices are backed up. +const backupEnabledByDefault = false; + function handleHTTPResponseError(response: Response): void { if (!response.ok) { const { status, statusText } = response; @@ -47,6 +53,7 @@ usingCommServicesAccessToken, supportingMultipleKeyservers, relyingOnAuthoritativeKeyserver, + backupEnabledByDefault, createHTTPAuthorizationHeader, createDefaultHTTPRequestHeaders, }; 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 @@ -5,6 +5,7 @@ import { isLoggedIn } from 'lib/selectors/user-selectors.js'; import { accountHasPassword } from 'lib/shared/account-utils.js'; import type { SIWEBackupSecrets } from 'lib/types/siwe-types.js'; +import type { CurrentUserInfo } from 'lib/types/user-types'; import { getContentSigningKey } from 'lib/utils/crypto-utils.js'; import { runMigrations } from 'lib/utils/migration-utils.js'; @@ -39,6 +40,17 @@ return siweBackupSecrets; } +async function createBackup(currentUserInfo: ?CurrentUserInfo): Promise { + commCoreModule.startBackupHandler(); + if (accountHasPassword(currentUserInfo)) { + const backupSecret = await getBackupSecret(); + await commCoreModule.createNewBackup(backupSecret); + } else { + const { message, signature } = await getSIWEBackupSecrets(); + await commCoreModule.createNewSIWEBackup(signature, message); + } +} + function useClientBackup(): ClientBackup { const accessToken = useSelector(state => state.commServicesAccessToken); const currentUserID = useSelector( @@ -69,13 +81,7 @@ await setMockCommServicesAuthMetadata(); - if (accountHasPassword(currentUserInfo)) { - const backupSecret = await getBackupSecret(); - await commCoreModule.createNewBackup(backupSecret); - } else { - const { message, signature } = await getSIWEBackupSecrets(); - await commCoreModule.createNewSIWEBackup(signature, message); - } + await createBackup(currentUserInfo); console.info('Backup uploaded.'); }, [ @@ -112,6 +118,7 @@ version: backupVersionNumber, rehydrated: true, }, + currentUserInfo, }, backupVersionNumber, persistConfig.version, @@ -119,9 +126,14 @@ ); console.info('Backup restored.'); - }, [currentUserID, loggedIn, setMockCommServicesAuthMetadata]); + }, [ + currentUserID, + currentUserInfo, + loggedIn, + setMockCommServicesAuthMetadata, + ]); return { uploadBackupProtocol, restoreBackupProtocol }; } -export { getBackupSecret, useClientBackup }; +export { getBackupSecret, useClientBackup, createBackup }; diff --git a/native/config.js b/native/config.js --- a/native/config.js +++ b/native/config.js @@ -6,6 +6,7 @@ import { resolveKeyserverSessionInvalidationUsingNativeCredentials } from './account/legacy-recover-keyserver-session.js'; import { authoritativeKeyserverID } from './authoritative-keyserver.js'; +import { createBackup } from './backup/use-client-backup.js'; import { olmAPI } from './crypto/olm-api.js'; import { sqliteAPI } from './database/sqlite-api.js'; import { persistConfig, codeVersion } from './redux/persist.js'; @@ -22,4 +23,5 @@ authoritativeKeyserverID, olmAPI, sqliteAPI, + createBackupCompaction: createBackup, });