This repository was archived by the owner on Sep 11, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 808
Set up key backup using non-deprecated APIs (2nd take) #12098
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
c263b17
Ensure backup settings in playwright
BillCarsonFr c0cef0b
Fix verification by pass causing backup reset
BillCarsonFr 1bc286c
fix force backup setup by default
BillCarsonFr 70091ad
fix test
BillCarsonFr 795e214
clarify when we need to bootstrap
BillCarsonFr d5a227c
jslint
BillCarsonFr befa0f9
Merge branch 'develop' into valere/fix_reset_backup_after_verif
BillCarsonFr 3a1305e
post merge fix
BillCarsonFr 8c087e0
post rebase missing files
BillCarsonFr 602d2b2
fix bad merge
BillCarsonFr 45c9f25
update test
BillCarsonFr 5e5d5ef
Fix import
BillCarsonFr 043f728
Merge branch 'develop' into valere/fix_reset_backup_after_verif
BillCarsonFr 08da26f
test user forgot passkey
BillCarsonFr 6fe0940
better usage of locator
BillCarsonFr a726c5d
fix snapshot
BillCarsonFr 9abb2d9
Merge branch 'develop' into valere/fix_reset_backup_after_verif
BillCarsonFr 71f00af
remove getDialogByTitle
BillCarsonFr 5114eb4
Update src/async-components/views/dialogs/security/CreateKeyBackupDia…
BillCarsonFr f1e89cc
unneeded permission
BillCarsonFr 9b2a902
Merge branch 'develop' into valere/fix_reset_backup_after_verif
BillCarsonFr 0b82647
code review
BillCarsonFr 2ae60bc
cleaning
BillCarsonFr 5c9494e
Merge branch 'develop' into valere/fix_reset_backup_after_verif
BillCarsonFr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| /* | ||
| Copyright 2023 The Matrix.org Foundation C.I.C. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| import { type Page } from "@playwright/test"; | ||
|
|
||
| import { test, expect } from "../../element-web-test"; | ||
|
|
||
| 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); | ||
| } | ||
|
|
||
| test.describe("Backups", () => { | ||
| test.use({ | ||
| displayName: "Hanako", | ||
| }); | ||
|
|
||
| test("Create, delete and recreate a keys backup", 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(); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| /* | ||
| Copyright 2023 The Matrix.org Foundation C.I.C. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| import { mocked } from "jest-mock"; | ||
| import { CryptoApi } from "matrix-js-sdk/src/crypto-api"; | ||
|
|
||
| import { accessSecretStorage } from "../src/SecurityManager"; | ||
| import { filterConsole, stubClient } from "./test-utils"; | ||
|
|
||
| describe("SecurityManager", () => { | ||
| describe("accessSecretStorage", () => { | ||
| filterConsole("Not setting dehydration key: no SSSS key found"); | ||
|
|
||
| it("runs the function passed in", async () => { | ||
| // Given a client | ||
| const crypto = { | ||
| bootstrapCrossSigning: () => {}, | ||
| bootstrapSecretStorage: () => {}, | ||
| } as unknown as CryptoApi; | ||
| const client = stubClient(); | ||
| mocked(client.hasSecretStorageKey).mockResolvedValue(true); | ||
| mocked(client.getCrypto).mockReturnValue(crypto); | ||
|
|
||
| // When I run accessSecretStorage | ||
| const func = jest.fn(); | ||
| await accessSecretStorage(func); | ||
|
|
||
| // Then we call the passed-in function | ||
| expect(func).toHaveBeenCalledTimes(1); | ||
| }); | ||
|
|
||
| describe("expecting errors", () => { | ||
| filterConsole("End-to-end encryption is disabled - unable to access secret storage"); | ||
|
|
||
| it("throws if crypto is unavailable", async () => { | ||
| // Given a client with no crypto | ||
| const client = stubClient(); | ||
| mocked(client.hasSecretStorageKey).mockResolvedValue(true); | ||
| mocked(client.getCrypto).mockReturnValue(undefined); | ||
|
|
||
| // When I run accessSecretStorage | ||
| // Then we throw an error | ||
| await expect(async () => { | ||
| await accessSecretStorage(jest.fn()); | ||
| }).rejects.toThrow("End-to-end encryption is disabled - unable to access secret storage"); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
test/components/views/dialogs/security/__snapshots__/CreateKeyBackupDialog-test.tsx.snap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest moving this (
const currentDialogLocator = page.locator(".mx_Dialog");) down to where it is used.