mirror of
https://github.com/vector-im/element-web.git
synced 2025-09-01 20:01:19 +02:00
Dehydration: enable dehydrated device on "Set up recovery" (#29265)
* playwright/dehydration: update check The old "Security & Privacy" tab is going away, so we need a new way to check for dehydrated device existence. * Dehydration: enable dehydrated device on "Set up recovery" Clicking "Set up recovery" should set up a dehydrated device, if that feature is enabled. Fixes #29135 * Empty commit ... to wake up the CLA bot
This commit is contained in:
parent
09db599fe0
commit
f822653d65
@ -10,6 +10,7 @@ import { test, expect } from "../../element-web-test";
|
||||
import { isDendrite } from "../../plugins/homeserver/dendrite";
|
||||
import { completeCreateSecretStorageDialog, createBot, logIntoElement } from "./utils.ts";
|
||||
import { type Client } from "../../pages/client.ts";
|
||||
import { type ElementAppPage } from "../../pages/ElementAppPage.ts";
|
||||
|
||||
const NAME = "Alice";
|
||||
|
||||
@ -49,13 +50,7 @@ test.describe("Dehydration", () => {
|
||||
|
||||
await completeCreateSecretStorageDialog(page);
|
||||
|
||||
// Open the settings again
|
||||
await app.settings.openUserSettings("Security & Privacy");
|
||||
|
||||
// The Security tab should indicate that there is a dehydrated device present
|
||||
await expect(securityTab.getByText("Offline device enabled")).toBeVisible();
|
||||
|
||||
await app.settings.closeDialog();
|
||||
await expectDehydratedDeviceEnabled(app);
|
||||
|
||||
// the dehydrated device gets created with the name "Dehydrated
|
||||
// device". We want to make sure that it is not visible as a normal
|
||||
@ -64,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,
|
||||
@ -109,3 +131,16 @@ async function getDehydratedDeviceIds(client: Client): Promise<string[]> {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/** Wait for our user to have a dehydrated device */
|
||||
async function expectDehydratedDeviceEnabled(app: ElementAppPage): Promise<void> {
|
||||
// It might be nice to do this via the UI, but currently this info is not exposed via the UI.
|
||||
//
|
||||
// Note we might have to wait for the device list to be refreshed, so we wrap in `expect.poll`.
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const dehydratedDeviceIds = await getDehydratedDeviceIds(app.client);
|
||||
return dehydratedDeviceIds.length;
|
||||
})
|
||||
.toEqual(1);
|
||||
}
|
||||
|
@ -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";
|
||||
|
||||
/**
|
||||
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user