diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js --- a/web/shared-worker/types/sqlite-query-executor.js +++ b/web/shared-worker/types/sqlite-query-executor.js @@ -32,7 +32,7 @@ +extras: string, }; -type OlmPersistSession = { +export type OlmPersistSession = { +targetUserID: string, +sessionData: string, }; diff --git a/web/shared-worker/worker/worker-crypto.js b/web/shared-worker/worker/worker-crypto.js --- a/web/shared-worker/worker/worker-crypto.js +++ b/web/shared-worker/worker/worker-crypto.js @@ -3,13 +3,14 @@ import olm from '@commapp/olm'; import uuid from 'uuid'; -import type { - CryptoStore, - PickledOLMAccount, - IdentityKeysBlob, - SignedIdentityKeysBlob, +import { + type CryptoStore, + type PickledOLMAccount, + type IdentityKeysBlob, + type SignedIdentityKeysBlob, } from 'lib/types/crypto-types.js'; import type { IdentityDeviceKeyUpload } from 'lib/types/identity-service-types.js'; +import { entries } from 'lib/utils/objects.js'; import { retrieveAccountKeysSet } from 'lib/utils/olm-utils.js'; import { getProcessingStoreOpsExceptionMessage } from './process-operations.js'; @@ -19,10 +20,12 @@ type WorkerResponseMessage, workerRequestMessageTypes, } from '../../types/worker-types.js'; +import type { OlmPersistSession } from '../types/sqlite-query-executor.js'; type WorkerCryptoStore = { +contentAccountPickleKey: string, +contentAccount: olm.Account, + +contentSessions: { [deviceID: string]: olm.Session }, +notificationAccountPickleKey: string, +notificationAccount: olm.Account, }; @@ -46,6 +49,7 @@ const { contentAccountPickleKey, contentAccount, + contentSessions, notificationAccountPickleKey, notificationAccount, } = cryptoStore; @@ -55,6 +59,13 @@ pickledAccount: contentAccount.pickle(contentAccountPickleKey), }; + const pickledContentSessions: OlmPersistSession[] = entries( + contentSessions, + ).map(([deviceID, session]) => ({ + targetUserID: deviceID, + sessionData: session.pickle(contentAccountPickleKey), + })); + const pickledNotificationAccount: PickledOLMAccount = { picklingKey: notificationAccountPickleKey, pickledAccount: notificationAccount.pickle(notificationAccountPickleKey), @@ -65,6 +76,9 @@ sqliteQueryExecutor.getContentAccountID(), JSON.stringify(pickledContentAccount), ); + for (const pickledSession of pickledContentSessions) { + sqliteQueryExecutor.storeOlmPersistSession(pickledSession); + } sqliteQueryExecutor.storeOlmPersistAccount( sqliteQueryExecutor.getNotifsAccountID(), JSON.stringify(pickledNotificationAccount), @@ -107,6 +121,32 @@ return { picklingKey, account }; } +function getOlmSessions(picklingKey: string): { + [deviceID: string]: olm.Session, +} { + const sqliteQueryExecutor = getSQLiteQueryExecutor(); + const dbModule = getDBModule(); + if (!sqliteQueryExecutor || !dbModule) { + throw new Error('Database not initialized'); + } + + let sessionsData; + try { + sessionsData = sqliteQueryExecutor.getOlmPersistSessionsData(); + } catch (err) { + throw new Error(getProcessingStoreOpsExceptionMessage(err, dbModule)); + } + + const sessions: { [deviceID: string]: olm.Session } = {}; + for (const sessionData of sessionsData) { + const session = new olm.Session(); + session.unpickle(picklingKey, sessionData.sessionData); + sessions[sessionData.targetUserID] = session; + } + + return sessions; +} + function unpickleInitialCryptoStoreAccount( account: PickledOLMAccount, ): olm.Account { @@ -133,6 +173,7 @@ contentAccount: unpickleInitialCryptoStoreAccount( initialCryptoStore.primaryAccount, ), + contentSessions: {}, notificationAccountPickleKey: initialCryptoStore.notificationAccount.picklingKey, notificationAccount: unpickleInitialCryptoStoreAccount( @@ -146,6 +187,7 @@ const contentAccountResult = getOrCreateOlmAccount( sqliteQueryExecutor.getContentAccountID(), ); + const contentSessions = getOlmSessions(contentAccountResult.picklingKey); const notificationAccountResult = getOrCreateOlmAccount( sqliteQueryExecutor.getNotifsAccountID(), ); @@ -153,6 +195,7 @@ cryptoStore = { contentAccountPickleKey: contentAccountResult.picklingKey, contentAccount: contentAccountResult.account, + contentSessions, notificationAccountPickleKey: notificationAccountResult.picklingKey, notificationAccount: notificationAccountResult.account, };