Merge pull request #5238 from matrix-org/travis/uifeat/paranoia

Add a UI feature to disable advanced encryption options
This commit is contained in:
Travis Ralston 2020-09-18 15:06:20 -06:00 committed by GitHub
commit 07f46fa3ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 113 additions and 17 deletions

View file

@ -19,6 +19,7 @@ import React from 'react';
import * as sdk from '../../../index'; import * as sdk from '../../../index';
import {_t} from "../../../languageHandler"; import {_t} from "../../../languageHandler";
import {SettingLevel} from "../../../settings/SettingLevel"; import {SettingLevel} from "../../../settings/SettingLevel";
import SettingsStore from "../../../settings/SettingsStore";
const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions"; const SETTING_MANUALLY_VERIFY_ALL_SESSIONS = "e2ee.manuallyVerifyAllSessions";
@ -37,3 +38,7 @@ const E2eAdvancedPanel = props => {
}; };
export default E2eAdvancedPanel; export default E2eAdvancedPanel;
export function isE2eAdvancedPanelPossible(): boolean {
return SettingsStore.isEnabled(SETTING_MANUALLY_VERIFY_ALL_SESSIONS);
}

View file

@ -24,6 +24,7 @@ import Modal from "../../../../../Modal";
import QuestionDialog from "../../../dialogs/QuestionDialog"; import QuestionDialog from "../../../dialogs/QuestionDialog";
import StyledRadioGroup from '../../../elements/StyledRadioGroup'; import StyledRadioGroup from '../../../elements/StyledRadioGroup';
import {SettingLevel} from "../../../../../settings/SettingLevel"; import {SettingLevel} from "../../../../../settings/SettingLevel";
import SettingsStore from "../../../../../settings/SettingsStore";
export default class SecurityRoomSettingsTab extends React.Component { export default class SecurityRoomSettingsTab extends React.Component {
static propTypes = { static propTypes = {
@ -340,10 +341,13 @@ export default class SecurityRoomSettingsTab extends React.Component {
const canEnableEncryption = !isEncrypted && hasEncryptionPermission; const canEnableEncryption = !isEncrypted && hasEncryptionPermission;
let encryptionSettings = null; let encryptionSettings = null;
if (isEncrypted) { if (isEncrypted && SettingsStore.isEnabled("blacklistUnverifiedDevices")) {
encryptionSettings = <SettingsFlag name="blacklistUnverifiedDevices" level={SettingLevel.ROOM_DEVICE} encryptionSettings = <SettingsFlag
onChange={this._updateBlacklistDevicesFlag} name="blacklistUnverifiedDevices"
roomId={this.props.roomId} />; level={SettingLevel.ROOM_DEVICE}
onChange={this._updateBlacklistDevicesFlag}
roomId={this.props.roomId}
/>;
} }
return ( return (

View file

@ -32,6 +32,7 @@ import {SettingLevel} from "../../../../../settings/SettingLevel";
import SecureBackupPanel from "../../SecureBackupPanel"; import SecureBackupPanel from "../../SecureBackupPanel";
import SettingsStore from "../../../../../settings/SettingsStore"; import SettingsStore from "../../../../../settings/SettingsStore";
import {UIFeature} from "../../../../../settings/UIFeature"; import {UIFeature} from "../../../../../settings/UIFeature";
import {isE2eAdvancedPanelPossible} from "../../E2eAdvancedPanel";
export class IgnoredUser extends React.Component { export class IgnoredUser extends React.Component {
static propTypes = { static propTypes = {
@ -219,6 +220,15 @@ export default class SecurityUserSettingsTab extends React.Component {
); );
} }
let noSendUnverifiedSetting;
if (SettingsStore.isEnabled("blacklistUnverifiedDevices")) {
noSendUnverifiedSetting = <SettingsFlag
name='blacklistUnverifiedDevices'
level={SettingLevel.DEVICE}
onChange={this._updateBlacklistDevicesFlag}
/>;
}
return ( return (
<div className='mx_SettingsTab_section'> <div className='mx_SettingsTab_section'>
<span className='mx_SettingsTab_subheading'>{_t("Cryptography")}</span> <span className='mx_SettingsTab_subheading'>{_t("Cryptography")}</span>
@ -233,8 +243,7 @@ export default class SecurityUserSettingsTab extends React.Component {
</li> </li>
</ul> </ul>
{importExportButtons} {importExportButtons}
<SettingsFlag name='blacklistUnverifiedDevices' level={SettingLevel.DEVICE} {noSendUnverifiedSetting}
onChange={this._updateBlacklistDevicesFlag} />
</div> </div>
); );
} }
@ -355,14 +364,20 @@ export default class SecurityUserSettingsTab extends React.Component {
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel'); const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
let advancedSection; let advancedSection;
if (SettingsStore.getValue(UIFeature.AdvancedSettings)) { if (SettingsStore.getValue(UIFeature.AdvancedSettings)) {
advancedSection = <> const ignoreUsersPanel = this._renderIgnoredUsers();
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div> const invitesPanel = this._renderManageInvites();
<div className="mx_SettingsTab_section"> const e2ePanel = isE2eAdvancedPanelPossible() ? <E2eAdvancedPanel /> : null;
{this._renderIgnoredUsers()} // only show the section if there's something to show
{this._renderManageInvites()} if (ignoreUsersPanel || invitesPanel || e2ePanel) {
<E2eAdvancedPanel /> advancedSection = <>
</div> <div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
</>; <div className="mx_SettingsTab_section">
{ignoreUsersPanel}
{invitesPanel}
{e2ePanel}
</div>
</>;
}
} }
return ( return (

View file

@ -34,6 +34,7 @@ import SettingController from "./controllers/SettingController";
import { RightPanelPhases } from "../stores/RightPanelStorePhases"; import { RightPanelPhases } from "../stores/RightPanelStorePhases";
import UIFeatureController from "./controllers/UIFeatureController"; import UIFeatureController from "./controllers/UIFeatureController";
import { UIFeature } from "./UIFeature"; import { UIFeature } from "./UIFeature";
import { OrderedMultiController } from "./controllers/OrderedMultiController";
// These are just a bunch of helper arrays to avoid copy/pasting a bunch of times // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times
const LEVELS_ROOM_SETTINGS = [ const LEVELS_ROOM_SETTINGS = [
@ -436,6 +437,7 @@ export const SETTINGS: {[setting: string]: ISetting} = {
"room-device": _td('Never send encrypted messages to unverified sessions in this room from this session'), "room-device": _td('Never send encrypted messages to unverified sessions in this room from this session'),
}, },
default: false, default: false,
controller: new UIFeatureController(UIFeature.AdvancedEncryption),
}, },
"urlPreviewsEnabled": { "urlPreviewsEnabled": {
supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM, supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM,
@ -591,9 +593,15 @@ export const SETTINGS: {[setting: string]: ISetting} = {
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS, supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
displayName: _td("Manually verify all remote sessions"), displayName: _td("Manually verify all remote sessions"),
default: false, default: false,
controller: new PushToMatrixClientController( controller: new OrderedMultiController([
MatrixClient.prototype.setCryptoTrustCrossSignedDevices, true, // Apply the feature controller first to ensure that the setting doesn't
), // show up and can't be toggled. PushToMatrixClientController doesn't
// do any overrides anyways.
new UIFeatureController(UIFeature.AdvancedEncryption),
new PushToMatrixClientController(
MatrixClient.prototype.setCryptoTrustCrossSignedDevices, true,
),
]),
}, },
"ircDisplayNameWidth": { "ircDisplayNameWidth": {
// We specifically want to have room-device > device so that users may set a device default // We specifically want to have room-device > device so that users may set a device default
@ -612,6 +620,10 @@ export const SETTINGS: {[setting: string]: ISetting} = {
supportedLevels: LEVELS_ROOM_OR_ACCOUNT, supportedLevels: LEVELS_ROOM_OR_ACCOUNT,
default: {}, default: {},
}, },
[UIFeature.AdvancedEncryption]: {
supportedLevels: LEVELS_UI_FEATURE,
default: true,
},
[UIFeature.URLPreviews]: { [UIFeature.URLPreviews]: {
supportedLevels: LEVELS_UI_FEATURE, supportedLevels: LEVELS_UI_FEATURE,
default: true, default: true,

View file

@ -16,6 +16,7 @@ limitations under the License.
// see settings.md for documentation on conventions // see settings.md for documentation on conventions
export enum UIFeature { export enum UIFeature {
AdvancedEncryption = "UIFeature.advancedEncryption",
URLPreviews = "UIFeature.urlPreviews", URLPreviews = "UIFeature.urlPreviews",
Widgets = "UIFeature.widgets", Widgets = "UIFeature.widgets",
Voip = "UIFeature.voip", Voip = "UIFeature.voip",

View file

@ -0,0 +1,59 @@
/*
Copyright 2020 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 SettingController from "./SettingController";
import { SettingLevel } from "../SettingLevel";
/**
* Allows for multiple controllers to affect a setting. The first controller
* provided to this class which overrides the setting value will affect
* the value - other controllers are not called. Change notification handlers
* are proxied through to all controllers.
*
* Similarly, the first controller which indicates that a setting is disabled
* will be used - other controllers will not be considered.
*/
export class OrderedMultiController extends SettingController {
constructor(public readonly controllers: SettingController[]) {
super();
}
public getValueOverride(
level: SettingLevel,
roomId: string,
calculatedValue: any,
calculatedAtLevel: SettingLevel,
): any {
for (const controller of this.controllers) {
const override = controller.getValueOverride(level, roomId, calculatedValue, calculatedAtLevel);
if (override !== undefined && override !== null) return override;
}
return null; // no override
}
public onChange(level: SettingLevel, roomId: string, newValue: any) {
for (const controller of this.controllers) {
controller.onChange(level, roomId, newValue);
}
}
public get settingDisabled(): boolean {
for (const controller of this.controllers) {
if (controller.settingDisabled) return true;
}
return false;
}
}