From 757af2cbbe28d06c9f8018fa5830633463165b7f Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Thu, 18 Aug 2022 13:44:53 -0700 Subject: [PATCH] Include ACI+Access Keys pairs with CDSI requests --- config/default.json | 2 +- ts/ConversationController.ts | 5 ++- ts/background.ts | 5 ++- ts/models/conversations.ts | 6 +-- ts/sql/Client.ts | 8 ++-- ts/state/ducks/accounts.ts | 20 ++++++--- .../updateConversationsWithUuidLookup_test.ts | 45 +++++++++---------- ts/textsecure/OutgoingMessage.ts | 6 +-- ts/textsecure/SendMessage.ts | 26 +---------- ts/textsecure/WebAPI.ts | 39 ++++------------ ts/textsecure/cds/CDSSocketBase.ts | 32 +++++-------- ts/textsecure/cds/LegacyCDS.ts | 5 --- ts/textsecure/cds/Types.d.ts | 4 +- ts/updateConversationsWithUuidLookup.ts | 23 +++++----- ts/util/getUuidsForE164s.ts | 45 +++++++++++++++++++ ts/util/index.ts | 2 + ts/util/lookupConversationWithoutUuid.ts | 16 ++++--- 17 files changed, 145 insertions(+), 144 deletions(-) create mode 100644 ts/util/getUuidsForE164s.ts diff --git a/config/default.json b/config/default.json index 538315950e..e9b18e9911 100644 --- a/config/default.json +++ b/config/default.json @@ -9,7 +9,7 @@ "directoryV2PublicKey": null, "directoryV2CodeHashes": null, "directoryV3Url": "https://cdsi.staging.signal.org", - "directoryV3MRENCLAVE": "7b75dd6e862decef9b37132d54be082441917a7790e82fe44f9cf653de03a75f", + "directoryV3MRENCLAVE": "ddc7b9b1cbcc932e24b9905e26c4ecbea3f9b7effd033f9e96488c2e8449f64e", "cdn": { "0": "https://cdn-staging.signal.org", "2": "https://cdn2-staging.signal.org" diff --git a/ts/ConversationController.ts b/ts/ConversationController.ts index f64ef6820c..fef7ebf48c 100644 --- a/ts/ConversationController.ts +++ b/ts/ConversationController.ts @@ -27,6 +27,7 @@ import { QualifiedAddress } from './types/QualifiedAddress'; import { sleep } from './util/sleep'; import { isNotNil } from './util/isNotNil'; import { MINUTE, SECOND } from './util/durations'; +import { getUuidsForE164s } from './util/getUuidsForE164s'; type ConvoMatchType = | { @@ -1104,7 +1105,9 @@ export class ConversationController { async _forgetE164(e164: string): Promise { const { server } = window.textsecure; strictAssert(server, 'Server must be initialized'); - const { [e164]: pni } = await server.getUuidsForE164s([e164]); + const uuidMap = await getUuidsForE164s(server, [e164]); + + const pni = uuidMap.get(e164)?.pni; log.info(`ConversationController: forgetting e164=${e164} pni=${pni}`); diff --git a/ts/background.ts b/ts/background.ts index e229d59334..3819dde543 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -2128,15 +2128,16 @@ export async function startApp(): Promise { !c.isEverUnregistered() ) ); + strictAssert(window.textsecure.server, 'server must be initialized'); await updateConversationsWithUuidLookup({ conversationController: window.ConversationController, conversations: lonelyE164Conversations, - messaging: window.textsecure.messaging, + server: window.textsecure.server, }); } catch (error) { log.error( 'connect: Error fetching UUIDs for lonely e164s:', - error && error.stack ? error.stack : error + Errors.toLogFormat(error) ); } } diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index ecd24d4941..643c84fc71 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -1033,8 +1033,8 @@ export class ConversationModel extends window.Backbone } async fetchSMSOnlyUUID(): Promise { - const { messaging } = window.textsecure; - if (!messaging) { + const { server } = window.textsecure; + if (!server) { return; } if (!this.isSMSOnly()) { @@ -1053,7 +1053,7 @@ export class ConversationModel extends window.Backbone await updateConversationsWithUuidLookup({ conversationController: window.ConversationController, conversations: [this], - messaging, + server, }); } finally { // No redux update here diff --git a/ts/sql/Client.ts b/ts/sql/Client.ts index 2bc7c3f58c..c57c031001 100644 --- a/ts/sql/Client.ts +++ b/ts/sql/Client.ts @@ -837,10 +837,6 @@ async function removeAllSignedPreKeys(): Promise { // Items const ITEM_SPECS: Partial> = { - senderCertificate: ['value.serialized'], - senderCertificateNoE164: ['value.serialized'], - subscriberId: ['value'], - profileKey: ['value'], identityKeyMap: { key: 'value', valueSpec: { @@ -848,6 +844,10 @@ const ITEM_SPECS: Partial> = { valueSpec: ['privKey', 'pubKey'], }, }, + profileKey: ['value'], + senderCertificate: ['value.serialized'], + senderCertificateNoE164: ['value.serialized'], + subscriberId: ['value'], }; async function createOrUpdateItem( data: ItemType diff --git a/ts/state/ducks/accounts.ts b/ts/state/ducks/accounts.ts index 9b91f47329..b1ddfed178 100644 --- a/ts/state/ducks/accounts.ts +++ b/ts/state/ducks/accounts.ts @@ -8,6 +8,7 @@ import * as log from '../../logging/log'; import type { StateType as RootStateType } from '../reducer'; import type { UUIDStringType } from '../../types/UUID'; +import { getUuidsForE164s } from '../../util/getUuidsForE164s'; import type { NoopActionType } from './noop'; @@ -44,7 +45,8 @@ function checkForAccount( AccountUpdateActionType | NoopActionType > { return async (dispatch, getState) => { - if (!window.textsecure.messaging) { + const { server } = window.textsecure; + if (!server) { dispatch({ type: 'NOOP', payload: null, @@ -77,16 +79,24 @@ function checkForAccount( type: 'NOOP', payload: null, }); + return; } let uuid: UUIDStringType | undefined; log.info(`checkForAccount: looking ${phoneNumber} up on server`); try { - const uuidLookup = await window.textsecure.messaging.getUuidsForE164s([ - phoneNumber, - ]); - uuid = uuidLookup[phoneNumber] || undefined; + const uuidLookup = await getUuidsForE164s(server, [phoneNumber]); + const maybePair = uuidLookup.get(phoneNumber); + + if (maybePair) { + uuid = window.ConversationController.maybeMergeContacts({ + aci: maybePair.aci, + pni: maybePair.pni, + e164: phoneNumber, + reason: 'checkForAccount', + })?.get('uuid'); + } } catch (error) { log.error('checkForAccount:', Errors.toLogFormat(error)); } diff --git a/ts/test-electron/updateConversationsWithUuidLookup_test.ts b/ts/test-electron/updateConversationsWithUuidLookup_test.ts index 48528f16b5..a3e2994742 100644 --- a/ts/test-electron/updateConversationsWithUuidLookup_test.ts +++ b/ts/test-electron/updateConversationsWithUuidLookup_test.ts @@ -7,7 +7,7 @@ import { assert } from 'chai'; import sinon from 'sinon'; import { ConversationModel } from '../models/conversations'; import type { ConversationAttributesType } from '../model-types.d'; -import type SendMessage from '../textsecure/SendMessage'; +import type { WebAPIType } from '../textsecure/WebAPI'; import { UUID } from '../types/UUID'; import { updateConversationsWithUuidLookup } from '../updateConversationsWithUuidLookup'; @@ -137,22 +137,19 @@ describe('updateConversationsWithUuidLookup', () => { let sinonSandbox: sinon.SinonSandbox; - let fakeGetUuidsForE164s: sinon.SinonStub; + let fakeCdsLookup: sinon.SinonStub; let fakeCheckAccountExistence: sinon.SinonStub; - let fakeMessaging: Pick< - SendMessage, - 'getUuidsForE164s' | 'checkAccountExistence' - >; + let fakeServer: Pick; beforeEach(() => { sinonSandbox = sinon.createSandbox(); sinonSandbox.stub(window.Signal.Data, 'updateConversation'); - fakeGetUuidsForE164s = sinonSandbox.stub().resolves({}); + fakeCdsLookup = sinonSandbox.stub().resolves(new Map()); fakeCheckAccountExistence = sinonSandbox.stub().resolves(false); - fakeMessaging = { - getUuidsForE164s: fakeGetUuidsForE164s, + fakeServer = { + cdsLookup: fakeCdsLookup, checkAccountExistence: fakeCheckAccountExistence, }; }); @@ -165,10 +162,10 @@ describe('updateConversationsWithUuidLookup', () => { await updateConversationsWithUuidLookup({ conversationController: new FakeConversationController(), conversations: [], - messaging: fakeMessaging, + server: fakeServer, }); - sinon.assert.notCalled(fakeMessaging.getUuidsForE164s as sinon.SinonStub); + sinon.assert.notCalled(fakeServer.cdsLookup as sinon.SinonStub); }); it('does nothing when called with an array of conversations that lack E164s', async () => { @@ -178,10 +175,10 @@ describe('updateConversationsWithUuidLookup', () => { createConversation(), createConversation({ uuid: UUID.generate().toString() }), ], - messaging: fakeMessaging, + server: fakeServer, }); - sinon.assert.notCalled(fakeMessaging.getUuidsForE164s as sinon.SinonStub); + sinon.assert.notCalled(fakeServer.cdsLookup as sinon.SinonStub); }); it('updates conversations with their UUID', async () => { @@ -194,10 +191,12 @@ describe('updateConversationsWithUuidLookup', () => { const uuid1 = UUID.generate().toString(); const uuid2 = UUID.generate().toString(); - fakeGetUuidsForE164s.resolves({ - '+13215559876': uuid1, - '+16545559876': uuid2, - }); + fakeCdsLookup.resolves( + new Map([ + ['+13215559876', { aci: uuid1, pni: undefined }], + ['+16545559876', { aci: uuid2, pni: undefined }], + ]) + ); await updateConversationsWithUuidLookup({ conversationController: new FakeConversationController([ @@ -205,7 +204,7 @@ describe('updateConversationsWithUuidLookup', () => { conversation2, ]), conversations: [conversation1, conversation2], - messaging: fakeMessaging, + server: fakeServer, }); assert.strictEqual(conversation1.get('uuid'), uuid1); @@ -219,12 +218,10 @@ describe('updateConversationsWithUuidLookup', () => { 'Test was not set up correctly' ); - fakeGetUuidsForE164s.resolves({ '+13215559876': null }); - await updateConversationsWithUuidLookup({ conversationController: new FakeConversationController([conversation]), conversations: [conversation], - messaging: fakeMessaging, + server: fakeServer, }); assert.approximately( @@ -245,13 +242,12 @@ describe('updateConversationsWithUuidLookup', () => { 'Test was not set up correctly' ); - fakeGetUuidsForE164s.resolves({ '+13215559876': null }); fakeCheckAccountExistence.resolves(true); await updateConversationsWithUuidLookup({ conversationController: new FakeConversationController([conversation]), conversations: [conversation], - messaging: fakeMessaging, + server: fakeServer, }); assert.strictEqual(conversation.get('uuid'), existingUuid); @@ -269,13 +265,12 @@ describe('updateConversationsWithUuidLookup', () => { 'Test was not set up correctly' ); - fakeGetUuidsForE164s.resolves({ '+13215559876': null }); fakeCheckAccountExistence.resolves(false); await updateConversationsWithUuidLookup({ conversationController: new FakeConversationController([conversation]), conversations: [conversation], - messaging: fakeMessaging, + server: fakeServer, }); assert.isUndefined(conversation.get('uuid')); diff --git a/ts/textsecure/OutgoingMessage.ts b/ts/textsecure/OutgoingMessage.ts index c50ae44d43..7761fa9510 100644 --- a/ts/textsecure/OutgoingMessage.ts +++ b/ts/textsecure/OutgoingMessage.ts @@ -671,9 +671,9 @@ export default class OutgoingMessage { if (isValidUuid(identifier)) { // We're good! } else if (isValidNumber(identifier)) { - if (!window.textsecure.messaging) { + if (!window.textsecure.server) { throw new Error( - 'sendToIdentifier: window.textsecure.messaging is not available!' + 'sendToIdentifier: window.textsecure.server is not available!' ); } @@ -683,7 +683,7 @@ export default class OutgoingMessage { conversations: [ window.ConversationController.getOrCreate(identifier, 'private'), ], - messaging: window.textsecure.messaging, + server: window.textsecure.server, }); const uuid = diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index e46dd6f071..37e9ea8f0b 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -5,7 +5,6 @@ /* eslint-disable max-classes-per-file */ import { z } from 'zod'; -import type { Dictionary } from 'lodash'; import Long from 'long'; import PQueue from 'p-queue'; import type { PlaintextContent } from '@signalapp/libsignal-client'; @@ -25,7 +24,7 @@ import { SenderKeys } from '../LibSignalStores'; import type { LinkPreviewType } from '../types/message/LinkPreviews'; import { MIMETypeToString } from '../types/MIME'; import type * as Attachment from '../types/Attachment'; -import type { UUID, UUIDStringType } from '../types/UUID'; +import type { UUID } from '../types/UUID'; import type { ChallengeType, GetGroupLogOptionsType, @@ -49,7 +48,6 @@ import type { SendLogCallbackType, } from './OutgoingMessage'; import OutgoingMessage from './OutgoingMessage'; -import type { CDSResponseType } from './cds/Types.d'; import * as Bytes from '../Bytes'; import { getRandomBytes, getZeroes, encryptAttachment } from '../Crypto'; import { @@ -2447,34 +2445,12 @@ export default class MessageSender { return this.server.getProfile(uuid.toString(), options); } - async checkAccountExistence(uuid: UUID): Promise { - return this.server.checkAccountExistence(uuid); - } - async getProfileForUsername( username: string ): ReturnType { return this.server.getProfileForUsername(username); } - async getUuidsForE164s( - numbers: ReadonlyArray - ): Promise> { - return this.server.getUuidsForE164s(numbers); - } - - async getUuidsForE164sV2( - e164s: ReadonlyArray, - acis: ReadonlyArray, - accessKeys: ReadonlyArray - ): Promise { - return this.server.getUuidsForE164sV2({ - e164s, - acis, - accessKeys, - }); - } - async getAvatar(path: string): Promise> { return this.server.getAvatar(path); } diff --git a/ts/textsecure/WebAPI.ts b/ts/textsecure/WebAPI.ts index 98e2b56dab..dfc2e5ccf9 100644 --- a/ts/textsecure/WebAPI.ts +++ b/ts/textsecure/WebAPI.ts @@ -11,7 +11,6 @@ import type { Response } from 'node-fetch'; import fetch from 'node-fetch'; import ProxyAgent from 'proxy-agent'; import { Agent } from 'https'; -import type { Dictionary } from 'lodash'; import { escapeRegExp, isNumber } from 'lodash'; import is from '@sindresorhus/is'; import PQueue from 'p-queue'; @@ -767,10 +766,10 @@ export type ConfirmCodeResultType = Readonly<{ deviceId?: number; }>; -export type GetUuidsForE164sV2OptionsType = Readonly<{ +export type CdsLookupOptionsType = Readonly<{ e164s: ReadonlyArray; - acis: ReadonlyArray; - accessKeys: ReadonlyArray; + acis?: ReadonlyArray; + accessKeys?: ReadonlyArray; }>; type GetProfileCommonOptionsType = Readonly< @@ -812,6 +811,7 @@ export type GetGroupCredentialsResultType = Readonly<{ export type WebAPIType = { startRegistration(): unknown; finishRegistration(baton: unknown): void; + cdsLookup: (options: CdsLookupOptionsType) => Promise; confirmCode: ( number: string, code: string, @@ -880,12 +880,6 @@ export type WebAPIType = { getStorageCredentials: MessageSender['getStorageCredentials']; getStorageManifest: MessageSender['getStorageManifest']; getStorageRecords: MessageSender['getStorageRecords']; - getUuidsForE164s: ( - e164s: ReadonlyArray - ) => Promise>; - getUuidsForE164sV2: ( - options: GetUuidsForE164sV2OptionsType - ) => Promise; fetchLinkPreviewMetadata: ( href: string, abortSignal: AbortSignal @@ -1251,6 +1245,7 @@ export function initialize({ unregisterRequestHandler, authenticate, logout, + cdsLookup, checkAccountExistence, confirmCode, createGroup, @@ -1285,8 +1280,6 @@ export function initialize({ getStorageCredentials, getStorageManifest, getStorageRecords, - getUuidsForE164s, - getUuidsForE164sV2, makeProxiedRequest, makeSfuRequest, modifyGroup, @@ -2858,25 +2851,11 @@ export function initialize({ return socketManager.getProvisioningResource(handler); } - async function getUuidsForE164s( - e164s: ReadonlyArray - ): Promise> { - const map = await cds.request({ - e164s, - }); - - const result: Dictionary = {}; - for (const [key, value] of map) { - result[key] = value.pni ?? value.aci ?? null; - } - return result; - } - - async function getUuidsForE164sV2({ + async function cdsLookup({ e164s, - acis, - accessKeys, - }: GetUuidsForE164sV2OptionsType): Promise { + acis = [], + accessKeys = [], + }: CdsLookupOptionsType): Promise { return cds.request({ e164s, acis, diff --git a/ts/textsecure/cds/CDSSocketBase.ts b/ts/textsecure/cds/CDSSocketBase.ts index a6ed7cdd1c..34a40f4915 100644 --- a/ts/textsecure/cds/CDSSocketBase.ts +++ b/ts/textsecure/cds/CDSSocketBase.ts @@ -85,28 +85,20 @@ export abstract class CDSSocketBase< const aciUakPairs = new Array(); - let version: 1 | 2; - if (acis) { - strictAssert(accessKeys, 'accessKeys are required when acis are present'); + const version = 2; + strictAssert( + acis.length === accessKeys.length, + `Number of ACIs ${acis.length} is different ` + + `from number of access keys ${accessKeys.length}` + ); - strictAssert( - acis.length === accessKeys.length, - `Number of ACIs ${acis.length} is different ` + - `from number of access keys ${accessKeys.length}` + for (let i = 0; i < acis.length; i += 1) { + aciUakPairs.push( + Bytes.concatenate([ + uuidToBytes(acis[i]), + Bytes.fromBase64(accessKeys[i]), + ]) ); - - version = 2; - - for (let i = 0; i < acis.length; i += 1) { - aciUakPairs.push( - Bytes.concatenate([ - uuidToBytes(acis[i]), - Bytes.fromBase64(accessKeys[i]), - ]) - ); - } - } else { - version = 1; } const request = Proto.CDSClientRequest.encode({ diff --git a/ts/textsecure/cds/LegacyCDS.ts b/ts/textsecure/cds/LegacyCDS.ts index 1adc2209c1..374126b60a 100644 --- a/ts/textsecure/cds/LegacyCDS.ts +++ b/ts/textsecure/cds/LegacyCDS.ts @@ -17,7 +17,6 @@ import { } from '../../Crypto'; import { calculateAgreement, generateKeyPair } from '../../Curve'; import * as Bytes from '../../Bytes'; -import { strictAssert } from '../../util/assert'; import { UUID } from '../../types/UUID'; import type { CDSBaseOptionsType } from './CDSBase'; import { CDSBase } from './CDSBase'; @@ -125,11 +124,7 @@ function getSgxConstants() { export class LegacyCDS extends CDSBase { public override async request({ e164s, - acis, - accessKeys, }: CDSRequestOptionsType): Promise { - strictAssert(!acis && !accessKeys, 'LegacyCDS does not support PNP'); - const directoryAuth = await this.getAuth(); const attestationResult = await this.putAttestation(directoryAuth); diff --git a/ts/textsecure/cds/Types.d.ts b/ts/textsecure/cds/Types.d.ts index 9e122ec8df..cbd3a99068 100644 --- a/ts/textsecure/cds/Types.d.ts +++ b/ts/textsecure/cds/Types.d.ts @@ -17,7 +17,7 @@ export type CDSResponseType = ReadonlyMap; export type CDSRequestOptionsType = Readonly<{ e164s: ReadonlyArray; - acis?: ReadonlyArray; - accessKeys?: ReadonlyArray; + acis: ReadonlyArray; + accessKeys: ReadonlyArray; timeout?: number; }>; diff --git a/ts/updateConversationsWithUuidLookup.ts b/ts/updateConversationsWithUuidLookup.ts index 56c6e34325..ed94334953 100644 --- a/ts/updateConversationsWithUuidLookup.ts +++ b/ts/updateConversationsWithUuidLookup.ts @@ -3,22 +3,22 @@ import type { ConversationController } from './ConversationController'; import type { ConversationModel } from './models/conversations'; -import type SendMessage from './textsecure/SendMessage'; +import type { WebAPIType } from './textsecure/WebAPI'; import { assert } from './util/assert'; -import { getOwn } from './util/getOwn'; import { isNotNil } from './util/isNotNil'; +import { getUuidsForE164s } from './util/getUuidsForE164s'; export async function updateConversationsWithUuidLookup({ conversationController, conversations, - messaging, + server, }: Readonly<{ conversationController: Pick< ConversationController, 'maybeMergeContacts' | 'get' >; conversations: ReadonlyArray; - messaging: Pick; + server: Pick; }>): Promise { const e164s = conversations .map(conversation => conversation.get('e164')) @@ -27,7 +27,7 @@ export async function updateConversationsWithUuidLookup({ return; } - const serverLookup = await messaging.getUuidsForE164s(e164s); + const serverLookup = await getUuidsForE164s(server, e164s); await Promise.all( conversations.map(async conversation => { @@ -38,11 +38,12 @@ export async function updateConversationsWithUuidLookup({ let finalConversation: ConversationModel; - const uuidFromServer = getOwn(serverLookup, e164); - if (uuidFromServer) { + const pairFromServer = serverLookup.get(e164); + if (pairFromServer) { const maybeFinalConversation = conversationController.maybeMergeContacts({ - aci: uuidFromServer, + aci: pairFromServer.aci, + pni: pairFromServer.pni, e164, reason: 'updateConversationsWithUuidLookup', }); @@ -59,10 +60,8 @@ export async function updateConversationsWithUuidLookup({ // they can't be looked up by a phone number. Check that uuid still exists, // and if not - drop it. let finalUuid = finalConversation.getUuid(); - if (!uuidFromServer && finalUuid) { - const doesAccountExist = await messaging.checkAccountExistence( - finalUuid - ); + if (!pairFromServer && finalUuid) { + const doesAccountExist = await server.checkAccountExistence(finalUuid); if (!doesAccountExist) { finalConversation.updateUuid(undefined); finalUuid = undefined; diff --git a/ts/util/getUuidsForE164s.ts b/ts/util/getUuidsForE164s.ts new file mode 100644 index 0000000000..adcc785b5c --- /dev/null +++ b/ts/util/getUuidsForE164s.ts @@ -0,0 +1,45 @@ +// Copyright 2022 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import type { CDSResponseType } from '../textsecure/cds/Types.d'; +import type { WebAPIType } from '../textsecure/WebAPI'; +import type { UUIDStringType } from '../types/UUID'; +import * as log from '../logging/log'; +import { isDirectConversation, isMe } from './whatTypeOfConversation'; + +export async function getUuidsForE164s( + server: Pick, + e164s: ReadonlyArray +): Promise { + // Note: these have no relationship to supplied e164s. We just provide + // all available information to the server so that it could return as many + // ACI+PNI+E164 matches as possible. + const acis = new Array(); + const accessKeys = new Array(); + + for (const convo of window.ConversationController.getAll()) { + if (!isDirectConversation(convo.attributes) || isMe(convo.attributes)) { + continue; + } + + const aci = convo.getUuid(); + if (!aci) { + continue; + } + + convo.deriveAccessKeyIfNeeded(); + const accessKey = convo.get('accessKey'); + if (!accessKey) { + continue; + } + + acis.push(aci.toString()); + accessKeys.push(accessKey); + } + + log.info( + `getUuidsForE164s(${e164s}): acis=${acis.length} ` + + `accessKeys=${accessKeys.length}` + ); + return server.cdsLookup({ e164s, acis, accessKeys }); +} diff --git a/ts/util/index.ts b/ts/util/index.ts index a89c73f387..a430a3eb17 100644 --- a/ts/util/index.ts +++ b/ts/util/index.ts @@ -12,6 +12,7 @@ import { downloadAttachment } from './downloadAttachment'; import { generateSecurityNumber } from './safetyNumber'; import { getStringForProfileChange } from './getStringForProfileChange'; import { getTextWithMentions } from './getTextWithMentions'; +import { getUuidsForE164s } from './getUuidsForE164s'; import { getUserAgent } from './getUserAgent'; import { hasExpired } from './hasExpired'; import { @@ -81,4 +82,5 @@ export { toWebSafeBase64, zkgroup, expirationTimer, + getUuidsForE164s, }; diff --git a/ts/util/lookupConversationWithoutUuid.ts b/ts/util/lookupConversationWithoutUuid.ts index 36af8d1e7f..de74e8c4ca 100644 --- a/ts/util/lookupConversationWithoutUuid.ts +++ b/ts/util/lookupConversationWithoutUuid.ts @@ -13,6 +13,7 @@ import { HTTPError } from '../textsecure/Errors'; import { showToast } from './showToast'; import { strictAssert } from './assert'; import type { UUIDFetchStateKeyType } from './uuidFetchState'; +import { getUuidsForE164s } from './getUuidsForE164s'; export type LookupConversationWithoutUuidActionsType = Readonly<{ lookupConversationWithoutUuid: typeof lookupConversationWithoutUuid; @@ -62,19 +63,22 @@ export async function lookupConversationWithoutUuid( const { showUserNotFoundModal, setIsFetchingUUID } = options; setIsFetchingUUID(identifier, true); - const { messaging } = window.textsecure; - if (!messaging) { - throw new Error('messaging is not available!'); + const { server } = window.textsecure; + if (!server) { + throw new Error('server is not available!'); } try { let conversationId: string | undefined; if (options.type === 'e164') { - const serverLookup = await messaging.getUuidsForE164s([options.e164]); + const serverLookup = await getUuidsForE164s(server, [options.e164]); - if (serverLookup[options.e164]) { + const maybePair = serverLookup.get(options.e164); + + if (maybePair) { const convo = window.ConversationController.maybeMergeContacts({ - aci: serverLookup[options.e164] || undefined, + aci: maybePair.aci, + pni: maybePair.pni, e164: options.e164, reason: 'startNewConversationWithoutUuid(e164)', });