Use combined username link API
This commit is contained in:
parent
82e058f2b8
commit
13193649d3
5 changed files with 63 additions and 42 deletions
|
@ -89,7 +89,7 @@
|
||||||
"@popperjs/core": "2.11.6",
|
"@popperjs/core": "2.11.6",
|
||||||
"@react-spring/web": "9.5.5",
|
"@react-spring/web": "9.5.5",
|
||||||
"@signalapp/better-sqlite3": "8.4.3",
|
"@signalapp/better-sqlite3": "8.4.3",
|
||||||
"@signalapp/libsignal-client": "0.28.0",
|
"@signalapp/libsignal-client": "0.29.0",
|
||||||
"@signalapp/ringrtc": "2.29.1",
|
"@signalapp/ringrtc": "2.29.1",
|
||||||
"@types/fabric": "4.5.3",
|
"@types/fabric": "4.5.3",
|
||||||
"backbone": "1.4.0",
|
"backbone": "1.4.0",
|
||||||
|
@ -190,7 +190,7 @@
|
||||||
"@electron/fuses": "1.5.0",
|
"@electron/fuses": "1.5.0",
|
||||||
"@formatjs/intl": "2.6.7",
|
"@formatjs/intl": "2.6.7",
|
||||||
"@mixer/parallel-prettier": "2.0.3",
|
"@mixer/parallel-prettier": "2.0.3",
|
||||||
"@signalapp/mock-server": "3.2.0",
|
"@signalapp/mock-server": "3.2.1",
|
||||||
"@storybook/addon-a11y": "6.5.6",
|
"@storybook/addon-a11y": "6.5.6",
|
||||||
"@storybook/addon-actions": "6.5.6",
|
"@storybook/addon-actions": "6.5.6",
|
||||||
"@storybook/addon-controls": "6.5.6",
|
"@storybook/addon-controls": "6.5.6",
|
||||||
|
|
|
@ -183,16 +183,26 @@ export async function confirmUsername(
|
||||||
strictAssert(usernames.hash(username).equals(hash), 'username hash mismatch');
|
strictAssert(usernames.hash(username).equals(hash), 'username hash mismatch');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await server.confirmUsername({
|
const { entropy, encryptedUsername } =
|
||||||
hash,
|
usernames.createUsernameLink(username);
|
||||||
proof,
|
|
||||||
abortSignal,
|
await window.storage.remove('usernameLink');
|
||||||
|
|
||||||
|
const { usernameLinkHandle: serverIdString } = await server.confirmUsername(
|
||||||
|
{
|
||||||
|
hash,
|
||||||
|
proof,
|
||||||
|
encryptedUsername,
|
||||||
|
abortSignal,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await window.storage.put('usernameLink', {
|
||||||
|
entropy,
|
||||||
|
serverId: uuidToBytes(serverIdString),
|
||||||
});
|
});
|
||||||
|
|
||||||
await updateUsernameAndSyncProfile(username);
|
await updateUsernameAndSyncProfile(username);
|
||||||
|
|
||||||
// TODO: DESKTOP-5687
|
|
||||||
await resetLink(username);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof HTTPError) {
|
if (error instanceof HTTPError) {
|
||||||
if (error.code === 413 || error.code === 429) {
|
if (error.code === 413 || error.code === 429) {
|
||||||
|
@ -245,17 +255,15 @@ export async function resetLink(username: string): Promise<void> {
|
||||||
throw new Error('Username has changed on another device');
|
throw new Error('Username has changed on another device');
|
||||||
}
|
}
|
||||||
|
|
||||||
const link = usernames.createUsernameLink(username);
|
const { entropy, encryptedUsername } = usernames.createUsernameLink(username);
|
||||||
|
|
||||||
await window.storage.remove('usernameLink');
|
await window.storage.remove('usernameLink');
|
||||||
|
|
||||||
const { usernameLinkHandle: serverIdString } =
|
const { usernameLinkHandle: serverIdString } =
|
||||||
await server.replaceUsernameLink({
|
await server.replaceUsernameLink({ encryptedUsername });
|
||||||
encryptedUsername: link.encryptedUsername,
|
|
||||||
});
|
|
||||||
|
|
||||||
await window.storage.put('usernameLink', {
|
await window.storage.put('usernameLink', {
|
||||||
entropy: link.entropy,
|
entropy,
|
||||||
serverId: uuidToBytes(serverIdString),
|
serverId: uuidToBytes(serverIdString),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -285,10 +293,8 @@ export async function resolveUsernameByLinkBase64(
|
||||||
serverId
|
serverId
|
||||||
);
|
);
|
||||||
|
|
||||||
const link = new usernames.UsernameLink(
|
return usernames.decryptUsernameLink({
|
||||||
Buffer.from(entropy),
|
entropy: Buffer.from(entropy),
|
||||||
Buffer.from(usernameLinkEncryptedValue)
|
encryptedUsername: Buffer.from(usernameLinkEncryptedValue),
|
||||||
);
|
});
|
||||||
|
|
||||||
return link.decryptUsername();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,18 +222,15 @@ describe('pnp/username', function needsName() {
|
||||||
|
|
||||||
const linkUuid = bufferToUuid(Buffer.from(usernameLink.serverId));
|
const linkUuid = bufferToUuid(Buffer.from(usernameLink.serverId));
|
||||||
|
|
||||||
const encryptedLinkBase64 = await server.lookupByUsernameLink(linkUuid);
|
const encryptedLink = await server.lookupByUsernameLink(linkUuid);
|
||||||
if (!encryptedLinkBase64) {
|
if (!encryptedLink) {
|
||||||
throw new Error('Could not find link on the sever');
|
throw new Error('Could not find link on the sever');
|
||||||
}
|
}
|
||||||
|
|
||||||
const encryptedLink = Buffer.from(encryptedLinkBase64, 'base64');
|
const linkUsername = usernames.decryptUsernameLink({
|
||||||
|
entropy: Buffer.from(usernameLink.entropy),
|
||||||
const link = new usernames.UsernameLink(
|
encryptedUsername: encryptedLink,
|
||||||
Buffer.from(usernameLink.entropy),
|
});
|
||||||
encryptedLink
|
|
||||||
);
|
|
||||||
const linkUsername = link.decryptUsername();
|
|
||||||
assert.strictEqual(linkUsername, username);
|
assert.strictEqual(linkUsername, username);
|
||||||
|
|
||||||
state = newState;
|
state = newState;
|
||||||
|
|
|
@ -831,6 +831,7 @@ export type ReplaceUsernameLinkOptionsType = Readonly<{
|
||||||
export type ConfirmUsernameOptionsType = Readonly<{
|
export type ConfirmUsernameOptionsType = Readonly<{
|
||||||
hash: Uint8Array;
|
hash: Uint8Array;
|
||||||
proof: Uint8Array;
|
proof: Uint8Array;
|
||||||
|
encryptedUsername: Uint8Array;
|
||||||
abortSignal?: AbortSignal;
|
abortSignal?: AbortSignal;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
@ -843,6 +844,13 @@ export type ReserveUsernameResultType = z.infer<
|
||||||
typeof reserveUsernameResultZod
|
typeof reserveUsernameResultZod
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
const confirmUsernameResultZod = z.object({
|
||||||
|
usernameLinkHandle: z.string(),
|
||||||
|
});
|
||||||
|
export type ConfirmUsernameResultType = z.infer<
|
||||||
|
typeof confirmUsernameResultZod
|
||||||
|
>;
|
||||||
|
|
||||||
const replaceUsernameLinkResultZod = z.object({
|
const replaceUsernameLinkResultZod = z.object({
|
||||||
usernameLinkHandle: z.string(),
|
usernameLinkHandle: z.string(),
|
||||||
});
|
});
|
||||||
|
@ -851,7 +859,9 @@ export type ReplaceUsernameLinkResultType = z.infer<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const resolveUsernameLinkResultZod = z.object({
|
const resolveUsernameLinkResultZod = z.object({
|
||||||
usernameLinkEncryptedValue: z.string().transform(x => Bytes.fromBase64(x)),
|
usernameLinkEncryptedValue: z
|
||||||
|
.string()
|
||||||
|
.transform(x => Bytes.fromBase64(fromWebSafeBase64(x))),
|
||||||
});
|
});
|
||||||
export type ResolveUsernameLinkResultType = z.infer<
|
export type ResolveUsernameLinkResultType = z.infer<
|
||||||
typeof resolveUsernameLinkResultZod
|
typeof resolveUsernameLinkResultZod
|
||||||
|
@ -1020,7 +1030,9 @@ export type WebAPIType = {
|
||||||
reserveUsername: (
|
reserveUsername: (
|
||||||
options: ReserveUsernameOptionsType
|
options: ReserveUsernameOptionsType
|
||||||
) => Promise<ReserveUsernameResultType>;
|
) => Promise<ReserveUsernameResultType>;
|
||||||
confirmUsername(options: ConfirmUsernameOptionsType): Promise<void>;
|
confirmUsername(
|
||||||
|
options: ConfirmUsernameOptionsType
|
||||||
|
): Promise<ConfirmUsernameResultType>;
|
||||||
replaceUsernameLink: (
|
replaceUsernameLink: (
|
||||||
options: ReplaceUsernameLinkOptionsType
|
options: ReplaceUsernameLinkOptionsType
|
||||||
) => Promise<ReplaceUsernameLinkResultType>;
|
) => Promise<ReplaceUsernameLinkResultType>;
|
||||||
|
@ -1916,17 +1928,21 @@ export function initialize({
|
||||||
async function confirmUsername({
|
async function confirmUsername({
|
||||||
hash,
|
hash,
|
||||||
proof,
|
proof,
|
||||||
|
encryptedUsername,
|
||||||
abortSignal,
|
abortSignal,
|
||||||
}: ConfirmUsernameOptionsType) {
|
}: ConfirmUsernameOptionsType) {
|
||||||
await _ajax({
|
const response = await _ajax({
|
||||||
call: 'confirmUsername',
|
call: 'confirmUsername',
|
||||||
httpType: 'PUT',
|
httpType: 'PUT',
|
||||||
jsonData: {
|
jsonData: {
|
||||||
usernameHash: toWebSafeBase64(Bytes.toBase64(hash)),
|
usernameHash: toWebSafeBase64(Bytes.toBase64(hash)),
|
||||||
zkProof: toWebSafeBase64(Bytes.toBase64(proof)),
|
zkProof: toWebSafeBase64(Bytes.toBase64(proof)),
|
||||||
|
encryptedUsername: toWebSafeBase64(Bytes.toBase64(encryptedUsername)),
|
||||||
},
|
},
|
||||||
|
responseType: 'json',
|
||||||
abortSignal,
|
abortSignal,
|
||||||
});
|
});
|
||||||
|
return confirmUsernameResultZod.parse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function replaceUsernameLink({
|
async function replaceUsernameLink({
|
||||||
|
@ -1938,7 +1954,9 @@ export function initialize({
|
||||||
httpType: 'PUT',
|
httpType: 'PUT',
|
||||||
responseType: 'json',
|
responseType: 'json',
|
||||||
jsonData: {
|
jsonData: {
|
||||||
usernameLinkEncryptedValue: Bytes.toBase64(encryptedUsername),
|
usernameLinkEncryptedValue: toWebSafeBase64(
|
||||||
|
Bytes.toBase64(encryptedUsername)
|
||||||
|
),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
18
yarn.lock
18
yarn.lock
|
@ -2276,20 +2276,20 @@
|
||||||
bindings "^1.5.0"
|
bindings "^1.5.0"
|
||||||
tar "^6.1.0"
|
tar "^6.1.0"
|
||||||
|
|
||||||
"@signalapp/libsignal-client@0.28.0", "@signalapp/libsignal-client@^0.28.0":
|
"@signalapp/libsignal-client@0.29.0", "@signalapp/libsignal-client@^0.29.0":
|
||||||
version "0.28.0"
|
version "0.29.0"
|
||||||
resolved "https://registry.yarnpkg.com/@signalapp/libsignal-client/-/libsignal-client-0.28.0.tgz#b1553a4b56fc01afe5e9b2785abd5c680f46ebc4"
|
resolved "https://registry.yarnpkg.com/@signalapp/libsignal-client/-/libsignal-client-0.29.0.tgz#36c467645551e023924371f2d894085dfbd3e59c"
|
||||||
integrity sha512-Vl3vt9hBdPW2/cwuf8+ZMwxmlAlnuBSgsKebRPfDOboLWDRlQRq+tstlwfBFU0e/2ixgY95Wulu46I1cl6H40g==
|
integrity sha512-p+FoCV0wORPoZNixyib/kxPL1+7OdNNjAxCKbiuN+1zx948YDZxVrttJv1FylPrLiTUpF+AloZr88elnUq4ZJA==
|
||||||
dependencies:
|
dependencies:
|
||||||
node-gyp-build "^4.2.3"
|
node-gyp-build "^4.2.3"
|
||||||
uuid "^8.3.0"
|
uuid "^8.3.0"
|
||||||
|
|
||||||
"@signalapp/mock-server@3.2.0":
|
"@signalapp/mock-server@3.2.1":
|
||||||
version "3.2.0"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-3.2.0.tgz#9371dc2002a1a8aa25ac815944a443cdc0a1b7c5"
|
resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-3.2.1.tgz#36fd3e72b44dbcb6c82fdb27bbf56f8393e8f065"
|
||||||
integrity sha512-4rpAAH5tV8eoIikb6FozMmrCKr+pqaP9JNyfZQ5YLPanAiTE9iER7WJex0HJ9PhscgswbzWIPFuRyhm/qPocVQ==
|
integrity sha512-irT4U3e8Lve9HODGIlXx+vElONaPNe7Ks9QRoSPSR4o0DbUX/g+zUxfEu7gjEi0CQI8OKxcJHe7e5DbE8mvXng==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@signalapp/libsignal-client" "^0.28.0"
|
"@signalapp/libsignal-client" "^0.29.0"
|
||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
long "^4.0.0"
|
long "^4.0.0"
|
||||||
micro "^9.3.4"
|
micro "^9.3.4"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue