diff --git a/src/IConfigOptions.ts b/src/IConfigOptions.ts index 97346641ec..72bee5d0ab 100644 --- a/src/IConfigOptions.ts +++ b/src/IConfigOptions.ts @@ -52,6 +52,8 @@ export interface IConfigOptions { 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 embedded_pages?: { diff --git a/src/components/structures/auth/CompleteSecurity.tsx b/src/components/structures/auth/CompleteSecurity.tsx index eb3ae3f592..568b7bffbd 100644 --- a/src/components/structures/auth/CompleteSecurity.tsx +++ b/src/components/structures/auth/CompleteSecurity.tsx @@ -14,6 +14,7 @@ import SetupEncryptionBody from "./SetupEncryptionBody"; import AccessibleButton from "../../views/elements/AccessibleButton"; import CompleteSecurityBody from "../../views/auth/CompleteSecurityBody"; import AuthPage from "../../views/auth/AuthPage"; +import SdkConfig from "../../../SdkConfig"; interface IProps { onFinished: () => void; @@ -82,8 +83,10 @@ export default class CompleteSecurity extends React.Component { throw new Error(`Unknown phase ${phase}`); } + const forceVerification = SdkConfig.get("force_verification") ?? false; + let skipButton; - if (phase === Phase.Intro || phase === Phase.ConfirmReset) { + if (!forceVerification && (phase === Phase.Intro || phase === Phase.ConfirmReset)) { skipButton = ( 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( {}} />); + + 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( {}} />); + + 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( {}} />); + + expect(screen.queryByRole("button", { name: "Skip verification for now" })).not.toBeInTheDocument(); + }); +}); diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 8e82c298e4..092f30fb52 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -108,6 +108,7 @@ export function createTestClient(): MatrixClient { secretStorage: { get: jest.fn(), + isStored: jest.fn().mockReturnValue(false), }, store: { @@ -128,6 +129,7 @@ export function createTestClient(): MatrixClient { getDeviceVerificationStatus: jest.fn(), resetKeyBackup: jest.fn(), isEncryptionEnabledInRoom: jest.fn(), + getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]), }), getPushActionsForEvent: jest.fn(),