mirror of
https://github.com/element-hq/element-web
synced 2024-11-28 04:21:57 +03:00
Add config option to force verification (#29)
* Add config option to force verification If this is set, users will not have the option to skip verification on login (they will still be able to reload and continue unverified, currently). Default off. * Test for complete security dialog * I hadn't set up prettier
This commit is contained in:
parent
75918f5b18
commit
a701e3afd7
4 changed files with 87 additions and 1 deletions
|
@ -52,6 +52,8 @@ export interface IConfigOptions {
|
||||||
auth_footer_links?: { text: string; url: string }[];
|
auth_footer_links?: { text: string; url: string }[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
force_verification?: boolean; // if true, users must verify new logins
|
||||||
|
|
||||||
map_style_url?: string; // for location-shared maps
|
map_style_url?: string; // for location-shared maps
|
||||||
|
|
||||||
embedded_pages?: {
|
embedded_pages?: {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import SetupEncryptionBody from "./SetupEncryptionBody";
|
||||||
import AccessibleButton from "../../views/elements/AccessibleButton";
|
import AccessibleButton from "../../views/elements/AccessibleButton";
|
||||||
import CompleteSecurityBody from "../../views/auth/CompleteSecurityBody";
|
import CompleteSecurityBody from "../../views/auth/CompleteSecurityBody";
|
||||||
import AuthPage from "../../views/auth/AuthPage";
|
import AuthPage from "../../views/auth/AuthPage";
|
||||||
|
import SdkConfig from "../../../SdkConfig";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
onFinished: () => void;
|
onFinished: () => void;
|
||||||
|
@ -82,8 +83,10 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
|
||||||
throw new Error(`Unknown phase ${phase}`);
|
throw new Error(`Unknown phase ${phase}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const forceVerification = SdkConfig.get("force_verification") ?? false;
|
||||||
|
|
||||||
let skipButton;
|
let skipButton;
|
||||||
if (phase === Phase.Intro || phase === Phase.ConfirmReset) {
|
if (!forceVerification && (phase === Phase.Intro || phase === Phase.ConfirmReset)) {
|
||||||
skipButton = (
|
skipButton = (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
onClick={this.onSkipClick}
|
onClick={this.onSkipClick}
|
||||||
|
|
79
test/components/structures/auth/CompleteSecurity-test.tsx
Normal file
79
test/components/structures/auth/CompleteSecurity-test.tsx
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 New Vector Ltd.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
|
Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import { mocked } from "jest-mock";
|
||||||
|
import EventEmitter from "events";
|
||||||
|
|
||||||
|
import CompleteSecurity from "../../../../src/components/structures/auth/CompleteSecurity";
|
||||||
|
import { stubClient } from "../../../test-utils";
|
||||||
|
import { Phase, SetupEncryptionStore } from "../../../../src/stores/SetupEncryptionStore";
|
||||||
|
import SdkConfig from "../../../../src/SdkConfig";
|
||||||
|
|
||||||
|
class MockSetupEncryptionStore extends EventEmitter {
|
||||||
|
public phase: Phase = Phase.Intro;
|
||||||
|
public lostKeys(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public start: () => void = jest.fn();
|
||||||
|
public stop: () => void = jest.fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("CompleteSecurity", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const client = stubClient();
|
||||||
|
const deviceIdToDevice = new Map();
|
||||||
|
deviceIdToDevice.set("DEVICE_ID", {
|
||||||
|
deviceId: "DEVICE_ID",
|
||||||
|
userId: "USER_ID",
|
||||||
|
});
|
||||||
|
const userIdToDevices = new Map();
|
||||||
|
userIdToDevices.set("USER_ID", deviceIdToDevice);
|
||||||
|
mocked(client.getCrypto()!.getUserDeviceInfo).mockResolvedValue(userIdToDevices);
|
||||||
|
|
||||||
|
const mockSetupEncryptionStore = new MockSetupEncryptionStore();
|
||||||
|
jest.spyOn(SetupEncryptionStore, "sharedInstance").mockReturnValue(
|
||||||
|
mockSetupEncryptionStore as SetupEncryptionStore,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Renders with a cancel button by default", () => {
|
||||||
|
render(<CompleteSecurity onFinished={() => {}} />);
|
||||||
|
|
||||||
|
expect(screen.getByRole("button", { name: "Skip verification for now" })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Renders with a cancel button if forceVerification false", () => {
|
||||||
|
jest.spyOn(SdkConfig, "get").mockImplementation((key: string) => {
|
||||||
|
if (key === "forceVerification") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<CompleteSecurity onFinished={() => {}} />);
|
||||||
|
|
||||||
|
expect(screen.getByRole("button", { name: "Skip verification for now" })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Renders without a cancel button if forceVerification true", () => {
|
||||||
|
jest.spyOn(SdkConfig, "get").mockImplementation((key: string) => {
|
||||||
|
if (key === "force_verification") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<CompleteSecurity onFinished={() => {}} />);
|
||||||
|
|
||||||
|
expect(screen.queryByRole("button", { name: "Skip verification for now" })).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
|
@ -108,6 +108,7 @@ export function createTestClient(): MatrixClient {
|
||||||
|
|
||||||
secretStorage: {
|
secretStorage: {
|
||||||
get: jest.fn(),
|
get: jest.fn(),
|
||||||
|
isStored: jest.fn().mockReturnValue(false),
|
||||||
},
|
},
|
||||||
|
|
||||||
store: {
|
store: {
|
||||||
|
@ -128,6 +129,7 @@ export function createTestClient(): MatrixClient {
|
||||||
getDeviceVerificationStatus: jest.fn(),
|
getDeviceVerificationStatus: jest.fn(),
|
||||||
resetKeyBackup: jest.fn(),
|
resetKeyBackup: jest.fn(),
|
||||||
isEncryptionEnabledInRoom: jest.fn(),
|
isEncryptionEnabledInRoom: jest.fn(),
|
||||||
|
getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getPushActionsForEvent: jest.fn(),
|
getPushActionsForEvent: jest.fn(),
|
||||||
|
|
Loading…
Reference in a new issue