Disable encryption toggle in room settings when force disabled (#11122)

* force disable encryption on room creation

* test allowChangingEncryption

* move into utils/room directory

* tests

* unit test CreateRoomDialog

* remove debug

* wait for constructor promises to settle

* test case for force_disable

* comment

* set forced value after resolving checkUserIsAllowedToChangeEncryption

* tidy and comments

* use label text in test

* disable encryption switch in room settings when force disabled
This commit is contained in:
Kerry 2023-06-22 11:17:30 +12:00 committed by GitHub
parent a692fe2181
commit 9f580a8680
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 3 deletions

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2019-2022 The Matrix.org Foundation C.I.C. Copyright 2019-2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -44,6 +44,8 @@ import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
import { SettingsSection } from "../../shared/SettingsSection"; import { SettingsSection } from "../../shared/SettingsSection";
import SettingsTab from "../SettingsTab"; import SettingsTab from "../SettingsTab";
import SdkConfig from "../../../../../SdkConfig"; import SdkConfig from "../../../../../SdkConfig";
import { shouldForceDisableEncryption } from "../../../../../utils/room/shouldForceDisableEncryption";
import { Caption } from "../../../typography/Caption";
interface IProps { interface IProps {
room: Room; room: Room;
@ -442,7 +444,8 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
const room = this.props.room; const room = this.props.room;
const isEncrypted = this.state.encrypted; const isEncrypted = this.state.encrypted;
const hasEncryptionPermission = room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, client); const hasEncryptionPermission = room.currentState.mayClientSendStateEvent(EventType.RoomEncryption, client);
const canEnableEncryption = !isEncrypted && hasEncryptionPermission; const isEncryptionForceDisabled = shouldForceDisableEncryption(client);
const canEnableEncryption = !isEncrypted && !isEncryptionForceDisabled && hasEncryptionPermission;
let encryptionSettings: JSX.Element | undefined; let encryptionSettings: JSX.Element | undefined;
if (isEncrypted && SettingsStore.isEnabled("blacklistUnverifiedDevices")) { if (isEncrypted && SettingsStore.isEnabled("blacklistUnverifiedDevices")) {
@ -463,7 +466,11 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<SettingsSection heading={_t("Security & Privacy")}> <SettingsSection heading={_t("Security & Privacy")}>
<SettingsFieldset <SettingsFieldset
legend={_t("Encryption")} legend={_t("Encryption")}
description={_t("Once enabled, encryption cannot be disabled.")} description={
isEncryptionForceDisabled && !isEncrypted
? undefined
: _t("Once enabled, encryption cannot be disabled.")
}
> >
<LabelledToggleSwitch <LabelledToggleSwitch
value={isEncrypted} value={isEncrypted}
@ -471,6 +478,9 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
label={_t("Encrypted")} label={_t("Encrypted")}
disabled={!canEnableEncryption} disabled={!canEnableEncryption}
/> />
{isEncryptionForceDisabled && !isEncrypted && (
<Caption>{_t("Your server requires encryption to be disabled.")}</Caption>
)}
{encryptionSettings} {encryptionSettings}
</SettingsFieldset> </SettingsFieldset>

View file

@ -1762,6 +1762,7 @@
"Security & Privacy": "Security & Privacy", "Security & Privacy": "Security & Privacy",
"Once enabled, encryption cannot be disabled.": "Once enabled, encryption cannot be disabled.", "Once enabled, encryption cannot be disabled.": "Once enabled, encryption cannot be disabled.",
"Encrypted": "Encrypted", "Encrypted": "Encrypted",
"Your server requires encryption to be disabled.": "Your server requires encryption to be disabled.",
"Enable %(brand)s as an additional calling option in this room": "Enable %(brand)s as an additional calling option in this room", "Enable %(brand)s as an additional calling option in this room": "Enable %(brand)s as an additional calling option in this room",
"%(brand)s is end-to-end encrypted, but is currently limited to smaller numbers of users.": "%(brand)s is end-to-end encrypted, but is currently limited to smaller numbers of users.", "%(brand)s is end-to-end encrypted, but is currently limited to smaller numbers of users.": "%(brand)s is end-to-end encrypted, but is currently limited to smaller numbers of users.",
"You do not have sufficient permissions to change this.": "You do not have sufficient permissions to change this.", "You do not have sufficient permissions to change this.": "You do not have sufficient permissions to change this.",

View file

@ -38,6 +38,7 @@ describe("<SecurityRoomSettingsTab />", () => {
isRoomEncrypted: jest.fn(), isRoomEncrypted: jest.fn(),
getLocalAliases: jest.fn().mockReturnValue([]), getLocalAliases: jest.fn().mockReturnValue([]),
sendStateEvent: jest.fn(), sendStateEvent: jest.fn(),
getClientWellKnown: jest.fn(),
}); });
const roomId = "!room:server.org"; const roomId = "!room:server.org";
@ -94,6 +95,7 @@ describe("<SecurityRoomSettingsTab />", () => {
beforeEach(async () => { beforeEach(async () => {
client.sendStateEvent.mockReset().mockResolvedValue({ event_id: "test" }); client.sendStateEvent.mockReset().mockResolvedValue({ event_id: "test" });
client.isRoomEncrypted.mockReturnValue(false); client.isRoomEncrypted.mockReturnValue(false);
client.getClientWellKnown.mockReturnValue(undefined);
jest.spyOn(SettingsStore, "getValue").mockRestore(); jest.spyOn(SettingsStore, "getValue").mockRestore();
await clearAllModals(); await clearAllModals();
@ -408,5 +410,39 @@ describe("<SecurityRoomSettingsTab />", () => {
expect(screen.getByDisplayValue(HistoryVisibility.Shared)).toBeChecked(); expect(screen.getByDisplayValue(HistoryVisibility.Shared)).toBeChecked();
expect(logger.error).toHaveBeenCalledWith("oups"); expect(logger.error).toHaveBeenCalledWith("oups");
}); });
describe("when encryption is force disabled by e2ee well-known config", () => {
beforeEach(() => {
client.getClientWellKnown.mockReturnValue({
"io.element.e2ee": {
force_disable: true,
},
});
});
it("displays encrypted rooms as encrypted", () => {
// rooms that are already encrypted still show encrypted
const room = new Room(roomId, client, userId);
client.isRoomEncrypted.mockReturnValue(true);
setRoomStateEvents(room);
getComponent(room);
expect(screen.getByLabelText("Encrypted")).toBeChecked();
expect(screen.getByLabelText("Encrypted").getAttribute("aria-disabled")).toEqual("true");
expect(screen.getByText("Once enabled, encryption cannot be disabled.")).toBeInTheDocument();
});
it("displays unencrypted rooms with toggle disabled", () => {
const room = new Room(roomId, client, userId);
client.isRoomEncrypted.mockReturnValue(false);
setRoomStateEvents(room);
getComponent(room);
expect(screen.getByLabelText("Encrypted")).not.toBeChecked();
expect(screen.getByLabelText("Encrypted").getAttribute("aria-disabled")).toEqual("true");
expect(screen.queryByText("Once enabled, encryption cannot be disabled.")).not.toBeInTheDocument();
expect(screen.getByText("Your server requires encryption to be disabled.")).toBeInTheDocument();
});
});
}); });
}); });