diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 829a337256..40b13eef67 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -144,6 +144,7 @@ import { findDMForUser } from "../../utils/dm/findDMForUser"; import { Linkify } from "../../HtmlUtils"; import { NotificationColor } from "../../stores/notifications/NotificationColor"; import { UserTab } from "../views/dialogs/UserTab"; +import { shouldSkipSetupEncryption } from "../../utils/crypto/shouldSkipSetupEncryption"; // legacy export export { default as Views } from "../../Views"; @@ -394,7 +395,10 @@ export default class MatrixChat extends React.PureComponent { } else { this.setStateForNewView({ view: Views.COMPLETE_SECURITY }); } - } else if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) { + } else if ( + (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) && + !shouldSkipSetupEncryption(cli) + ) { // if cross-signing is not yet set up, do so now if possible. this.setStateForNewView({ view: Views.E2E_SETUP }); } else { diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index 14e8e638ae..973a0dbeb7 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -44,7 +44,7 @@ import MatrixClientContext from "../../../../../contexts/MatrixClientContext"; import { SettingsSection } from "../../shared/SettingsSection"; import SettingsTab from "../SettingsTab"; import SdkConfig from "../../../../../SdkConfig"; -import { shouldForceDisableEncryption } from "../../../../../utils/room/shouldForceDisableEncryption"; +import { shouldForceDisableEncryption } from "../../../../../utils/crypto/shouldForceDisableEncryption"; import { Caption } from "../../../typography/Caption"; interface IProps { diff --git a/src/createRoom.ts b/src/createRoom.ts index 10f1104b4c..b0888d7d00 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -43,7 +43,7 @@ import Spinner from "./components/views/elements/Spinner"; import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload"; import { findDMForUser } from "./utils/dm/findDMForUser"; import { privateShouldBeEncrypted } from "./utils/rooms"; -import { shouldForceDisableEncryption } from "./utils/room/shouldForceDisableEncryption"; +import { shouldForceDisableEncryption } from "./utils/crypto/shouldForceDisableEncryption"; import { waitForMember } from "./utils/membership"; import { PreferredRoomVersions } from "./utils/PreferredRoomVersions"; import SettingsStore from "./settings/SettingsStore"; diff --git a/src/utils/room/shouldForceDisableEncryption.ts b/src/utils/crypto/shouldForceDisableEncryption.ts similarity index 100% rename from src/utils/room/shouldForceDisableEncryption.ts rename to src/utils/crypto/shouldForceDisableEncryption.ts diff --git a/src/utils/crypto/shouldSkipSetupEncryption.ts b/src/utils/crypto/shouldSkipSetupEncryption.ts new file mode 100644 index 0000000000..24a1dbee83 --- /dev/null +++ b/src/utils/crypto/shouldSkipSetupEncryption.ts @@ -0,0 +1,30 @@ +/* +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 { MatrixClient } from "matrix-js-sdk/src/client"; + +import { shouldForceDisableEncryption } from "./shouldForceDisableEncryption"; + +/** + * If encryption is force disabled AND the user is not in any encrypted rooms + * skip setting up encryption + * @param client + * @returns {boolean} true when we can skip settings up encryption + */ +export const shouldSkipSetupEncryption = (client: MatrixClient): boolean => { + const isEncryptionForceDisabled = shouldForceDisableEncryption(client); + return isEncryptionForceDisabled && !client.getRooms().some((r) => client.isRoomEncrypted(r.roomId)); +}; diff --git a/src/utils/rooms.ts b/src/utils/rooms.ts index 27be4a644c..1aa2150d94 100644 --- a/src/utils/rooms.ts +++ b/src/utils/rooms.ts @@ -16,7 +16,7 @@ limitations under the License. import { MatrixClient } from "matrix-js-sdk/src/matrix"; -import { shouldForceDisableEncryption } from "./room/shouldForceDisableEncryption"; +import { shouldForceDisableEncryption } from "./crypto/shouldForceDisableEncryption"; import { getE2EEWellKnown } from "./WellKnownUtils"; export function privateShouldBeEncrypted(client: MatrixClient): boolean { diff --git a/test/components/structures/MatrixChat-test.tsx b/test/components/structures/MatrixChat-test.tsx index d86d2ba29f..e527292fdd 100644 --- a/test/components/structures/MatrixChat-test.tsx +++ b/test/components/structures/MatrixChat-test.tsx @@ -85,6 +85,7 @@ describe("", () => { isStored: jest.fn().mockReturnValue(null), }, getDehydratedDevice: jest.fn(), + isRoomEncrypted: jest.fn(), }); let mockClient = getMockClientWithEventEmitter(getMockClientMethods()); const serverConfig = { @@ -454,6 +455,59 @@ describe("", () => { await screen.findByLabelText("User menu"); }); + describe("when server supports cross signing and user does not have cross signing setup", () => { + beforeEach(() => { + loginClient.doesServerSupportUnstableFeature.mockResolvedValue(true); + loginClient.userHasCrossSigningKeys.mockResolvedValue(false); + }); + + describe("when encryption is force disabled", () => { + const unencryptedRoom = new Room("!unencrypted:server.org", loginClient, userId); + const encryptedRoom = new Room("!encrypted:server.org", loginClient, userId); + + beforeEach(() => { + loginClient.getClientWellKnown.mockReturnValue({ + "io.element.e2ee": { + force_disable: true, + }, + }); + + loginClient.isRoomEncrypted.mockImplementation((roomId) => roomId === encryptedRoom.roomId); + }); + + it("should go straight to logged in view when user is not in any encrypted rooms", async () => { + loginClient.getRooms.mockReturnValue([unencryptedRoom]); + await getComponentAndLogin(false); + + await flushPromises(); + + // logged in, did not setup keys + await screen.findByLabelText("User menu"); + }); + + it("should go to setup e2e screen when user is in encrypted rooms", async () => { + loginClient.getRooms.mockReturnValue([unencryptedRoom, encryptedRoom]); + await getComponentAndLogin(); + await flushPromises(); + // set up keys screen is rendered + expect(screen.getByText("Setting up keys")).toBeInTheDocument(); + }); + }); + + it("should go to setup e2e screen", async () => { + loginClient.doesServerSupportUnstableFeature.mockResolvedValue(true); + + await getComponentAndLogin(); + + expect(loginClient.userHasCrossSigningKeys).toHaveBeenCalled(); + + await flushPromises(); + + // set up keys screen is rendered + expect(screen.getByText("Setting up keys")).toBeInTheDocument(); + }); + }); + it("should show complete security screen when user has cross signing setup", async () => { loginClient.userHasCrossSigningKeys.mockResolvedValue(true); diff --git a/test/utils/room/shouldForceDisableEncryption-test.ts b/test/utils/crypto/shouldForceDisableEncryption-test.ts similarity index 98% rename from test/utils/room/shouldForceDisableEncryption-test.ts rename to test/utils/crypto/shouldForceDisableEncryption-test.ts index 3812e61ce9..a274d0df7c 100644 --- a/test/utils/room/shouldForceDisableEncryption-test.ts +++ b/test/utils/crypto/shouldForceDisableEncryption-test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { shouldForceDisableEncryption } from "../../../src/utils/room/shouldForceDisableEncryption"; +import { shouldForceDisableEncryption } from "../../../src/utils/crypto/shouldForceDisableEncryption"; import { getMockClientWithEventEmitter } from "../../test-utils"; describe("shouldForceDisableEncryption()", () => {