Use combined username link API

This commit is contained in:
Fedor Indutny
2023-07-21 01:19:32 +02:00
committed by GitHub
parent 82e058f2b8
commit 13193649d3
5 changed files with 63 additions and 42 deletions

View File

@@ -183,16 +183,26 @@ export async function confirmUsername(
strictAssert(usernames.hash(username).equals(hash), 'username hash mismatch');
try {
await server.confirmUsername({
hash,
proof,
abortSignal,
const { entropy, encryptedUsername } =
usernames.createUsernameLink(username);
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);
// TODO: DESKTOP-5687
await resetLink(username);
} catch (error) {
if (error instanceof HTTPError) {
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');
}
const link = usernames.createUsernameLink(username);
const { entropy, encryptedUsername } = usernames.createUsernameLink(username);
await window.storage.remove('usernameLink');
const { usernameLinkHandle: serverIdString } =
await server.replaceUsernameLink({
encryptedUsername: link.encryptedUsername,
});
await server.replaceUsernameLink({ encryptedUsername });
await window.storage.put('usernameLink', {
entropy: link.entropy,
entropy,
serverId: uuidToBytes(serverIdString),
});
@@ -285,10 +293,8 @@ export async function resolveUsernameByLinkBase64(
serverId
);
const link = new usernames.UsernameLink(
Buffer.from(entropy),
Buffer.from(usernameLinkEncryptedValue)
);
return link.decryptUsername();
return usernames.decryptUsernameLink({
entropy: Buffer.from(entropy),
encryptedUsername: Buffer.from(usernameLinkEncryptedValue),
});
}

View File

@@ -222,18 +222,15 @@ describe('pnp/username', function needsName() {
const linkUuid = bufferToUuid(Buffer.from(usernameLink.serverId));
const encryptedLinkBase64 = await server.lookupByUsernameLink(linkUuid);
if (!encryptedLinkBase64) {
const encryptedLink = await server.lookupByUsernameLink(linkUuid);
if (!encryptedLink) {
throw new Error('Could not find link on the sever');
}
const encryptedLink = Buffer.from(encryptedLinkBase64, 'base64');
const link = new usernames.UsernameLink(
Buffer.from(usernameLink.entropy),
encryptedLink
);
const linkUsername = link.decryptUsername();
const linkUsername = usernames.decryptUsernameLink({
entropy: Buffer.from(usernameLink.entropy),
encryptedUsername: encryptedLink,
});
assert.strictEqual(linkUsername, username);
state = newState;

View File

@@ -831,6 +831,7 @@ export type ReplaceUsernameLinkOptionsType = Readonly<{
export type ConfirmUsernameOptionsType = Readonly<{
hash: Uint8Array;
proof: Uint8Array;
encryptedUsername: Uint8Array;
abortSignal?: AbortSignal;
}>;
@@ -843,6 +844,13 @@ export type ReserveUsernameResultType = z.infer<
typeof reserveUsernameResultZod
>;
const confirmUsernameResultZod = z.object({
usernameLinkHandle: z.string(),
});
export type ConfirmUsernameResultType = z.infer<
typeof confirmUsernameResultZod
>;
const replaceUsernameLinkResultZod = z.object({
usernameLinkHandle: z.string(),
});
@@ -851,7 +859,9 @@ export type ReplaceUsernameLinkResultType = z.infer<
>;
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<
typeof resolveUsernameLinkResultZod
@@ -1020,7 +1030,9 @@ export type WebAPIType = {
reserveUsername: (
options: ReserveUsernameOptionsType
) => Promise<ReserveUsernameResultType>;
confirmUsername(options: ConfirmUsernameOptionsType): Promise<void>;
confirmUsername(
options: ConfirmUsernameOptionsType
): Promise<ConfirmUsernameResultType>;
replaceUsernameLink: (
options: ReplaceUsernameLinkOptionsType
) => Promise<ReplaceUsernameLinkResultType>;
@@ -1916,17 +1928,21 @@ export function initialize({
async function confirmUsername({
hash,
proof,
encryptedUsername,
abortSignal,
}: ConfirmUsernameOptionsType) {
await _ajax({
const response = await _ajax({
call: 'confirmUsername',
httpType: 'PUT',
jsonData: {
usernameHash: toWebSafeBase64(Bytes.toBase64(hash)),
zkProof: toWebSafeBase64(Bytes.toBase64(proof)),
encryptedUsername: toWebSafeBase64(Bytes.toBase64(encryptedUsername)),
},
responseType: 'json',
abortSignal,
});
return confirmUsernameResultZod.parse(response);
}
async function replaceUsernameLink({
@@ -1938,7 +1954,9 @@ export function initialize({
httpType: 'PUT',
responseType: 'json',
jsonData: {
usernameLinkEncryptedValue: Bytes.toBase64(encryptedUsername),
usernameLinkEncryptedValue: toWebSafeBase64(
Bytes.toBase64(encryptedUsername)
),
},
})
);