From 8030284a40de17257d5cfadb7d6d1755f84560ce Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Tue, 6 Jan 2026 07:00:18 +1000 Subject: [PATCH] resolveUsernameByLink: Move to libsignal typed API --- ts/services/username.preload.ts | 31 ++++++++++++---------------- ts/textsecure/WebAPI.preload.ts | 36 ++++++++++++++------------------- 2 files changed, 28 insertions(+), 39 deletions(-) diff --git a/ts/services/username.preload.ts b/ts/services/username.preload.ts index 1f97419347..8fc7aa030b 100644 --- a/ts/services/username.preload.ts +++ b/ts/services/username.preload.ts @@ -30,6 +30,7 @@ import { deleteUsername as doDeleteUsername, resolveUsernameLink, } from '../textsecure/WebAPI.preload.js'; +import type { ResolveUsernameByLinkOptionsType } from '../textsecure/WebAPI.preload.js'; import { HTTPError } from '../types/HTTPError.std.js'; import { findRetryAfterTimeFromError } from '../jobs/helpers/findRetryAfterTimeFromError.std.js'; import * as Bytes from '../Bytes.std.js'; @@ -364,28 +365,22 @@ export async function resolveUsernameByLinkBase64( const entropy = content.subarray(0, USERNAME_LINK_ENTROPY_SIZE); const serverId = content.subarray(USERNAME_LINK_ENTROPY_SIZE); - return resolveUsernameByLink({ entropy, serverId }); + const uuid = bytesToUuid(serverId); + strictAssert(uuid, 'Failed to re-encode server id as uuid'); + + return resolveUsernameByLink({ entropy, uuid }); } -export type ResolveUsernameByLinkOptionsType = Readonly<{ - entropy: Uint8Array; - serverId: Uint8Array; -}>; - -export async function resolveUsernameByLink({ - entropy, - serverId: serverIdBytes, -}: ResolveUsernameByLinkOptionsType): Promise { - const serverId = bytesToUuid(serverIdBytes); - strictAssert(serverId, 'Failed to re-encode server id as uuid'); - +export async function resolveUsernameByLink( + options: ResolveUsernameByLinkOptionsType +): Promise { try { - const { usernameLinkEncryptedValue } = await resolveUsernameLink(serverId); + const result = await resolveUsernameLink(options); + if (!result) { + return undefined; + } - return usernames.decryptUsernameLink({ - entropy, - encryptedUsername: usernameLinkEncryptedValue, - }); + return result.username; } catch (error) { if (error instanceof HTTPError && error.code === 404) { return undefined; diff --git a/ts/textsecure/WebAPI.preload.ts b/ts/textsecure/WebAPI.preload.ts index 93befbf7aa..7cf6fce973 100644 --- a/ts/textsecure/WebAPI.preload.ts +++ b/ts/textsecure/WebAPI.preload.ts @@ -1061,14 +1061,14 @@ export type ReplaceUsernameLinkResultType = z.infer< typeof replaceUsernameLinkResultZod >; -const resolveUsernameLinkResultZod = z.object({ - usernameLinkEncryptedValue: z - .string() - .transform(x => Bytes.fromBase64(fromWebSafeBase64(x))), -}); -export type ResolveUsernameLinkResultType = z.infer< - typeof resolveUsernameLinkResultZod ->; +export type ResolveUsernameByLinkOptionsType = Readonly<{ + entropy: Uint8Array; + uuid: string; +}>; +export type ResolveUsernameLinkResultType = { + username: string; + hash: Uint8Array; +} | null; export type CreateAccountOptionsType = Readonly<{ sessionId: string; @@ -2659,19 +2659,13 @@ export async function deleteUsernameLink(): Promise { }); } -export async function resolveUsernameLink( - serverId: string -): Promise { - return _ajax({ - host: 'chatService', - httpType: 'GET', - call: 'usernameLink', - urlParameters: `/${encodeURIComponent(serverId)}`, - responseType: 'json', - unauthenticated: true, - accessKey: undefined, - groupSendToken: undefined, - zodSchema: resolveUsernameLinkResultZod, +export async function resolveUsernameLink({ + entropy, + uuid, +}: ResolveUsernameByLinkOptionsType): Promise { + return _retry(async () => { + const chat = await socketManager.getUnauthenticatedLibsignalApi(); + return chat.lookUpUsernameLink({ uuid, entropy }); }); }