diff --git a/lib/selectors/socket-selectors.js b/lib/selectors/socket-selectors.js --- a/lib/selectors/socket-selectors.js +++ b/lib/selectors/socket-selectors.js @@ -90,12 +90,22 @@ return { specsPerHashKey, specPerInnerHashKey }; }); +async function getSignedIdentityKeysBlob(): Promise { + const { olmAPI } = getConfig(); + await olmAPI.initializeCryptoAccount(); + const { blobPayload, signature } = await olmAPI.getUserPublicKey(); + const signedIdentityKeysBlob: SignedIdentityKeysBlob = { + payload: blobPayload, + signature, + }; + return signedIdentityKeysBlob; +} + const getClientResponsesSelector: ( state: AppState, keyserverID: string, ) => ( calendarActive: boolean, - getSignedIdentityKeysBlob: () => Promise, getInitialNotificationsEncryptedMessage: () => Promise, serverRequests: $ReadOnlyArray, ) => Promise<$ReadOnlyArray> = createSelector( @@ -109,7 +119,6 @@ ) => { return async ( calendarActive: boolean, - getSignedIdentityKeysBlob: () => Promise, getInitialNotificationsEncryptedMessage: () => Promise, serverRequests: $ReadOnlyArray, ): Promise<$ReadOnlyArray> => { diff --git a/native/selectors/socket-selectors.js b/native/selectors/socket-selectors.js --- a/native/selectors/socket-selectors.js +++ b/native/selectors/socket-selectors.js @@ -8,7 +8,6 @@ getClientResponsesSelector, sessionStateFuncSelector, } from 'lib/selectors/socket-selectors.js'; -import type { SignedIdentityKeysBlob } from 'lib/types/crypto-types.js'; import type { ClientServerRequest, ClientClientResponse, @@ -18,7 +17,6 @@ SessionState, } from 'lib/types/session-types.js'; -import { commCoreModule } from '../native-modules.js'; import { calendarActiveSelector } from '../navigation/nav-selectors.js'; import type { AppState } from '../redux/state-types.js'; import type { NavPlusRedux } from '../types/selector-types.js'; @@ -37,16 +35,6 @@ baseSessionIdentificationSelector, ); -async function getSignedIdentityKeysBlob(): Promise { - await commCoreModule.initializeCryptoAccount(); - const { blobPayload, signature } = await commCoreModule.getUserPublicKey(); - const signedIdentityKeysBlob: SignedIdentityKeysBlob = { - payload: blobPayload, - signature, - }; - return signedIdentityKeysBlob; -} - type NativeGetClientResponsesSelectorInputType = $ReadOnly<{ ...NavPlusRedux, +getInitialNotificationsEncryptedMessage: () => Promise, @@ -67,7 +55,6 @@ ( getClientResponsesFunc: ( calendarActive: boolean, - getSignedIdentityKeysBlob: () => Promise, getInitialNotificationsEncryptedMessage: () => Promise, serverRequests: $ReadOnlyArray, ) => Promise<$ReadOnlyArray>, @@ -77,7 +64,6 @@ (serverRequests: $ReadOnlyArray) => getClientResponsesFunc( calendarActive, - getSignedIdentityKeysBlob, getInitialNotificationsEncryptedMessage, serverRequests, ), diff --git a/web/account/account-hooks.js b/web/account/account-hooks.js deleted file mode 100644 --- a/web/account/account-hooks.js +++ /dev/null @@ -1,226 +0,0 @@ -// @flow - -import olm from '@commapp/olm'; -import invariant from 'invariant'; -import * as React from 'react'; -import uuid from 'uuid'; - -import type { - SignedIdentityKeysBlob, - CryptoStore, - IdentityKeysBlob, - CryptoStoreContextType, -} from 'lib/types/crypto-types.js'; -import { type IdentityDeviceKeyUpload } from 'lib/types/identity-service-types.js'; -import { retrieveAccountKeysSet } from 'lib/utils/olm-utils.js'; -import { useDispatch } from 'lib/utils/redux-utils.js'; - -import { initOlm } from '../olm/olm-utils.js'; -import { setCryptoStore } from '../redux/crypto-store-reducer.js'; -import { useSelector } from '../redux/redux-utils.js'; - -const CryptoStoreContext: React.Context = - React.createContext(null); - -type Props = { - +children: React.Node, -}; - -function GetOrCreateCryptoStoreProvider(props: Props): React.Node { - const dispatch = useDispatch(); - const createCryptoStore = React.useCallback(async () => { - await initOlm(); - - const identityAccount = new olm.Account(); - identityAccount.create(); - const { ed25519: identityED25519, curve25519: identityCurve25519 } = - JSON.parse(identityAccount.identity_keys()); - - const identityAccountPicklingKey = uuid.v4(); - const pickledIdentityAccount = identityAccount.pickle( - identityAccountPicklingKey, - ); - - const notificationAccount = new olm.Account(); - notificationAccount.create(); - const { ed25519: notificationED25519, curve25519: notificationCurve25519 } = - JSON.parse(notificationAccount.identity_keys()); - - const notificationAccountPicklingKey = uuid.v4(); - const pickledNotificationAccount = notificationAccount.pickle( - notificationAccountPicklingKey, - ); - - const newCryptoStore = { - primaryAccount: { - picklingKey: identityAccountPicklingKey, - pickledAccount: pickledIdentityAccount, - }, - primaryIdentityKeys: { - ed25519: identityED25519, - curve25519: identityCurve25519, - }, - notificationAccount: { - picklingKey: notificationAccountPicklingKey, - pickledAccount: pickledNotificationAccount, - }, - notificationIdentityKeys: { - ed25519: notificationED25519, - curve25519: notificationCurve25519, - }, - }; - - dispatch({ type: setCryptoStore, payload: newCryptoStore }); - return newCryptoStore; - }, [dispatch]); - - const currentCryptoStore = useSelector(state => state.cryptoStore); - const createCryptoStorePromiseRef = React.useRef>(null); - const getCryptoStorePromise = React.useCallback(() => { - if (currentCryptoStore) { - return Promise.resolve(currentCryptoStore); - } - - const currentCreateCryptoStorePromiseRef = - createCryptoStorePromiseRef.current; - if (currentCreateCryptoStorePromiseRef) { - return currentCreateCryptoStorePromiseRef; - } - - const newCreateCryptoStorePromise = (async () => { - try { - return await createCryptoStore(); - } catch (e) { - createCryptoStorePromiseRef.current = undefined; - throw e; - } - })(); - - createCryptoStorePromiseRef.current = newCreateCryptoStorePromise; - return newCreateCryptoStorePromise; - }, [createCryptoStore, currentCryptoStore]); - - const isCryptoStoreSet = !!currentCryptoStore; - React.useEffect(() => { - if (!isCryptoStoreSet) { - createCryptoStorePromiseRef.current = undefined; - } - }, [isCryptoStoreSet]); - - const contextValue = React.useMemo( - () => ({ - getInitializedCryptoStore: getCryptoStorePromise, - }), - [getCryptoStorePromise], - ); - - return ( - - {props.children} - - ); -} - -function useGetOrCreateCryptoStore(): () => Promise { - const context = React.useContext(CryptoStoreContext); - invariant(context, 'CryptoStoreContext not found'); - return context.getInitializedCryptoStore; -} - -function useGetSignedIdentityKeysBlob(): () => Promise { - const getOrCreateCryptoStore = useGetOrCreateCryptoStore(); - - return React.useCallback(async () => { - const [{ primaryAccount, primaryIdentityKeys, notificationIdentityKeys }] = - await Promise.all([getOrCreateCryptoStore(), initOlm()]); - const primaryOLMAccount = new olm.Account(); - primaryOLMAccount.unpickle( - primaryAccount.picklingKey, - primaryAccount.pickledAccount, - ); - - const identityKeysBlob: IdentityKeysBlob = { - primaryIdentityPublicKeys: primaryIdentityKeys, - notificationIdentityPublicKeys: notificationIdentityKeys, - }; - - const payloadToBeSigned: string = JSON.stringify(identityKeysBlob); - const signedIdentityKeysBlob: SignedIdentityKeysBlob = { - payload: payloadToBeSigned, - signature: primaryOLMAccount.sign(payloadToBeSigned), - }; - - return signedIdentityKeysBlob; - }, [getOrCreateCryptoStore]); -} - -function useGetDeviceKeyUpload(): () => Promise { - const getOrCreateCryptoStore = useGetOrCreateCryptoStore(); - // `getSignedIdentityKeysBlob()` will initialize OLM, so no need to do it - // again - const getSignedIdentityKeysBlob = useGetSignedIdentityKeysBlob(); - const dispatch = useDispatch(); - - return React.useCallback(async () => { - const [signedIdentityKeysBlob, cryptoStore] = await Promise.all([ - getSignedIdentityKeysBlob(), - getOrCreateCryptoStore(), - ]); - - const primaryOLMAccount = new olm.Account(); - const notificationOLMAccount = new olm.Account(); - primaryOLMAccount.unpickle( - cryptoStore.primaryAccount.picklingKey, - cryptoStore.primaryAccount.pickledAccount, - ); - notificationOLMAccount.unpickle( - cryptoStore.notificationAccount.picklingKey, - cryptoStore.notificationAccount.pickledAccount, - ); - - const primaryAccountKeysSet = retrieveAccountKeysSet(primaryOLMAccount); - const notificationAccountKeysSet = retrieveAccountKeysSet( - notificationOLMAccount, - ); - - const pickledPrimaryAccount = primaryOLMAccount.pickle( - cryptoStore.primaryAccount.picklingKey, - ); - const pickledNotificationAccount = notificationOLMAccount.pickle( - cryptoStore.notificationAccount.picklingKey, - ); - - const updatedCryptoStore = { - primaryAccount: { - picklingKey: cryptoStore.primaryAccount.picklingKey, - pickledAccount: pickledPrimaryAccount, - }, - primaryIdentityKeys: cryptoStore.primaryIdentityKeys, - notificationAccount: { - picklingKey: cryptoStore.notificationAccount.picklingKey, - pickledAccount: pickledNotificationAccount, - }, - notificationIdentityKeys: cryptoStore.notificationIdentityKeys, - }; - - dispatch({ type: setCryptoStore, payload: updatedCryptoStore }); - - return { - keyPayload: signedIdentityKeysBlob.payload, - keyPayloadSignature: signedIdentityKeysBlob.signature, - contentPrekey: primaryAccountKeysSet.prekey, - contentPrekeySignature: primaryAccountKeysSet.prekeySignature, - notifPrekey: notificationAccountKeysSet.prekey, - notifPrekeySignature: notificationAccountKeysSet.prekeySignature, - contentOneTimeKeys: primaryAccountKeysSet.oneTimeKeys, - notifOneTimeKeys: notificationAccountKeysSet.oneTimeKeys, - }; - }, [dispatch, getOrCreateCryptoStore, getSignedIdentityKeysBlob]); -} - -export { - useGetSignedIdentityKeysBlob, - useGetOrCreateCryptoStore, - GetOrCreateCryptoStoreProvider, - useGetDeviceKeyUpload, -}; diff --git a/web/account/log-in-form.react.js b/web/account/log-in-form.react.js --- a/web/account/log-in-form.react.js +++ b/web/account/log-in-form.react.js @@ -7,13 +7,13 @@ import { isDev } from 'lib/utils/dev-utils.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; -import { useGetOrCreateCryptoStore } from './account-hooks.js'; import css from './log-in-form.css'; import SIWEButton from './siwe-button.react.js'; import SIWELoginForm from './siwe-login-form.react.js'; import TraditionalLoginForm from './traditional-login-form.react.js'; import Button from '../components/button.react.js'; import OrBreak from '../components/or-break.react.js'; +import { olmAPI } from '../crypto/olm-api.js'; import { updateNavInfoActionType } from '../redux/action-types.js'; function LoginForm(): React.Node { @@ -21,11 +21,9 @@ const { data: signer } = useWalletClient(); const dispatch = useDispatch(); - const getOrCreateCryptoStore = useGetOrCreateCryptoStore(); - React.useEffect(() => { - void getOrCreateCryptoStore(); - }, [getOrCreateCryptoStore]); + void olmAPI.initializeCryptoAccount(); + }, []); const onQRCodeLoginButtonClick = React.useCallback(() => { dispatch({ diff --git a/web/account/qr-code-login.react.js b/web/account/qr-code-login.react.js --- a/web/account/qr-code-login.react.js +++ b/web/account/qr-code-login.react.js @@ -8,29 +8,30 @@ import { uintArrayToHexString } from 'lib/media/data-utils.js'; import css from './qr-code-login.css'; -import { useSelector } from '../redux/redux-utils.js'; +import { olmAPI } from '../crypto/olm-api.js'; function QrCodeLogin(): React.Node { const [qrCodeValue, setQrCodeValue] = React.useState(); - const ed25519Key = useSelector( - state => state.cryptoStore?.primaryIdentityKeys.ed25519, - ); const generateQRCode = React.useCallback(async () => { try { - if (!ed25519Key) { + await olmAPI.initializeCryptoAccount(); + const { + primaryIdentityPublicKeys: { ed25519 }, + } = await olmAPI.getUserPublicKey(); + if (!ed25519) { return; } const rawAESKey: Uint8Array = await generateKeyCommon(crypto); const aesKeyAsHexString: string = uintArrayToHexString(rawAESKey); - const url = qrCodeLinkURL(aesKeyAsHexString, ed25519Key); + const url = qrCodeLinkURL(aesKeyAsHexString, ed25519); setQrCodeValue(url); } catch (err) { console.error('Failed to generate QR Code:', err); } - }, [ed25519Key]); + }, []); React.useEffect(() => { void generateQRCode(); diff --git a/web/account/siwe-login-form.react.js b/web/account/siwe-login-form.react.js --- a/web/account/siwe-login-form.react.js +++ b/web/account/siwe-login-form.react.js @@ -28,7 +28,6 @@ LogInStartingPayload, LogInExtraInfo, } from 'lib/types/account-types.js'; -import type { OLMIdentityKeys } from 'lib/types/crypto-types.js'; import { useLegacyAshoatKeyserverCall } from 'lib/utils/action-utils.js'; import { getMessageForException, ServerError } from 'lib/utils/errors.js'; import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; @@ -40,11 +39,11 @@ siweMessageSigningExplanationStatements, } from 'lib/utils/siwe-utils.js'; -import { useGetSignedIdentityKeysBlob } from './account-hooks.js'; import HeaderSeparator from './header-separator.react.js'; import css from './siwe.css'; import Button from '../components/button.react.js'; import OrBreak from '../components/or-break.react.js'; +import { olmAPI } from '../crypto/olm-api.js'; import LoadingIndicator from '../loading-indicator.react.js'; import { useSelector } from '../redux/redux-utils.js'; @@ -117,24 +116,18 @@ siweNonceShouldBeFetched, ]); - const primaryIdentityPublicKeys: ?OLMIdentityKeys = useSelector( - state => state.cryptoStore?.primaryIdentityKeys, - ); - - const getSignedIdentityKeysBlob = useGetSignedIdentityKeysBlob(); - const callLegacySIWEAuthEndpoint = React.useCallback( async (message: string, signature: string, extraInfo: LogInExtraInfo) => { - const signedIdentityKeysBlob = await getSignedIdentityKeysBlob(); - invariant( - signedIdentityKeysBlob, - 'signedIdentityKeysBlob must be set in attemptSIWEAuth', - ); + await olmAPI.initializeCryptoAccount(); + const userPublicKey = await olmAPI.getUserPublicKey(); try { return await legacySiweAuthCall({ message, signature, - signedIdentityKeysBlob, + signedIdentityKeysBlob: { + payload: userPublicKey.blobPayload, + signature: userPublicKey.signature, + }, doNotRegister: true, ...extraInfo, }); @@ -148,7 +141,7 @@ throw e; } }, - [getSignedIdentityKeysBlob, legacySiweAuthCall], + [legacySiweAuthCall], ); const attemptLegacySIWEAuth = React.useCallback( @@ -190,13 +183,11 @@ const onSignInButtonClick = React.useCallback(async () => { invariant(signer, 'signer must be present during SIWE attempt'); invariant(siweNonce, 'nonce must be present during SIWE attempt'); - invariant( - primaryIdentityPublicKeys, - 'primaryIdentityPublicKeys must be present during SIWE attempt', - ); - const statement = getSIWEStatementForPublicKey( - primaryIdentityPublicKeys.ed25519, - ); + await olmAPI.initializeCryptoAccount(); + const { + primaryIdentityPublicKeys: { ed25519 }, + } = await olmAPI.getUserPublicKey(); + const statement = getSIWEStatementForPublicKey(ed25519); const message = createSIWEMessage(address, statement, siweNonce); const signature = await signer.signMessage({ message }); if (usingCommServicesAccessToken) { @@ -214,7 +205,6 @@ address, attemptLegacySIWEAuth, attemptIdentityWalletLogIn, - primaryIdentityPublicKeys, signer, siweNonce, dispatch, @@ -243,11 +233,7 @@ [css.hidden]: !error, }); - if ( - siweAuthLoadingStatus === 'loading' || - !siweNonce || - !primaryIdentityPublicKeys - ) { + if (siweAuthLoadingStatus === 'loading' || !siweNonce) { return (
diff --git a/web/account/traditional-login-form.react.js b/web/account/traditional-login-form.react.js --- a/web/account/traditional-login-form.react.js +++ b/web/account/traditional-login-form.react.js @@ -25,11 +25,11 @@ import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import { usingCommServicesAccessToken } from 'lib/utils/services-utils.js'; -import { useGetSignedIdentityKeysBlob } from './account-hooks.js'; import HeaderSeparator from './header-separator.react.js'; import css from './log-in-form.css'; import PasswordInput from './password-input.react.js'; import Button from '../components/button.react.js'; +import { olmAPI } from '../crypto/olm-api.js'; import LoadingIndicator from '../loading-indicator.react.js'; import Input from '../modals/input.react.js'; import { useSelector } from '../redux/redux-utils.js'; @@ -44,8 +44,6 @@ const dispatchActionPromise = useDispatchActionPromise(); const modalContext = useModalContext(); - const getSignedIdentityKeysBlob = useGetSignedIdentityKeysBlob(); - const usernameInputRef = React.useRef(); React.useEffect(() => { usernameInputRef.current?.focus(); @@ -77,19 +75,18 @@ const legacyLogInAction = React.useCallback( async (extraInfo: LogInExtraInfo) => { - const signedIdentityKeysBlob = await getSignedIdentityKeysBlob(); + await olmAPI.initializeCryptoAccount(); + const userPublicKey = await olmAPI.getUserPublicKey(); try { - invariant( - signedIdentityKeysBlob, - 'signedIdentityKeysBlob must be set in logInAction', - ); - const result = await callLegacyLogIn({ ...extraInfo, username, password, authActionSource: logInActionSources.logInFromWebForm, - signedIdentityKeysBlob, + signedIdentityKeysBlob: { + payload: userPublicKey.blobPayload, + signature: userPublicKey.signature, + }, }); modalContext.popModal(); return result; @@ -105,13 +102,7 @@ throw e; } }, - [ - callLegacyLogIn, - modalContext, - password, - getSignedIdentityKeysBlob, - username, - ], + [callLegacyLogIn, modalContext, password, username], ); const identityPasswordLogInAction = React.useCallback(async () => { diff --git a/web/app.react.js b/web/app.react.js --- a/web/app.react.js +++ b/web/app.react.js @@ -71,7 +71,6 @@ import VisibilityHandler from './redux/visibility-handler.react.js'; import history from './router-history.js'; import { MessageSearchStateProvider } from './search/message-search-state-provider.react.js'; -import { createTunnelbrokerInitMessage } from './selectors/tunnelbroker-selectors.js'; import AccountSettings from './settings/account-settings.react.js'; import DangerZone from './settings/danger-zone.react.js'; import KeyserverSelectionList from './settings/keyserver-selection-list.react.js'; @@ -82,6 +81,7 @@ import css from './style.css'; import { TooltipProvider } from './tooltips/tooltip-provider.js'; import { canonicalURLFromReduxState, navInfoFromURL } from './url-utils.js'; +import { useTunnelbrokerInitMessage } from './utils/tunnelbroker-utils.js'; import { useWebLock, TUNNELBROKER_LOCK_NAME } from './web-lock.js'; void initOpaque(); @@ -520,7 +520,7 @@ [modalContext.modals], ); - const tunnelbrokerInitMessage = useSelector(createTunnelbrokerInitMessage); + const tunnelbrokerInitMessage = useTunnelbrokerInitMessage(); const { lockStatus, releaseLockOrAbortRequest } = useWebLock( TUNNELBROKER_LOCK_NAME, diff --git a/web/crypto/olm-api.js b/web/crypto/olm-api.js --- a/web/crypto/olm-api.js +++ b/web/crypto/olm-api.js @@ -1,7 +1,5 @@ // @flow -import olm from '@commapp/olm'; - import { type OlmAPI } from 'lib/types/crypto-types.js'; import { getCommSharedWorker } from '../shared-worker/shared-worker-provider.js'; @@ -11,8 +9,6 @@ workerResponseMessageTypes, } from '../types/worker-types.js'; -const usingSharedWorker = false; - function proxyToWorker( method: $Keys, ): (...args: $ReadOnlyArray) => Promise { @@ -41,15 +37,11 @@ const olmAPI: OlmAPI = { async initializeCryptoAccount(): Promise { - if (usingSharedWorker) { - const sharedWorker = await getCommSharedWorker(); - await sharedWorker.schedule({ - type: workerRequestMessageTypes.INITIALIZE_CRYPTO_ACCOUNT, - olmWasmPath: getOlmWasmPath(), - }); - } else { - await olm.init(); - } + const sharedWorker = await getCommSharedWorker(); + await sharedWorker.schedule({ + type: workerRequestMessageTypes.INITIALIZE_CRYPTO_ACCOUNT, + olmWasmPath: getOlmWasmPath(), + }); }, getUserPublicKey: proxyToWorker('getUserPublicKey'), encrypt: proxyToWorker('encrypt'), @@ -61,4 +53,4 @@ validateAndUploadPrekeys: proxyToWorker('validateAndUploadPrekeys'), }; -export { olmAPI, usingSharedWorker }; +export { olmAPI }; diff --git a/web/grpc/identity-service-context-provider.react.js b/web/grpc/identity-service-context-provider.react.js --- a/web/grpc/identity-service-context-provider.react.js +++ b/web/grpc/identity-service-context-provider.react.js @@ -6,12 +6,9 @@ IdentityClientContext, type AuthMetadata, } from 'lib/shared/identity-client-context.js'; -import { getConfig } from 'lib/utils/config.js'; +import { getContentSigningKey } from 'lib/utils/crypto-utils.js'; import { IdentityServiceClientSharedProxy } from './identity-service-client-proxy.js'; -import { IdentityServiceClientWrapper } from './identity-service-client-wrapper.js'; -import { useGetDeviceKeyUpload } from '../account/account-hooks.js'; -import { usingSharedWorker } from '../crypto/olm-api.js'; import { useSelector } from '../redux/redux-utils.js'; type Props = { @@ -22,10 +19,14 @@ const userID = useSelector(state => state.currentUserInfo?.id); const accessToken = useSelector(state => state.commServicesAccessToken); - const deviceID = useSelector( - state => state.cryptoStore?.primaryIdentityKeys.ed25519, - ); - const getDeviceKeyUpload = useGetDeviceKeyUpload(); + const [deviceID, setDeviceID] = React.useState(null); + + React.useEffect(() => { + void (async () => { + const contentSigningKey = await getContentSigningKey(); + setDeviceID(contentSigningKey); + })(); + }, [accessToken]); const client = React.useMemo(() => { let authLayer = null; @@ -36,26 +37,20 @@ commServicesAccessToken: accessToken, }; } - if (usingSharedWorker) { - return new IdentityServiceClientSharedProxy(authLayer); - } else { - return new IdentityServiceClientWrapper( - getConfig().platformDetails, - null, - authLayer, - getDeviceKeyUpload, - ); - } - }, [accessToken, deviceID, getDeviceKeyUpload, userID]); - const getAuthMetadata = React.useCallback<() => Promise>( - async () => ({ + return new IdentityServiceClientSharedProxy(authLayer); + }, [accessToken, deviceID, userID]); + + const getAuthMetadata = React.useCallback< + () => Promise, + >(async () => { + const contentSigningKey = await getContentSigningKey(); + return { userID, - deviceID, + deviceID: contentSigningKey, accessToken, - }), - [accessToken, deviceID, userID], - ); + }; + }, [accessToken, userID]); const value = React.useMemo( () => ({ diff --git a/web/selectors/socket-selectors.js b/web/selectors/socket-selectors.js --- a/web/selectors/socket-selectors.js +++ b/web/selectors/socket-selectors.js @@ -11,7 +11,6 @@ getClientResponsesSelector, sessionStateFuncSelector, } from 'lib/selectors/socket-selectors.js'; -import type { SignedIdentityKeysBlob } from 'lib/types/crypto-types.js'; import type { ClientServerRequest, ClientClientResponse, @@ -43,7 +42,6 @@ type WebGetClientResponsesSelectorInputType = { +state: AppState, - +getSignedIdentityKeysBlob: () => Promise, +getInitialNotificationsEncryptedMessage: () => Promise, +keyserverID: string, }; @@ -55,8 +53,6 @@ ) => Promise<$ReadOnlyArray> = createSelector( (input: WebGetClientResponsesSelectorInputType) => getClientResponsesSelector(input.state, input.keyserverID), - (input: WebGetClientResponsesSelectorInputType) => - input.getSignedIdentityKeysBlob, (input: WebGetClientResponsesSelectorInputType) => input.state.navInfo.tab === 'calendar', (input: WebGetClientResponsesSelectorInputType) => @@ -64,18 +60,15 @@ ( getClientResponsesFunc: ( calendarActive: boolean, - getSignedIdentityKeysBlob: () => Promise, getInitialNotificationsEncryptedMessage: () => Promise, serverRequests: $ReadOnlyArray, ) => Promise<$ReadOnlyArray>, - getSignedIdentityKeysBlob: () => Promise, calendarActive: boolean, getInitialNotificationsEncryptedMessage: () => Promise, ) => (serverRequests: $ReadOnlyArray) => getClientResponsesFunc( calendarActive, - getSignedIdentityKeysBlob, getInitialNotificationsEncryptedMessage, serverRequests, ), diff --git a/web/selectors/tunnelbroker-selectors.js b/web/selectors/tunnelbroker-selectors.js deleted file mode 100644 --- a/web/selectors/tunnelbroker-selectors.js +++ /dev/null @@ -1,30 +0,0 @@ -// @flow - -import { createSelector } from 'reselect'; - -import type { ConnectionInitializationMessage } from 'lib/types/tunnelbroker/session-types.js'; - -import type { AppState } from '../redux/redux-setup.js'; - -export const createTunnelbrokerInitMessage: AppState => ?ConnectionInitializationMessage = - createSelector( - (state: AppState) => state.cryptoStore?.primaryIdentityKeys?.ed25519, - (state: AppState) => state.commServicesAccessToken, - (state: AppState) => state.currentUserInfo?.id, - ( - deviceID: ?string, - accessToken: ?string, - userID: ?string, - ): ?ConnectionInitializationMessage => { - if (!deviceID || !accessToken || !userID) { - return null; - } - return ({ - type: 'ConnectionInitializationMessage', - deviceID, - accessToken, - userID, - deviceType: 'web', - }: ConnectionInitializationMessage); - }, - ); diff --git a/web/socket.react.js b/web/socket.react.js --- a/web/socket.react.js +++ b/web/socket.react.js @@ -15,7 +15,6 @@ import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; -import { useGetSignedIdentityKeysBlob } from './account/account-hooks.js'; import { useSelector } from './redux/redux-utils.js'; import { activeThreadSelector, @@ -50,13 +49,11 @@ const preRequestUserState = useSelector( preRequestUserStateForSingleKeyserverSelector(keyserverID), ); - const getSignedIdentityKeysBlob = useGetSignedIdentityKeysBlob(); const getInitialNotificationsEncryptedMessage = useInitialNotificationsEncryptedMessage(keyserverID); const getClientResponses = useSelector(state => webGetClientResponsesSelector({ state, - getSignedIdentityKeysBlob, getInitialNotificationsEncryptedMessage, keyserverID, }), diff --git a/web/utils/tunnelbroker-utils.js b/web/utils/tunnelbroker-utils.js new file mode 100644 --- /dev/null +++ b/web/utils/tunnelbroker-utils.js @@ -0,0 +1,36 @@ +// @flow + +import * as React from 'react'; + +import type { ConnectionInitializationMessage } from 'lib/types/tunnelbroker/session-types.js'; +import { getContentSigningKey } from 'lib/utils/crypto-utils.js'; + +import { useSelector } from '../redux/redux-utils.js'; + +function useTunnelbrokerInitMessage(): ?ConnectionInitializationMessage { + const [deviceID, setDeviceID] = React.useState(); + const accessToken = useSelector(state => state.commServicesAccessToken); + const userID = useSelector(state => state.currentUserInfo?.id); + + React.useEffect(() => { + void (async () => { + const contentSigningKey = await getContentSigningKey(); + setDeviceID(contentSigningKey); + })(); + }, [accessToken]); + + return React.useMemo(() => { + if (!deviceID || !accessToken || !userID) { + return null; + } + return ({ + type: 'ConnectionInitializationMessage', + deviceID, + accessToken, + userID, + deviceType: 'mobile', + }: ConnectionInitializationMessage); + }, [accessToken, deviceID, userID]); +} + +export { useTunnelbrokerInitMessage };