* show correct toast when cross-signing keys missing If cross-signing keys are missing both locally and in 4S, show a new toast saying that identity needs resetting, rather than saying that the device needs to be verified. * refactor: make DeviceListener in charge of device state - move enum from SetupEncryptionToast to DeviceListener - DeviceListener has public method to get device state - DeviceListener emits events to update device state * reset key backup when needed in RecoveryPanelOutOfSync brings RecoveryPanelOutOfSync in line with SetupEncryptionToast behaviour * update strings to agree with designs from Figma * use DeviceListener to determine EncryptionUserSettingsTab display rather than using its own logic * prompt to reset identity in Encryption Settings when needed * fix type * calculate device state even if we aren't going to show a toast * update snapshot * make logs more accurate * add tests * make the bot use a different access token/device * only log in a new session when requested * Mark properties as read-only Co-authored-by: Skye Elliot <actuallyori@gmail.com> * remove some duplicate strings * make accessToken optional instead of using empty string * switch from enum to string union as per review * apply other changes from review * handle errors in accessSecretStorage * remove incorrect testid --------- Co-authored-by: Skye Elliot <actuallyori@gmail.com>
94 lines
4.3 KiB
TypeScript
94 lines
4.3 KiB
TypeScript
/*
|
|
* Copyright 2024 New Vector Ltd.
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
* Please see LICENSE files in the repository root for full details.
|
|
*/
|
|
|
|
import { test, expect } from ".";
|
|
import { checkDeviceIsConnectedKeyBackup, createBot, verifySession } from "../../crypto/utils";
|
|
import type { GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
|
|
|
|
test.describe("Recovery section in Encryption tab", () => {
|
|
test.use({
|
|
displayName: "Alice",
|
|
});
|
|
|
|
let recoveryKey: GeneratedSecretStorageKey;
|
|
test.beforeEach(async ({ page, homeserver, credentials }) => {
|
|
// The bot bootstraps cross-signing, creates a key backup and sets up a recovery key
|
|
const botCredentials = { ...credentials };
|
|
delete botCredentials.accessToken; // use a new login for the bot
|
|
const res = await createBot(page, homeserver, botCredentials);
|
|
recoveryKey = res.recoveryKey;
|
|
});
|
|
|
|
test(
|
|
"should change the recovery key",
|
|
{ tag: ["@screenshot", "@no-webkit"] },
|
|
async ({ page, app, homeserver, credentials, util, context }) => {
|
|
await verifySession(app, recoveryKey.encodedPrivateKey);
|
|
const dialog = await util.openEncryptionTab();
|
|
|
|
// The user can only change the recovery key
|
|
const changeButton = dialog.getByRole("button", { name: "Change recovery key" });
|
|
await expect(changeButton).toBeVisible();
|
|
await expect(util.getEncryptionRecoverySection()).toMatchScreenshot("default-recovery.png");
|
|
await changeButton.click();
|
|
|
|
// Display the new recovery key and click on the copy button
|
|
await expect(dialog.getByText("Change recovery key?")).toBeVisible();
|
|
await expect(util.getEncryptionTabContent()).toMatchScreenshot("change-key-1-encryption-tab.png", {
|
|
mask: [dialog.getByTestId("recoveryKey")],
|
|
});
|
|
await dialog.getByRole("button", { name: "Copy" }).click();
|
|
await dialog.getByRole("button", { name: "Continue" }).click();
|
|
|
|
// Confirm the recovery key
|
|
await util.confirmRecoveryKey(
|
|
"Enter your new recovery key",
|
|
"Confirm new recovery key",
|
|
"change-key-2-encryption-tab.png",
|
|
);
|
|
},
|
|
);
|
|
|
|
test("should setup the recovery key", { tag: ["@screenshot", "@no-webkit"] }, async ({ page, app, util }) => {
|
|
await verifySession(app, recoveryKey.encodedPrivateKey);
|
|
await util.removeSecretStorageDefaultKeyId();
|
|
|
|
// The key backup is deleted and the user needs to set it up
|
|
const dialog = await util.openEncryptionTab();
|
|
const setupButton = dialog.getByRole("button", { name: "Set up recovery" });
|
|
await expect(setupButton).toBeVisible();
|
|
await expect(util.getEncryptionRecoverySection()).toMatchScreenshot("set-up-recovery.png");
|
|
await setupButton.click();
|
|
|
|
// Display an informative panel about the recovery key
|
|
await expect(dialog.getByRole("heading", { name: "Set up recovery" })).toBeVisible();
|
|
await expect(util.getEncryptionTabContent()).toMatchScreenshot("set-up-key-1-encryption-tab.png");
|
|
await dialog.getByRole("button", { name: "Continue" }).click();
|
|
|
|
// Display the new recovery key and click on the copy button
|
|
await expect(dialog.getByText("Save your recovery key somewhere safe")).toBeVisible();
|
|
await expect(util.getEncryptionTabContent()).toMatchScreenshot("set-up-key-2-encryption-tab.png", {
|
|
mask: [dialog.getByTestId("recoveryKey")],
|
|
});
|
|
await dialog.getByRole("button", { name: "Copy" }).click();
|
|
await dialog.getByRole("button", { name: "Continue" }).click();
|
|
|
|
// Confirm the recovery key
|
|
await util.confirmRecoveryKey(
|
|
"Enter your recovery key to confirm",
|
|
"Finish set up",
|
|
"set-up-key-3-encryption-tab.png",
|
|
);
|
|
|
|
// The recovery key is now set up and the user can change it
|
|
await expect(dialog.getByRole("button", { name: "Change recovery key" })).toBeVisible();
|
|
|
|
// Check that the current device is connected to key backup and the backup version is the expected one
|
|
await checkDeviceIsConnectedKeyBackup(app, "1", true);
|
|
});
|
|
});
|