145 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
/*
 | 
						|
Copyright 2024 New Vector Ltd.
 | 
						|
Copyright 2023 The Matrix.org Foundation C.I.C.
 | 
						|
 | 
						|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
 | 
						|
Please see LICENSE files in the repository root for full details.
 | 
						|
*/
 | 
						|
 | 
						|
import { type Page } from "@playwright/test";
 | 
						|
 | 
						|
import { test, expect } from "../../element-web-test";
 | 
						|
import { test as masTest, registerAccountMas } from "../oidc";
 | 
						|
import { isDendrite } from "../../plugins/homeserver/dendrite";
 | 
						|
 | 
						|
async function expectBackupVersionToBe(page: Page, version: string) {
 | 
						|
    await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(5) td")).toHaveText(
 | 
						|
        version + " (Algorithm: m.megolm_backup.v1.curve25519-aes-sha2)",
 | 
						|
    );
 | 
						|
 | 
						|
    await expect(page.locator(".mx_SecureBackupPanel_statusList tr:nth-child(6) td")).toHaveText(version);
 | 
						|
}
 | 
						|
 | 
						|
masTest.describe("Encryption state after registration", () => {
 | 
						|
    masTest.skip(isDendrite, "does not yet support MAS");
 | 
						|
 | 
						|
    masTest("Key backup is enabled by default", async ({ page, mailhog, app }) => {
 | 
						|
        await page.goto("/#/login");
 | 
						|
        await page.getByRole("button", { name: "Continue" }).click();
 | 
						|
        await registerAccountMas(page, mailhog.api, "alice", "alice@email.com", "Pa$sW0rD!");
 | 
						|
 | 
						|
        await app.settings.openUserSettings("Security & Privacy");
 | 
						|
        expect(page.getByText("This session is backing up your keys.")).toBeVisible();
 | 
						|
    });
 | 
						|
 | 
						|
    masTest("user is prompted to set up recovery", async ({ page, mailhog, app }) => {
 | 
						|
        await page.goto("/#/login");
 | 
						|
        await page.getByRole("button", { name: "Continue" }).click();
 | 
						|
        await registerAccountMas(page, mailhog.api, "alice", "alice@email.com", "Pa$sW0rD!");
 | 
						|
 | 
						|
        await page.getByRole("button", { name: "Add room" }).click();
 | 
						|
        await page.getByRole("menuitem", { name: "New room" }).click();
 | 
						|
        await page.getByRole("textbox", { name: "Name" }).fill("test room");
 | 
						|
        await page.getByRole("button", { name: "Create room" }).click();
 | 
						|
 | 
						|
        await expect(page.getByRole("heading", { name: "Set up recovery" })).toBeVisible();
 | 
						|
    });
 | 
						|
});
 | 
						|
 | 
						|
test.describe("Backups", () => {
 | 
						|
    test.use({
 | 
						|
        displayName: "Hanako",
 | 
						|
    });
 | 
						|
 | 
						|
    test(
 | 
						|
        "Create, delete and recreate a keys backup",
 | 
						|
        { tag: "@no-webkit" },
 | 
						|
        async ({ page, user, app }, workerInfo) => {
 | 
						|
            // Create a backup
 | 
						|
            const securityTab = await app.settings.openUserSettings("Security & Privacy");
 | 
						|
 | 
						|
            await expect(securityTab.getByRole("heading", { name: "Secure Backup" })).toBeVisible();
 | 
						|
            await securityTab.getByRole("button", { name: "Set up", exact: true }).click();
 | 
						|
 | 
						|
            const currentDialogLocator = page.locator(".mx_Dialog");
 | 
						|
 | 
						|
            // It's the first time and secure storage is not set up, so it will create one
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Set up Secure Backup" })).toBeVisible();
 | 
						|
            await currentDialogLocator.getByRole("button", { name: "Continue", exact: true }).click();
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Save your Security Key" })).toBeVisible();
 | 
						|
            await currentDialogLocator.getByRole("button", { name: "Copy", exact: true }).click();
 | 
						|
            // copy the recovery key to use it later
 | 
						|
            const securityKey = await app.getClipboard();
 | 
						|
            await currentDialogLocator.getByRole("button", { name: "Continue", exact: true }).click();
 | 
						|
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Secure Backup successful" })).toBeVisible();
 | 
						|
            await currentDialogLocator.getByRole("button", { name: "Done", exact: true }).click();
 | 
						|
 | 
						|
            // Open the settings again
 | 
						|
            await app.settings.openUserSettings("Security & Privacy");
 | 
						|
            await expect(securityTab.getByRole("heading", { name: "Secure Backup" })).toBeVisible();
 | 
						|
 | 
						|
            // expand the advanced section to see the active version in the reports
 | 
						|
            await page
 | 
						|
                .locator(".mx_Dialog .mx_SettingsSubsection_content details .mx_SecureBackupPanel_advanced")
 | 
						|
                .locator("..")
 | 
						|
                .click();
 | 
						|
 | 
						|
            await expectBackupVersionToBe(page, "1");
 | 
						|
 | 
						|
            await securityTab.getByRole("button", { name: "Delete Backup", exact: true }).click();
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Delete Backup" })).toBeVisible();
 | 
						|
            // Delete it
 | 
						|
            await currentDialogLocator.getByTestId("dialog-primary-button").click(); // Click "Delete Backup"
 | 
						|
 | 
						|
            // Create another
 | 
						|
            await securityTab.getByRole("button", { name: "Set up", exact: true }).click();
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Security Key" })).toBeVisible();
 | 
						|
            await currentDialogLocator.getByLabel("Security Key").fill(securityKey);
 | 
						|
            await currentDialogLocator.getByRole("button", { name: "Continue", exact: true }).click();
 | 
						|
 | 
						|
            // Should be successful
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Success!" })).toBeVisible();
 | 
						|
            await currentDialogLocator.getByRole("button", { name: "OK", exact: true }).click();
 | 
						|
 | 
						|
            // Open the settings again
 | 
						|
            await app.settings.openUserSettings("Security & Privacy");
 | 
						|
            await expect(securityTab.getByRole("heading", { name: "Secure Backup" })).toBeVisible();
 | 
						|
 | 
						|
            // expand the advanced section to see the active version in the reports
 | 
						|
            await page
 | 
						|
                .locator(".mx_Dialog .mx_SettingsSubsection_content details .mx_SecureBackupPanel_advanced")
 | 
						|
                .locator("..")
 | 
						|
                .click();
 | 
						|
 | 
						|
            await expectBackupVersionToBe(page, "2");
 | 
						|
 | 
						|
            // ==
 | 
						|
            // Ensure that if you don't have the secret storage passphrase the backup won't be created
 | 
						|
            // ==
 | 
						|
 | 
						|
            // First delete version 2
 | 
						|
            await securityTab.getByRole("button", { name: "Delete Backup", exact: true }).click();
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Delete Backup" })).toBeVisible();
 | 
						|
            // Click "Delete Backup"
 | 
						|
            await currentDialogLocator.getByTestId("dialog-primary-button").click();
 | 
						|
 | 
						|
            // Try to create another
 | 
						|
            await securityTab.getByRole("button", { name: "Set up", exact: true }).click();
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Security Key" })).toBeVisible();
 | 
						|
            // But cancel the security key dialog, to simulate not having the secret storage passphrase
 | 
						|
            await currentDialogLocator.getByTestId("dialog-cancel-button").click();
 | 
						|
 | 
						|
            await expect(currentDialogLocator.getByRole("heading", { name: "Starting backup…" })).toBeVisible();
 | 
						|
            // check that it failed
 | 
						|
            await expect(currentDialogLocator.getByText("Unable to create key backup")).toBeVisible();
 | 
						|
            // cancel
 | 
						|
            await currentDialogLocator.getByTestId("dialog-cancel-button").click();
 | 
						|
 | 
						|
            // go back to the settings to check that no backup was created (the setup button should still be there)
 | 
						|
            await app.settings.openUserSettings("Security & Privacy");
 | 
						|
            await expect(securityTab.getByRole("button", { name: "Set up", exact: true })).toBeVisible();
 | 
						|
        },
 | 
						|
    );
 | 
						|
});
 |