Skip to content

Commit

Permalink
Derhydration: enable dehydrated device on "Set up recovery"
Browse files Browse the repository at this point in the history
Clicking "Set up recovery" should set up a dehydrated device, if that feature
is enabled.

Fixes #29135
  • Loading branch information
richvdh committed Feb 14, 2025
1 parent 28454f4 commit 7bb64dd
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
27 changes: 27 additions & 0 deletions playwright/e2e/crypto/dehydration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,33 @@ test.describe("Dehydration", () => {
await expect(sessionsTab.getByText("Dehydrated device")).not.toBeVisible();
});

test("'Set up recovery' creates dehydrated device", async ({ app, credentials, page }) => {
await logIntoElement(page, credentials);

const settingsDialogLocator = await app.settings.openUserSettings("Encryption");
await settingsDialogLocator.getByRole("button", { name: "Set up recovery" }).click();

// First it displays an informative panel about the recovery key
await expect(settingsDialogLocator.getByRole("heading", { name: "Set up recovery" })).toBeVisible();
await settingsDialogLocator.getByRole("button", { name: "Continue" }).click();

// Next, it displays the new recovery key. We click on the copy button.
await expect(settingsDialogLocator.getByText("Save your recovery key somewhere safe")).toBeVisible();
await settingsDialogLocator.getByRole("button", { name: "Copy" }).click();
const recoveryKey = await app.getClipboard();
await settingsDialogLocator.getByRole("button", { name: "Continue" }).click();

await expect(
settingsDialogLocator.getByText("Enter your recovery key to confirm", { exact: true }),
).toBeVisible();
await settingsDialogLocator.getByRole("textbox").fill(recoveryKey);
await settingsDialogLocator.getByRole("button", { name: "Finish set up" }).click();

await app.settings.closeDialog();

await expectDehydratedDeviceEnabled(app);
});

test("Reset recovery key during login re-creates dehydrated device", async ({
page,
homeserver,
Expand Down
10 changes: 6 additions & 4 deletions src/components/views/settings/encryption/ChangeRecoveryKey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { EncryptionCard } from "./EncryptionCard";
import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext";
import { useAsyncMemo } from "../../../../hooks/useAsyncMemo";
import { copyPlaintext } from "../../../../utils/strings";
import { initialiseDehydrationIfEnabled } from "../../../../utils/device/dehydration.ts";
import { withSecretStorageKeyCache } from "../../../../SecurityManager";

/**
Expand Down Expand Up @@ -122,12 +123,13 @@ export function ChangeRecoveryKey({
try {
// We need to enable the cache to avoid to prompt the user to enter the new key
// when we will try to access the secret storage during the bootstrap
await withSecretStorageKeyCache(() =>
crypto.bootstrapSecretStorage({
await withSecretStorageKeyCache(async () => {
await crypto.bootstrapSecretStorage({
setupNewSecretStorage: true,
createSecretStorageKey: async () => recoveryKey,
}),
);
});
await initialiseDehydrationIfEnabled(matrixClient, { createNewKey: true });
});
onFinish();
} catch (e) {
logger.error("Failed to bootstrap secret storage", e);
Expand Down

0 comments on commit 7bb64dd

Please sign in to comment.