Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions playwright/e2e/crypto/dehydration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ test.describe("Dehydration", () => {
// Reset the identity key
const settings = await app.settings.openUserSettings("Encryption");
await settings.getByRole("button", { name: "Verify this device" }).click();
await page.getByRole("button", { name: "Proceed with reset" }).click();
await page.getByRole("button", { name: "Can't confirm?" }).click();
await page.getByRole("button", { name: "Continue" }).click();

// Set up recovery
Expand Down Expand Up @@ -106,7 +106,7 @@ test.describe("Dehydration", () => {
await logIntoElement(page, credentials);

// Oh no, we forgot our recovery key - reset our identity
await page.locator(".mx_AuthPage").getByRole("button", { name: "Reset all" }).click();
await page.locator(".mx_AuthPage").getByRole("button", { name: "Can't confirm" }).click();
await expect(
page.getByRole("heading", { name: "Are you sure you want to reset your identity?" }),
).toBeVisible();
Expand Down
8 changes: 4 additions & 4 deletions playwright/e2e/crypto/device-verification.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {
expectedBackupVersion = res.expectedBackupVersion;
});

// Click the "Verify with another device" button, and have the bot client auto-accept it.
// Click the "Use another device" button, and have the bot client auto-accept it.
async function initiateAliceVerificationRequest(page: Page): Promise<JSHandle<VerificationRequest>> {
// alice bot waits for verification request
const promiseVerificationRequest = waitForVerificationRequest(aliceBotClient);

// Click on "Verify with another device"
await page.locator(".mx_AuthPage").getByRole("button", { name: "Verify with another device" }).click();
// Click on "Use another device"
await page.locator(".mx_AuthPage").getByRole("button", { name: "Use another device" }).click();

// alice bot responds yes to verification request from alice
return promiseVerificationRequest;
Expand Down Expand Up @@ -203,7 +203,7 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {

/** Helper for the three tests above which verify by recovery key */
async function enterRecoveryKeyAndCheckVerified(page: Page, app: ElementAppPage, recoveryKey: string) {
await page.getByRole("button", { name: "Verify with Recovery Key or Phrase" }).click();
await page.getByRole("button", { name: "Use recovery key" }).click();

// Enter the recovery key
const dialog = page.locator(".mx_Dialog");
Expand Down
6 changes: 3 additions & 3 deletions playwright/e2e/crypto/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ export async function logIntoElement(page: Page, credentials: Credentials) {
export async function logIntoElementAndVerify(page: Page, credentials: Credentials, recoveryKey: string) {
await logIntoElement(page, credentials);

await page.locator(".mx_AuthPage").getByRole("button", { name: "Verify with Recovery Key" }).click();
await page.locator(".mx_AuthPage").getByRole("button", { name: "Use recovery key" }).click();

const useSecurityKey = page.locator(".mx_Dialog").getByRole("button", { name: "use your Recovery Key" });
const useSecurityKey = page.locator(".mx_Dialog").getByRole("button", { name: "Use recovery key" });
// If the user has set a recovery *passphrase*, they'll be prompted for that first and have to click
// through to enter the recovery key which is what we have here. If they haven't, they'll be prompted
// for a recovery key straight away. We click the button if it's there so this works in both cases.
Expand Down Expand Up @@ -272,7 +272,7 @@ export async function logOutOfElement(page: Page, discardKeys: boolean = false)
export async function verifySession(app: ElementAppPage, securityKey: string) {
const settings = await app.settings.openUserSettings("Encryption");
await settings.getByRole("button", { name: "Verify this device" }).click();
await app.page.getByRole("button", { name: "Verify with Recovery Key" }).click();
await app.page.getByRole("button", { name: "Use recovery key" }).click();
await app.page.locator(".mx_Dialog").getByTitle("Recovery key").fill(securityKey);
await app.page.getByRole("button", { name: "Continue", disabled: false }).click();
await app.page.getByRole("button", { name: "Done" }).click();
Expand Down
30 changes: 15 additions & 15 deletions playwright/e2e/login/login-consent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ test.describe("Login", () => {
await page.goto("/");
await login(page, homeserver, credentials);

await expect(page.getByRole("heading", { name: "Verify this device", level: 1 })).toBeVisible();
await expect(page.getByRole("heading", { name: "Confirm your identity", level: 2 })).toBeVisible();

await expect(page.getByRole("button", { name: "Skip verification for now" })).toBeVisible();
});
Expand Down Expand Up @@ -219,7 +219,7 @@ test.describe("Login", () => {
await page.goto("/");
await login(page, homeserver, credentials);

await expect(page.getByRole("heading", { name: "Verify this device", level: 1 })).toBeVisible();
await expect(page.getByRole("heading", { name: "Confirm your identity", level: 2 })).toBeVisible();

await expect(page.getByRole("button", { name: "Skip verification for now" })).toBeVisible();
});
Expand Down Expand Up @@ -254,10 +254,10 @@ test.describe("Login", () => {
await page.goto("/");
await login(page, homeserver, credentials);

const h1 = page.getByRole("heading", { name: "Verify this device", level: 1 });
await expect(h1).toBeVisible();
const h2 = page.getByRole("heading", { name: "Confirm your identity", level: 2 });
await expect(h2).toBeVisible();

await expect(h1.locator(".mx_CompleteSecurity_skip")).toHaveCount(0);
await expect(h2.locator(".mx_CompleteSecurity_skip")).toHaveCount(0);
});

test("Continues to show verification prompt after cancelling device verification", async ({
Expand All @@ -274,18 +274,18 @@ test.describe("Login", () => {
// Load the page and see that we are asked to verify
await page.goto("/#/welcome");
await login(page, homeserver, credentials);
let h1 = page.getByRole("heading", { name: "Verify this device", level: 1 });
await expect(h1).toBeVisible();
let h2 = page.getByRole("heading", { name: "Confirm your identity", level: 2 });
await expect(h2).toBeVisible();

// Click "Verify with another device"
await page.getByRole("button", { name: "Verify with another device" }).click();
// Click "Use another device"
await page.getByRole("button", { name: "Use another device" }).click();

// Cancel the new dialog
await page.getByRole("button", { name: "Close dialog" }).click();

// Check that we are still being asked to verify
h1 = page.getByRole("heading", { name: "Verify this device", level: 1 });
await expect(h1).toBeVisible();
h2 = page.getByRole("heading", { name: "Confirm your identity", level: 2 });
await expect(h2).toBeVisible();
});
});

Expand All @@ -303,18 +303,18 @@ test.describe("Login", () => {
await page.goto("/");
await login(page, homeserver, credentials);

await expect(page.getByRole("heading", { name: "Verify this device", level: 1 })).toBeVisible();
await expect(page.getByRole("heading", { name: "Confirm your identity", level: 2 })).toBeVisible();

// Start the reset process
await page.getByRole("button", { name: "Proceed with reset" }).click();
await page.getByRole("button", { name: "Can't confirm?" }).click();

// First try cancelling and restarting
await page.getByRole("button", { name: "Cancel" }).click();
await page.getByRole("button", { name: "Proceed with reset" }).click();
await page.getByRole("button", { name: "Can't confirm?" }).click();

// Then click outside the dialog and restart
await page.getByRole("link", { name: "Powered by Matrix" }).click({ force: true });
await page.getByRole("button", { name: "Proceed with reset" }).click();
await page.getByRole("button", { name: "Can't confirm?" }).click();

// Finally we actually continue
await page.getByRole("button", { name: "Continue" }).click();
Expand Down
10 changes: 5 additions & 5 deletions playwright/e2e/oidc/oidc-native.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
await page.getByRole("button", { name: "Continue" }).click();
await page.getByRole("button", { name: "Continue" }).click();

// We should be in (we see an error because we have no recovery key).
await expect(page.getByText("Unable to verify this device")).toBeVisible();
// We should be in
await expect(page.getByText("Confirm your identity")).toBeVisible();
});

test.describe("with force_verification on", () => {
Expand Down Expand Up @@ -162,7 +162,7 @@ test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
await page.getByRole("button", { name: "Continue" }).click();

// We should be being warned that we need to verify (but we can't)
await expect(page.getByText("Unable to verify this device")).toBeVisible();
await expect(page.getByText("Confirm your identity")).toBeVisible();

// And there should be no way to close this prompt
await expect(page.getByRole("button", { name: "Skip verification for now" })).not.toBeVisible();
Expand Down Expand Up @@ -210,7 +210,7 @@ test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
await expect(page.getByRole("button", { name: "Skip verification for now" })).not.toBeVisible();

// When we start verifying with another device
await page.getByRole("button", { name: "Verify with another device" }).click();
await page.getByRole("button", { name: "Use another device" }).click();

// And then cancel it
await page.getByRole("button", { name: "Close dialog" }).click();
Expand All @@ -227,7 +227,7 @@ test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
* Perform interactive emoji verification for a new device.
*/
async function verifyUsingOtherDevice(deviceToVerifyPage: Page, alreadyVerifiedDevicePage: Page) {
await deviceToVerifyPage.getByRole("button", { name: "Verify with another device" }).click();
await deviceToVerifyPage.getByRole("button", { name: "Use another device" }).click();
await alreadyVerifiedDevicePage.getByRole("button", { name: "Verify session" }).click();
await alreadyVerifiedDevicePage.getByRole("button", { name: "Start" }).click();
await alreadyVerifiedDevicePage.getByRole("button", { name: "They match" }).click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,15 @@ test.describe("Encryption tab", () => {

// We will reset our identity
await settings.getByRole("button", { name: "Verify this device" }).click();
await page.getByRole("button", { name: "Proceed with reset" }).click();
await page.getByRole("button", { name: "Can't confirm?" }).click();

// First try cancelling and restarting
await page.getByRole("button", { name: "Cancel" }).click();
await page.getByRole("button", { name: "Proceed with reset" }).click();
await page.getByRole("button", { name: "Can't confirm?" }).click();

// Then click outside the dialog and restart
await page.locator("li").filter({ hasText: "Encryption" }).click({ force: true });
await page.getByRole("button", { name: "Proceed with reset" }).click();
await page.getByRole("button", { name: "Can't confirm?" }).click();

// Finally we actually continue
await page.getByRole("button", { name: "Continue" }).click();
Expand Down
2 changes: 1 addition & 1 deletion playwright/e2e/settings/encryption-user-tab/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Helpers {
*/
async verifyDevice(recoveryKey: GeneratedSecretStorageKey) {
// Select the security phrase
await this.page.getByRole("button", { name: "Verify with Recovery Key" }).click();
await this.page.getByRole("button", { name: "Use recovery key" }).click();
await this.enterRecoveryKey(recoveryKey);
await this.page.getByRole("button", { name: "Done" }).click();
}
Expand Down
11 changes: 2 additions & 9 deletions res/css/structures/auth/_SetupEncryptionBody.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/

.mx_SetupEncryptionBody_reset {
color: $light-fg-color;
margin-top: $font-14px;

.mx_SetupEncryptionBody_reset_link {
&.mx_AccessibleButton_kind_link_inline {
color: $alert;
}
}
.mx_SetupEncryptionBody {
width: 600px;
}
6 changes: 5 additions & 1 deletion res/css/views/auth/_AuthPage.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ Please see LICENSE files in the repository root for full details.
display: flex;
margin: 100px auto auto;
border-radius: 4px;
box-shadow: 0 2px 4px 0 rgb(0, 0, 0, 0.33);
background-color: $authpage-modal-bg-color;

@media only screen and (max-height: 768px) {
Expand All @@ -29,4 +28,9 @@ Please see LICENSE files in the repository root for full details.
@media only screen and (max-width: 480px) {
margin-top: 0;
}

/* Apply a blurred shadow around the modal */
&.mx_AuthPage_modal_withBlur {
box-shadow: 0 2px 4px 0 rgb(0, 0, 0, 0.33);
}
}
3 changes: 1 addition & 2 deletions res/css/views/auth/_CompleteSecurityBody.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ Please see LICENSE files in the repository root for full details.
*/

.mx_CompleteSecurityBody {
width: 600px;
color: $authpage-primary-color;
background-color: $background;
border-radius: 4px;
padding: 20px;
padding: 20px 20px 60px 20px;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason that I haven't been able to figure out, it squishes the bottom of the dialog, so I had to add some extra padding here.

box-sizing: border-box;

h2 {
Expand Down
7 changes: 7 additions & 0 deletions res/css/views/settings/encryption/_EncryptionCard.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
text-align: center;
}
}

/* extra class for specifying that we don't need a border */
&.mx_EncryptionCard_noBorder {
border: 0px none;
box-shadow: none;
padding: 0px;
}
}

.mx_EncryptionCard_buttons {
Expand Down
43 changes: 21 additions & 22 deletions src/components/structures/auth/CompleteSecurity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/

import React from "react";
import { Glass } from "@vector-im/compound-web";

import { _t } from "../../../languageHandler";
import { SetupEncryptionStore, Phase } from "../../../stores/SetupEncryptionStore";
Expand All @@ -22,15 +23,17 @@ interface IProps {

interface IState {
phase?: Phase;
lostKeys: boolean;
}

/**
* Prompts the user to verify their device when they first log in.
*/
export default class CompleteSecurity extends React.Component<IProps, IState> {
public constructor(props: IProps) {
super(props);
const store = SetupEncryptionStore.sharedInstance();
store.start();
this.state = { phase: store.phase, lostKeys: store.lostKeys() };
this.state = { phase: store.phase };
}

public componentDidMount(): void {
Expand All @@ -40,7 +43,7 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {

private onStoreUpdate = (): void => {
const store = SetupEncryptionStore.sharedInstance();
this.setState({ phase: store.phase, lostKeys: store.lostKeys() });
this.setState({ phase: store.phase });
};

private onSkipClick = (): void => {
Expand All @@ -55,20 +58,14 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
}

public render(): React.ReactNode {
const { phase, lostKeys } = this.state;
const { phase } = this.state;
let icon;
let title;

if (phase === Phase.Loading) {
return null;
} else if (phase === Phase.Intro) {
if (lostKeys) {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
title = _t("encryption|verification|after_new_login|unable_to_verify");
} else {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_warning" />;
title = _t("encryption|verification|after_new_login|verify_this_device");
}
// We don't specify an icon nor title since `SetupEncryptionBody` provides its own
} else if (phase === Phase.Done) {
icon = <span className="mx_CompleteSecurity_headerIcon mx_E2EIcon_verified" />;
title = _t("encryption|verification|after_new_login|device_verified");
Expand Down Expand Up @@ -98,17 +95,19 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
}

return (
<AuthPage>
<CompleteSecurityBody>
<h1 className="mx_CompleteSecurity_header">
{icon}
{title}
{skipButton}
</h1>
<div className="mx_CompleteSecurity_body">
<SetupEncryptionBody onFinished={this.props.onFinished} />
</div>
</CompleteSecurityBody>
<AuthPage addBlur={false}>
<Glass className="mx_Dialog_border">
<CompleteSecurityBody>
<h1 className="mx_CompleteSecurity_header">
{icon}
{title}
{skipButton}
</h1>
<div className="mx_CompleteSecurity_body">
<SetupEncryptionBody onFinished={this.props.onFinished} allowLogout={true} />
</div>
</CompleteSecurityBody>
</Glass>
</AuthPage>
);
}
Expand Down
Loading
Loading