Remove feature_cross_signing
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
515304d32e
commit
2b432b0d82
25 changed files with 106 additions and 1799 deletions
|
@ -15,7 +15,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {MatrixClientPeg} from './MatrixClientPeg';
|
import {MatrixClientPeg} from './MatrixClientPeg';
|
||||||
import SettingsStore from './settings/SettingsStore';
|
|
||||||
import {
|
import {
|
||||||
hideToast as hideBulkUnverifiedSessionsToast,
|
hideToast as hideBulkUnverifiedSessionsToast,
|
||||||
showToast as showBulkUnverifiedSessionsToast
|
showToast as showBulkUnverifiedSessionsToast
|
||||||
|
@ -173,10 +172,7 @@ export default class DeviceListener {
|
||||||
async _recheck() {
|
async _recheck() {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
if (
|
if (!await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) return;
|
||||||
!SettingsStore.getValue("feature_cross_signing") ||
|
|
||||||
!await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")
|
|
||||||
) return;
|
|
||||||
|
|
||||||
if (!cli.isCryptoEnabled()) return;
|
if (!cli.isCryptoEnabled()) return;
|
||||||
// don't recheck until the initial sync is complete: lots of account data events will fire
|
// don't recheck until the initial sync is complete: lots of account data events will fire
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
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 * as sdk from './index';
|
|
||||||
import Modal from './Modal';
|
|
||||||
import SettingsStore from './settings/SettingsStore';
|
|
||||||
|
|
||||||
// TODO: We can remove this once cross-signing is the only way.
|
|
||||||
// https://github.com/vector-im/riot-web/issues/11908
|
|
||||||
export default class KeyRequestHandler {
|
|
||||||
constructor(matrixClient) {
|
|
||||||
this._matrixClient = matrixClient;
|
|
||||||
|
|
||||||
// the user/device for which we currently have a dialog open
|
|
||||||
this._currentUser = null;
|
|
||||||
this._currentDevice = null;
|
|
||||||
|
|
||||||
// userId -> deviceId -> [keyRequest]
|
|
||||||
this._pendingKeyRequests = Object.create(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleKeyRequest(keyRequest) {
|
|
||||||
// Ignore own device key requests if cross-signing lab enabled
|
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userId = keyRequest.userId;
|
|
||||||
const deviceId = keyRequest.deviceId;
|
|
||||||
const requestId = keyRequest.requestId;
|
|
||||||
|
|
||||||
if (!this._pendingKeyRequests[userId]) {
|
|
||||||
this._pendingKeyRequests[userId] = Object.create(null);
|
|
||||||
}
|
|
||||||
if (!this._pendingKeyRequests[userId][deviceId]) {
|
|
||||||
this._pendingKeyRequests[userId][deviceId] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we already have this request
|
|
||||||
const requests = this._pendingKeyRequests[userId][deviceId];
|
|
||||||
if (requests.find((r) => r.requestId === requestId)) {
|
|
||||||
console.log("Already have this key request, ignoring");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
requests.push(keyRequest);
|
|
||||||
|
|
||||||
if (this._currentUser) {
|
|
||||||
// ignore for now
|
|
||||||
console.log("Key request, but we already have a dialog open");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._processNextRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleKeyRequestCancellation(cancellation) {
|
|
||||||
// Ignore own device key requests if cross-signing lab enabled
|
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if we can find the request in the queue
|
|
||||||
const userId = cancellation.userId;
|
|
||||||
const deviceId = cancellation.deviceId;
|
|
||||||
const requestId = cancellation.requestId;
|
|
||||||
|
|
||||||
if (userId === this._currentUser && deviceId === this._currentDevice) {
|
|
||||||
console.log(
|
|
||||||
"room key request cancellation for the user we currently have a"
|
|
||||||
+ " dialog open for",
|
|
||||||
);
|
|
||||||
// TODO: update the dialog. For now, we just ignore the
|
|
||||||
// cancellation.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._pendingKeyRequests[userId]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const requests = this._pendingKeyRequests[userId][deviceId];
|
|
||||||
if (!requests) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const idx = requests.findIndex((r) => r.requestId === requestId);
|
|
||||||
if (idx < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("Forgetting room key request");
|
|
||||||
requests.splice(idx, 1);
|
|
||||||
if (requests.length === 0) {
|
|
||||||
delete this._pendingKeyRequests[userId][deviceId];
|
|
||||||
if (Object.keys(this._pendingKeyRequests[userId]).length === 0) {
|
|
||||||
delete this._pendingKeyRequests[userId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_processNextRequest() {
|
|
||||||
const userId = Object.keys(this._pendingKeyRequests)[0];
|
|
||||||
if (!userId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const deviceId = Object.keys(this._pendingKeyRequests[userId])[0];
|
|
||||||
if (!deviceId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(`Starting KeyShareDialog for ${userId}:${deviceId}`);
|
|
||||||
|
|
||||||
const finished = (r) => {
|
|
||||||
this._currentUser = null;
|
|
||||||
this._currentDevice = null;
|
|
||||||
|
|
||||||
if (!this._pendingKeyRequests[userId] || !this._pendingKeyRequests[userId][deviceId]) {
|
|
||||||
// request was removed in the time the dialog was displayed
|
|
||||||
this._processNextRequest();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r) {
|
|
||||||
for (const req of this._pendingKeyRequests[userId][deviceId]) {
|
|
||||||
req.share();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete this._pendingKeyRequests[userId][deviceId];
|
|
||||||
if (Object.keys(this._pendingKeyRequests[userId]).length === 0) {
|
|
||||||
delete this._pendingKeyRequests[userId];
|
|
||||||
}
|
|
||||||
|
|
||||||
this._processNextRequest();
|
|
||||||
};
|
|
||||||
|
|
||||||
const KeyShareDialog = sdk.getComponent("dialogs.KeyShareDialog");
|
|
||||||
Modal.appendTrackedDialog('Key Share', 'Process Next Request', KeyShareDialog, {
|
|
||||||
matrixClient: this._matrixClient,
|
|
||||||
userId: userId,
|
|
||||||
deviceId: deviceId,
|
|
||||||
onFinished: finished,
|
|
||||||
});
|
|
||||||
this._currentUser = userId;
|
|
||||||
this._currentDevice = deviceId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import {MatrixClientPeg} from '../../../../MatrixClientPeg';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {_t, _td} from '../../../../languageHandler';
|
import {_t, _td} from '../../../../languageHandler';
|
||||||
import { accessSecretStorage } from '../../../../CrossSigningManager';
|
import { accessSecretStorage } from '../../../../CrossSigningManager';
|
||||||
import SettingsStore from '../../../../settings/SettingsStore';
|
|
||||||
import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
|
import AccessibleButton from "../../../../components/views/elements/AccessibleButton";
|
||||||
import {copyNode} from "../../../../utils/strings";
|
import {copyNode} from "../../../../utils/strings";
|
||||||
import PassphraseField from "../../../../components/views/auth/PassphraseField";
|
import PassphraseField from "../../../../components/views/auth/PassphraseField";
|
||||||
|
@ -67,10 +66,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const secureSecretStorage = (
|
const secureSecretStorage = await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing");
|
||||||
SettingsStore.getValue("feature_cross_signing") &&
|
|
||||||
await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")
|
|
||||||
);
|
|
||||||
this.setState({ secureSecretStorage });
|
this.setState({ secureSecretStorage });
|
||||||
|
|
||||||
// If we're using secret storage, skip ahead to the backing up step, as
|
// If we're using secret storage, skip ahead to the backing up step, as
|
||||||
|
|
|
@ -49,7 +49,6 @@ import PageTypes from '../../PageTypes';
|
||||||
import { getHomePageUrl } from '../../utils/pages';
|
import { getHomePageUrl } from '../../utils/pages';
|
||||||
|
|
||||||
import createRoom from "../../createRoom";
|
import createRoom from "../../createRoom";
|
||||||
import KeyRequestHandler from '../../KeyRequestHandler';
|
|
||||||
import { _t, getCurrentLanguage } from '../../languageHandler';
|
import { _t, getCurrentLanguage } from '../../languageHandler';
|
||||||
import SettingsStore, { SettingLevel } from "../../settings/SettingsStore";
|
import SettingsStore, { SettingLevel } from "../../settings/SettingsStore";
|
||||||
import ThemeController from "../../settings/controllers/ThemeController";
|
import ThemeController from "../../settings/controllers/ThemeController";
|
||||||
|
@ -1471,16 +1470,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
cli.on("Session.logged_out", () => dft.stop());
|
cli.on("Session.logged_out", () => dft.stop());
|
||||||
cli.on("Event.decrypted", (e, err) => dft.eventDecrypted(e, err));
|
cli.on("Event.decrypted", (e, err) => dft.eventDecrypted(e, err));
|
||||||
|
|
||||||
// TODO: We can remove this once cross-signing is the only way.
|
|
||||||
// https://github.com/vector-im/riot-web/issues/11908
|
|
||||||
const krh = new KeyRequestHandler(cli);
|
|
||||||
cli.on("crypto.roomKeyRequest", (req) => {
|
|
||||||
krh.handleKeyRequest(req);
|
|
||||||
});
|
|
||||||
cli.on("crypto.roomKeyRequestCancellation", (req) => {
|
|
||||||
krh.handleKeyRequestCancellation(req);
|
|
||||||
});
|
|
||||||
|
|
||||||
cli.on("Room", (room) => {
|
cli.on("Room", (room) => {
|
||||||
if (MatrixClientPeg.get().isCryptoEnabled()) {
|
if (MatrixClientPeg.get().isCryptoEnabled()) {
|
||||||
const blacklistEnabled = SettingsStore.getValueAt(
|
const blacklistEnabled = SettingsStore.getValueAt(
|
||||||
|
@ -1551,13 +1540,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
});
|
});
|
||||||
|
|
||||||
cli.on("crypto.verification.request", request => {
|
cli.on("crypto.verification.request", request => {
|
||||||
const isFlagOn = SettingsStore.getValue("feature_cross_signing");
|
|
||||||
|
|
||||||
if (!isFlagOn && !request.channel.deviceId) {
|
|
||||||
request.cancel({code: "m.invalid_message", reason: "This client has cross-signing disabled"});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.verifier) {
|
if (request.verifier) {
|
||||||
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
|
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
|
||||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||||
|
@ -1600,9 +1582,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
// be aware of will be signalled through the room shield
|
// be aware of will be signalled through the room shield
|
||||||
// changing colour. More advanced behaviour will come once
|
// changing colour. More advanced behaviour will come once
|
||||||
// we implement more settings.
|
// we implement more settings.
|
||||||
cli.setGlobalErrorOnUnknownDevices(
|
cli.setGlobalErrorOnUnknownDevices(false);
|
||||||
!SettingsStore.getValue("feature_cross_signing"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1956,18 +1936,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
return setLoggedInPromise;
|
return setLoggedInPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for the master cross-signing key in SSSS as a quick proxy for
|
if (await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")) {
|
||||||
// whether cross-signing has been set up on the account.
|
|
||||||
const masterKeyInStorage = !!cli.getAccountData("m.cross_signing.master");
|
|
||||||
if (masterKeyInStorage) {
|
|
||||||
// Auto-enable cross-signing for the new session when key found in
|
|
||||||
// secret storage.
|
|
||||||
SettingsStore.setValue("feature_cross_signing", null, SettingLevel.DEVICE, true);
|
|
||||||
this.setStateForNewView({ view: Views.COMPLETE_SECURITY });
|
|
||||||
} else if (
|
|
||||||
SettingsStore.getValue("feature_cross_signing") &&
|
|
||||||
await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")
|
|
||||||
) {
|
|
||||||
// This will only work if the feature is set to 'enable' in the config,
|
// This will only work if the feature is set to 'enable' in the config,
|
||||||
// since it's too early in the lifecycle for users to have turned the
|
// since it's too early in the lifecycle for users to have turned the
|
||||||
// labs flag on.
|
// labs flag on.
|
||||||
|
|
|
@ -189,16 +189,45 @@ export default class RightPanel extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCloseRoomMemberInfo = () => {
|
||||||
|
// XXX: There are three different ways of 'closing' this panel depending on what state
|
||||||
|
// things are in... this knows far more than it should do about the state of the rest
|
||||||
|
// of the app and is generally a bit silly.
|
||||||
|
if (this.props.user) {
|
||||||
|
// If we have a user prop then we're displaying a user from the 'user' page type
|
||||||
|
// in LoggedInView, so need to change the page type to close the panel (we switch
|
||||||
|
// to the home page which is not obviously the correct thing to do, but I'm not sure
|
||||||
|
// anything else is - we could hide the close button altogether?)
|
||||||
|
dis.dispatch({
|
||||||
|
action: "view_home_page",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Otherwise we have got our user from RoomViewStore which means we're being shown
|
||||||
|
// within a room, so go back to the member panel if we were in the encryption panel,
|
||||||
|
// or the member list if we were in the member panel... phew.
|
||||||
|
dis.dispatch({
|
||||||
|
action: Action.ViewUser,
|
||||||
|
member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ?
|
||||||
|
this.state.member : null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onCloseGroupMemberInfo = () => {
|
||||||
|
dis.dispatch({
|
||||||
|
action: Action.ViewUser,
|
||||||
|
member: null,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const MemberList = sdk.getComponent('rooms.MemberList');
|
const MemberList = sdk.getComponent('rooms.MemberList');
|
||||||
const MemberInfo = sdk.getComponent('rooms.MemberInfo');
|
|
||||||
const UserInfo = sdk.getComponent('right_panel.UserInfo');
|
const UserInfo = sdk.getComponent('right_panel.UserInfo');
|
||||||
const ThirdPartyMemberInfo = sdk.getComponent('rooms.ThirdPartyMemberInfo');
|
const ThirdPartyMemberInfo = sdk.getComponent('rooms.ThirdPartyMemberInfo');
|
||||||
const NotificationPanel = sdk.getComponent('structures.NotificationPanel');
|
const NotificationPanel = sdk.getComponent('structures.NotificationPanel');
|
||||||
const FilePanel = sdk.getComponent('structures.FilePanel');
|
const FilePanel = sdk.getComponent('structures.FilePanel');
|
||||||
|
|
||||||
const GroupMemberList = sdk.getComponent('groups.GroupMemberList');
|
const GroupMemberList = sdk.getComponent('groups.GroupMemberList');
|
||||||
const GroupMemberInfo = sdk.getComponent('groups.GroupMemberInfo');
|
|
||||||
const GroupRoomList = sdk.getComponent('groups.GroupRoomList');
|
const GroupRoomList = sdk.getComponent('groups.GroupRoomList');
|
||||||
const GroupRoomInfo = sdk.getComponent('groups.GroupRoomInfo');
|
const GroupRoomInfo = sdk.getComponent('groups.GroupRoomInfo');
|
||||||
|
|
||||||
|
@ -220,71 +249,25 @@ export default class RightPanel extends React.Component {
|
||||||
break;
|
break;
|
||||||
case RIGHT_PANEL_PHASES.RoomMemberInfo:
|
case RIGHT_PANEL_PHASES.RoomMemberInfo:
|
||||||
case RIGHT_PANEL_PHASES.EncryptionPanel:
|
case RIGHT_PANEL_PHASES.EncryptionPanel:
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
panel = <UserInfo
|
||||||
const onClose = () => {
|
user={this.state.member}
|
||||||
// XXX: There are three different ways of 'closing' this panel depending on what state
|
roomId={this.props.roomId}
|
||||||
// things are in... this knows far more than it should do about the state of the rest
|
key={this.props.roomId || this.state.member.userId}
|
||||||
// of the app and is generally a bit silly.
|
onClose={this.onCloseRoomMemberInfo}
|
||||||
if (this.props.user) {
|
phase={this.state.phase}
|
||||||
// If we have a user prop then we're displaying a user from the 'user' page type
|
verificationRequest={this.state.verificationRequest}
|
||||||
// in LoggedInView, so need to change the page type to close the panel (we switch
|
verificationRequestPromise={this.state.verificationRequestPromise}
|
||||||
// to the home page which is not obviously the correct thing to do, but I'm not sure
|
/>;
|
||||||
// anything else is - we could hide the close button altogether?)
|
|
||||||
dis.dispatch({
|
|
||||||
action: "view_home_page",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Otherwise we have got our user from RoomViewStore which means we're being shown
|
|
||||||
// within a room, so go back to the member panel if we were in the encryption panel,
|
|
||||||
// or the member list if we were in the member panel... phew.
|
|
||||||
dis.dispatch({
|
|
||||||
action: Action.ViewUser,
|
|
||||||
member: this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel ?
|
|
||||||
this.state.member : null,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
panel = <UserInfo
|
|
||||||
user={this.state.member}
|
|
||||||
roomId={this.props.roomId}
|
|
||||||
key={this.props.roomId || this.state.member.userId}
|
|
||||||
onClose={onClose}
|
|
||||||
phase={this.state.phase}
|
|
||||||
verificationRequest={this.state.verificationRequest}
|
|
||||||
verificationRequestPromise={this.state.verificationRequestPromise}
|
|
||||||
/>;
|
|
||||||
} else {
|
|
||||||
panel = <MemberInfo
|
|
||||||
member={this.state.member}
|
|
||||||
key={this.props.roomId || this.state.member.userId}
|
|
||||||
/>;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case RIGHT_PANEL_PHASES.Room3pidMemberInfo:
|
case RIGHT_PANEL_PHASES.Room3pidMemberInfo:
|
||||||
panel = <ThirdPartyMemberInfo event={this.state.event} key={this.props.roomId} />;
|
panel = <ThirdPartyMemberInfo event={this.state.event} key={this.props.roomId} />;
|
||||||
break;
|
break;
|
||||||
case RIGHT_PANEL_PHASES.GroupMemberInfo:
|
case RIGHT_PANEL_PHASES.GroupMemberInfo:
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
panel = <UserInfo
|
||||||
const onClose = () => {
|
user={this.state.member}
|
||||||
dis.dispatch({
|
groupId={this.props.groupId}
|
||||||
action: Action.ViewUser,
|
key={this.state.member.userId}
|
||||||
member: null,
|
onClose={this.onCloseGroupMemberInfo} />;
|
||||||
});
|
|
||||||
};
|
|
||||||
panel = <UserInfo
|
|
||||||
user={this.state.member}
|
|
||||||
groupId={this.props.groupId}
|
|
||||||
key={this.state.member.userId}
|
|
||||||
onClose={onClose} />;
|
|
||||||
} else {
|
|
||||||
panel = (
|
|
||||||
<GroupMemberInfo
|
|
||||||
groupMember={this.state.member}
|
|
||||||
groupId={this.props.groupId}
|
|
||||||
key={this.state.member.user_id}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case RIGHT_PANEL_PHASES.GroupRoomInfo:
|
case RIGHT_PANEL_PHASES.GroupRoomInfo:
|
||||||
panel = <GroupRoomInfo
|
panel = <GroupRoomInfo
|
||||||
|
|
|
@ -854,15 +854,6 @@ export default createReactClass({
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
room.hasUnverifiedDevices().then((hasUnverifiedDevices) => {
|
|
||||||
this.setState({
|
|
||||||
e2eStatus: hasUnverifiedDevices ? "warning" : "verified",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
debuglog("e2e check is warning/verified only as cross-signing is off");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At this point, the user has encryption on and cross-signing on */
|
/* At this point, the user has encryption on and cross-signing on */
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
|
@ -24,7 +24,6 @@ import withValidation from '../elements/Validation';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||||
import {Key} from "../../../Keyboard";
|
import {Key} from "../../../Keyboard";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
|
||||||
|
|
||||||
export default createReactClass({
|
export default createReactClass({
|
||||||
displayName: 'CreateRoomDialog',
|
displayName: 'CreateRoomDialog',
|
||||||
|
@ -66,7 +65,7 @@ export default createReactClass({
|
||||||
createOpts.creation_content = {'m.federate': false};
|
createOpts.creation_content = {'m.federate': false};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.isPublic && SettingsStore.getValue("feature_cross_signing")) {
|
if (!this.state.isPublic) {
|
||||||
opts.encryption = this.state.isEncrypted;
|
opts.encryption = this.state.isEncrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +192,7 @@ export default createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
let e2eeSection;
|
let e2eeSection;
|
||||||
if (!this.state.isPublic && SettingsStore.getValue("feature_cross_signing")) {
|
if (!this.state.isPublic) {
|
||||||
e2eeSection = <React.Fragment>
|
e2eeSection = <React.Fragment>
|
||||||
<LabelledToggleSwitch
|
<LabelledToggleSwitch
|
||||||
label={ _t("Enable end-to-end encryption")}
|
label={ _t("Enable end-to-end encryption")}
|
||||||
|
|
|
@ -119,7 +119,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
const verifyingOwnDevice = this.props.userId === client.getUserId();
|
const verifyingOwnDevice = this.props.userId === client.getUserId();
|
||||||
try {
|
try {
|
||||||
if (!verifyingOwnDevice && SettingsStore.getValue("feature_cross_signing")) {
|
if (!verifyingOwnDevice) {
|
||||||
const roomId = await ensureDMExistsAndOpen(this.props.userId);
|
const roomId = await ensureDMExistsAndOpen(this.props.userId);
|
||||||
// throws upon cancellation before having started
|
// throws upon cancellation before having started
|
||||||
const request = await client.requestVerificationDM(
|
const request = await client.requestVerificationDM(
|
||||||
|
@ -131,7 +131,7 @@ export default class DeviceVerifyDialog extends React.Component {
|
||||||
} else {
|
} else {
|
||||||
this._verifier = request.verifier;
|
this._verifier = request.verifier;
|
||||||
}
|
}
|
||||||
} else if (verifyingOwnDevice && SettingsStore.getValue("feature_cross_signing")) {
|
} else if (verifyingOwnDevice) {
|
||||||
this._request = await client.requestVerification(this.props.userId, [
|
this._request = await client.requestVerification(this.props.userId, [
|
||||||
verificationMethods.SAS,
|
verificationMethods.SAS,
|
||||||
SHOW_QR_CODE_METHOD,
|
SHOW_QR_CODE_METHOD,
|
||||||
|
|
|
@ -576,16 +576,14 @@ export default class InviteDialog extends React.PureComponent {
|
||||||
|
|
||||||
const createRoomOptions = {inlineErrors: true};
|
const createRoomOptions = {inlineErrors: true};
|
||||||
|
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
// Check whether all users have uploaded device keys before.
|
||||||
// Check whether all users have uploaded device keys before.
|
// If so, enable encryption in the new room.
|
||||||
// If so, enable encryption in the new room.
|
const has3PidMembers = targets.some(t => t instanceof ThreepidMember);
|
||||||
const has3PidMembers = targets.some(t => t instanceof ThreepidMember);
|
if (!has3PidMembers) {
|
||||||
if (!has3PidMembers) {
|
const client = MatrixClientPeg.get();
|
||||||
const client = MatrixClientPeg.get();
|
const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds);
|
||||||
const allHaveDeviceKeys = await canEncryptToAllUsers(client, targetIds);
|
if (allHaveDeviceKeys) {
|
||||||
if (allHaveDeviceKeys) {
|
createRoomOptions.encryption = true;
|
||||||
createRoomOptions.encryption = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,21 +90,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
|
||||||
|
|
||||||
_onResetRecoveryClick = () => {
|
_onResetRecoveryClick = () => {
|
||||||
this.props.onFinished(false);
|
this.props.onFinished(false);
|
||||||
|
accessSecretStorage(() => {}, /* forceReset = */ true);
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
// If cross-signing is enabled, we reset the SSSS recovery passphrase (and cross-signing keys)
|
|
||||||
this.props.onFinished(false);
|
|
||||||
accessSecretStorage(() => {}, /* forceReset = */ true);
|
|
||||||
} else {
|
|
||||||
Modal.createTrackedDialogAsync('Key Backup', 'Key Backup',
|
|
||||||
import('../../../../async-components/views/dialogs/keybackup/CreateKeyBackupDialog'),
|
|
||||||
{
|
|
||||||
onFinished: () => {
|
|
||||||
this._loadBackupStatus();
|
|
||||||
},
|
|
||||||
}, null, /* priority = */ false, /* static = */ true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRecoveryKeyChange = (e) => {
|
_onRecoveryKeyChange = (e) => {
|
||||||
|
|
|
@ -1,208 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
Copyright 2017 New Vector Ltd
|
|
||||||
Copyright 2019 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 React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import createReactClass from 'create-react-class';
|
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
|
||||||
import Modal from '../../../Modal';
|
|
||||||
import * as sdk from '../../../index';
|
|
||||||
import { _t } from '../../../languageHandler';
|
|
||||||
import { GroupMemberType } from '../../../groups';
|
|
||||||
import GroupStore from '../../../stores/GroupStore';
|
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|
||||||
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
|
|
||||||
import {Action} from "../../../dispatcher/actions";
|
|
||||||
|
|
||||||
export default createReactClass({
|
|
||||||
displayName: 'GroupMemberInfo',
|
|
||||||
|
|
||||||
statics: {
|
|
||||||
contextType: MatrixClientContext,
|
|
||||||
},
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
groupId: PropTypes.string,
|
|
||||||
groupMember: GroupMemberType,
|
|
||||||
isInvited: PropTypes.bool,
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
removingUser: false,
|
|
||||||
isUserPrivilegedInGroup: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
componentDidMount: function() {
|
|
||||||
this._unmounted = false;
|
|
||||||
this._initGroupStore(this.props.groupId);
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
|
|
||||||
UNSAFE_componentWillReceiveProps(newProps) {
|
|
||||||
if (newProps.groupId !== this.props.groupId) {
|
|
||||||
this._unregisterGroupStore(this.props.groupId);
|
|
||||||
this._initGroupStore(newProps.groupId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this._unmounted = true;
|
|
||||||
this._unregisterGroupStore(this.props.groupId);
|
|
||||||
},
|
|
||||||
|
|
||||||
_initGroupStore(groupId) {
|
|
||||||
GroupStore.registerListener(groupId, this.onGroupStoreUpdated);
|
|
||||||
},
|
|
||||||
|
|
||||||
_unregisterGroupStore(groupId) {
|
|
||||||
GroupStore.unregisterListener(this.onGroupStoreUpdated);
|
|
||||||
},
|
|
||||||
|
|
||||||
onGroupStoreUpdated: function() {
|
|
||||||
if (this._unmounted) return;
|
|
||||||
this.setState({
|
|
||||||
isUserInvited: GroupStore.getGroupInvitedMembers(this.props.groupId).some(
|
|
||||||
(m) => m.userId === this.props.groupMember.userId,
|
|
||||||
),
|
|
||||||
isUserPrivilegedInGroup: GroupStore.isUserPrivileged(this.props.groupId),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_onKick: function() {
|
|
||||||
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
|
||||||
Modal.createDialog(ConfirmUserActionDialog, {
|
|
||||||
matrixClient: this.context,
|
|
||||||
groupMember: this.props.groupMember,
|
|
||||||
action: this.state.isUserInvited ? _t('Disinvite') : _t('Remove from community'),
|
|
||||||
title: this.state.isUserInvited ? _t('Disinvite this user from community?')
|
|
||||||
: _t('Remove this user from community?'),
|
|
||||||
danger: true,
|
|
||||||
onFinished: (proceed) => {
|
|
||||||
if (!proceed) return;
|
|
||||||
|
|
||||||
this.setState({removingUser: true});
|
|
||||||
this.context.removeUserFromGroup(
|
|
||||||
this.props.groupId, this.props.groupMember.userId,
|
|
||||||
).then(() => {
|
|
||||||
// return to the user list
|
|
||||||
dis.dispatch({
|
|
||||||
action: Action.ViewUser,
|
|
||||||
member: null,
|
|
||||||
});
|
|
||||||
}).catch((e) => {
|
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
||||||
Modal.createTrackedDialog('Failed to remove user from group', '', ErrorDialog, {
|
|
||||||
title: _t('Error'),
|
|
||||||
description: this.state.isUserInvited ?
|
|
||||||
_t('Failed to withdraw invitation') :
|
|
||||||
_t('Failed to remove user from community'),
|
|
||||||
});
|
|
||||||
}).finally(() => {
|
|
||||||
this.setState({removingUser: false});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_onCancel: function(e) {
|
|
||||||
// Go back to the user list
|
|
||||||
dis.dispatch({
|
|
||||||
action: Action.ViewUser,
|
|
||||||
member: null,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onRoomTileClick(roomId) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'view_room',
|
|
||||||
room_id: roomId,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
if (this.state.removingUser) {
|
|
||||||
const Spinner = sdk.getComponent("elements.Spinner");
|
|
||||||
return <div className="mx_MemberInfo">
|
|
||||||
<Spinner />
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let adminTools;
|
|
||||||
if (this.state.isUserPrivilegedInGroup) {
|
|
||||||
const kickButton = (
|
|
||||||
<AccessibleButton className="mx_MemberInfo_field"
|
|
||||||
onClick={this._onKick}>
|
|
||||||
{ this.state.isUserInvited ? _t('Disinvite') : _t('Remove from community') }
|
|
||||||
</AccessibleButton>
|
|
||||||
);
|
|
||||||
|
|
||||||
// No make/revoke admin API yet
|
|
||||||
/*const opLabel = this.state.isTargetMod ? _t("Revoke Moderator") : _t("Make Moderator");
|
|
||||||
giveModButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onModToggle}>
|
|
||||||
{giveOpLabel}
|
|
||||||
</AccessibleButton>;*/
|
|
||||||
|
|
||||||
if (kickButton) {
|
|
||||||
adminTools =
|
|
||||||
<div className="mx_MemberInfo_adminTools">
|
|
||||||
<h3>{ _t("Admin Tools") }</h3>
|
|
||||||
<div className="mx_MemberInfo_buttons">
|
|
||||||
{ kickButton }
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const avatarUrl = this.props.groupMember.avatarUrl;
|
|
||||||
let avatarElement;
|
|
||||||
if (avatarUrl) {
|
|
||||||
const httpUrl = this.context.mxcUrlToHttp(avatarUrl, 800, 800);
|
|
||||||
avatarElement = (<div className="mx_MemberInfo_avatar">
|
|
||||||
<img src={httpUrl} />
|
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupMemberName = (
|
|
||||||
this.props.groupMember.displayname || this.props.groupMember.userId
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="mx_MemberInfo" role="tabpanel">
|
|
||||||
<AutoHideScrollbar>
|
|
||||||
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this._onCancel}>
|
|
||||||
<img src={require("../../../../res/img/cancel.svg")} width="18" height="18" className="mx_filterFlipColor" />
|
|
||||||
</AccessibleButton>
|
|
||||||
{ avatarElement }
|
|
||||||
<h2>{ groupMemberName }</h2>
|
|
||||||
|
|
||||||
<div className="mx_MemberInfo_profile">
|
|
||||||
<div className="mx_MemberInfo_profileField">
|
|
||||||
{ this.props.groupMember.userId }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{ adminTools }
|
|
||||||
</AutoHideScrollbar>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -64,10 +64,6 @@ const _disambiguateDevices = (devices) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getE2EStatus = (cli, userId, devices) => {
|
export const getE2EStatus = (cli, userId, devices) => {
|
||||||
if (!SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
const hasUnverifiedDevice = devices.some((device) => device.isUnverified());
|
|
||||||
return hasUnverifiedDevice ? "warning" : "verified";
|
|
||||||
}
|
|
||||||
const isMe = userId === cli.getUserId();
|
const isMe = userId === cli.getUserId();
|
||||||
const userTrust = cli.checkUserTrust(userId);
|
const userTrust = cli.checkUserTrust(userId);
|
||||||
if (!userTrust.isCrossSigningVerified()) {
|
if (!userTrust.isCrossSigningVerified()) {
|
||||||
|
@ -112,17 +108,15 @@ async function openDMForUser(matrixClient, userId) {
|
||||||
dmUserId: userId,
|
dmUserId: userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
// Check whether all users have uploaded device keys before.
|
||||||
// Check whether all users have uploaded device keys before.
|
// If so, enable encryption in the new room.
|
||||||
// If so, enable encryption in the new room.
|
const usersToDevicesMap = await matrixClient.downloadKeys([userId]);
|
||||||
const usersToDevicesMap = await matrixClient.downloadKeys([userId]);
|
const allHaveDeviceKeys = Object.values(usersToDevicesMap).every(devices => {
|
||||||
const allHaveDeviceKeys = Object.values(usersToDevicesMap).every(devices => {
|
// `devices` is an object of the form { deviceId: deviceInfo, ... }.
|
||||||
// `devices` is an object of the form { deviceId: deviceInfo, ... }.
|
return Object.keys(devices).length > 0;
|
||||||
return Object.keys(devices).length > 0;
|
});
|
||||||
});
|
if (allHaveDeviceKeys) {
|
||||||
if (allHaveDeviceKeys) {
|
createRoomOptions.encryption = true;
|
||||||
createRoomOptions.encryption = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createRoom(createRoomOptions);
|
createRoom(createRoomOptions);
|
||||||
|
@ -167,9 +161,7 @@ function DeviceItem({userId, device}) {
|
||||||
// cross-signing so that other users can then safely trust you.
|
// cross-signing so that other users can then safely trust you.
|
||||||
// For other people's devices, the more general verified check that
|
// For other people's devices, the more general verified check that
|
||||||
// includes locally verified devices can be used.
|
// includes locally verified devices can be used.
|
||||||
const isVerified = (isMe && SettingsStore.getValue("feature_cross_signing")) ?
|
const isVerified = isMe ? deviceTrust.isCrossSigningVerified() : deviceTrust.isVerified();
|
||||||
deviceTrust.isCrossSigningVerified() :
|
|
||||||
deviceTrust.isVerified();
|
|
||||||
|
|
||||||
const classes = classNames("mx_UserInfo_device", {
|
const classes = classNames("mx_UserInfo_device", {
|
||||||
mx_UserInfo_device_verified: isVerified,
|
mx_UserInfo_device_verified: isVerified,
|
||||||
|
@ -248,9 +240,7 @@ function DevicesSection({devices, userId, loading}) {
|
||||||
// cross-signing so that other users can then safely trust you.
|
// cross-signing so that other users can then safely trust you.
|
||||||
// For other people's devices, the more general verified check that
|
// For other people's devices, the more general verified check that
|
||||||
// includes locally verified devices can be used.
|
// includes locally verified devices can be used.
|
||||||
const isVerified = (isMe && SettingsStore.getValue("feature_cross_signing")) ?
|
const isVerified = isMe ? deviceTrust.isCrossSigningVerified() : deviceTrust.isVerified();
|
||||||
deviceTrust.isCrossSigningVerified() :
|
|
||||||
deviceTrust.isVerified();
|
|
||||||
|
|
||||||
if (isVerified) {
|
if (isVerified) {
|
||||||
expandSectionDevices.push(device);
|
expandSectionDevices.push(device);
|
||||||
|
@ -1309,8 +1299,7 @@ const BasicUserInfo = ({room, member, groupId, devices, isRoomEncrypted}) => {
|
||||||
const userTrust = cli.checkUserTrust(member.userId);
|
const userTrust = cli.checkUserTrust(member.userId);
|
||||||
const userVerified = userTrust.isCrossSigningVerified();
|
const userVerified = userTrust.isCrossSigningVerified();
|
||||||
const isMe = member.userId === cli.getUserId();
|
const isMe = member.userId === cli.getUserId();
|
||||||
const canVerify = SettingsStore.getValue("feature_cross_signing") &&
|
const canVerify = homeserverSupportsCrossSigning && !userVerified && !isMe;
|
||||||
homeserverSupportsCrossSigning && !userVerified && !isMe;
|
|
||||||
|
|
||||||
const setUpdating = (updating) => {
|
const setUpdating = (updating) => {
|
||||||
setPendingUpdateCount(count => count + (updating ? 1 : -1));
|
setPendingUpdateCount(count => count + (updating ? 1 : -1));
|
||||||
|
|
|
@ -20,7 +20,6 @@ import PropTypes from "prop-types";
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import {_t, _td} from '../../../languageHandler';
|
import {_t, _td} from '../../../languageHandler';
|
||||||
import {useSettingValue} from "../../../hooks/useSettings";
|
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
import Tooltip from "../elements/Tooltip";
|
import Tooltip from "../elements/Tooltip";
|
||||||
|
|
||||||
|
@ -42,15 +41,6 @@ const crossSigningRoomTitles = {
|
||||||
[E2E_STATE.VERIFIED]: _td("Everyone in this room is verified"),
|
[E2E_STATE.VERIFIED]: _td("Everyone in this room is verified"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const legacyUserTitles = {
|
|
||||||
[E2E_STATE.WARNING]: _td("Some sessions for this user are not trusted"),
|
|
||||||
[E2E_STATE.VERIFIED]: _td("All sessions for this user are trusted"),
|
|
||||||
};
|
|
||||||
const legacyRoomTitles = {
|
|
||||||
[E2E_STATE.WARNING]: _td("Some sessions in this encrypted room are not trusted"),
|
|
||||||
[E2E_STATE.VERIFIED]: _td("All sessions in this encrypted room are trusted"),
|
|
||||||
};
|
|
||||||
|
|
||||||
const E2EIcon = ({isUser, status, className, size, onClick, hideTooltip}) => {
|
const E2EIcon = ({isUser, status, className, size, onClick, hideTooltip}) => {
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
|
|
||||||
|
@ -62,15 +52,10 @@ const E2EIcon = ({isUser, status, className, size, onClick, hideTooltip}) => {
|
||||||
}, className);
|
}, className);
|
||||||
|
|
||||||
let e2eTitle;
|
let e2eTitle;
|
||||||
const crossSigning = useSettingValue("feature_cross_signing");
|
if (isUser) {
|
||||||
if (crossSigning && isUser) {
|
|
||||||
e2eTitle = crossSigningUserTitles[status];
|
e2eTitle = crossSigningUserTitles[status];
|
||||||
} else if (crossSigning && !isUser) {
|
} else {
|
||||||
e2eTitle = crossSigningRoomTitles[status];
|
e2eTitle = crossSigningRoomTitles[status];
|
||||||
} else if (!crossSigning && isUser) {
|
|
||||||
e2eTitle = legacyUserTitles[status];
|
|
||||||
} else if (!crossSigning && !isUser) {
|
|
||||||
e2eTitle = legacyRoomTitles[status];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let style;
|
let style;
|
||||||
|
|
|
@ -325,15 +325,6 @@ export default createReactClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If cross-signing is off, the old behaviour is to scream at the user
|
|
||||||
// as if they've done something wrong, which they haven't
|
|
||||||
if (!SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
this.setState({
|
|
||||||
verified: E2E_STATE.WARNING,
|
|
||||||
}, this.props.onHeightChanged);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.context.checkUserTrust(mxEvent.getSender()).isCrossSigningVerified()) {
|
if (!this.context.checkUserTrust(mxEvent.getSender()).isCrossSigningVerified()) {
|
||||||
this.setState({
|
this.setState({
|
||||||
verified: E2E_STATE.NORMAL,
|
verified: E2E_STATE.NORMAL,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -57,21 +57,19 @@ export default createReactClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
const { roomId } = this.props.member;
|
||||||
const { roomId } = this.props.member;
|
if (roomId) {
|
||||||
if (roomId) {
|
const isRoomEncrypted = cli.isRoomEncrypted(roomId);
|
||||||
const isRoomEncrypted = cli.isRoomEncrypted(roomId);
|
this.setState({
|
||||||
this.setState({
|
isRoomEncrypted,
|
||||||
isRoomEncrypted,
|
});
|
||||||
});
|
if (isRoomEncrypted) {
|
||||||
if (isRoomEncrypted) {
|
cli.on("userTrustStatusChanged", this.onUserTrustStatusChanged);
|
||||||
cli.on("userTrustStatusChanged", this.onUserTrustStatusChanged);
|
cli.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
|
||||||
cli.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
|
this.updateE2EStatus();
|
||||||
this.updateE2EStatus();
|
} else {
|
||||||
} else {
|
// Listen for room to become encrypted
|
||||||
// Listen for room to become encrypted
|
cli.on("RoomState.events", this.onRoomStateEvents);
|
||||||
cli.on("RoomState.events", this.onRoomStateEvents);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -281,33 +281,17 @@ export default class MessageComposer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPlaceholderText() {
|
renderPlaceholderText() {
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
if (this.state.isQuoting) {
|
||||||
if (this.state.isQuoting) {
|
if (this.props.e2eStatus) {
|
||||||
if (this.props.e2eStatus) {
|
return _t('Send an encrypted reply…');
|
||||||
return _t('Send an encrypted reply…');
|
|
||||||
} else {
|
|
||||||
return _t('Send a reply…');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (this.props.e2eStatus) {
|
return _t('Send a reply…');
|
||||||
return _t('Send an encrypted message…');
|
|
||||||
} else {
|
|
||||||
return _t('Send a message…');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.state.isQuoting) {
|
if (this.props.e2eStatus) {
|
||||||
if (this.props.e2eStatus) {
|
return _t('Send an encrypted message…');
|
||||||
return _t('Send an encrypted reply…');
|
|
||||||
} else {
|
|
||||||
return _t('Send a reply (unencrypted)…');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (this.props.e2eStatus) {
|
return _t('Send a message…');
|
||||||
return _t('Send an encrypted message…');
|
|
||||||
} else {
|
|
||||||
return _t('Send a message (unencrypted)…');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,10 +168,8 @@ export default createReactClass({
|
||||||
const joinRule = joinRules && joinRules.getContent().join_rule;
|
const joinRule = joinRules && joinRules.getContent().join_rule;
|
||||||
let privateIcon;
|
let privateIcon;
|
||||||
// Don't show an invite-only icon for DMs. Users know they're invite-only.
|
// Don't show an invite-only icon for DMs. Users know they're invite-only.
|
||||||
if (!dmUserId && SettingsStore.getValue("feature_cross_signing")) {
|
if (!dmUserId && joinRule === "invite") {
|
||||||
if (joinRule == "invite") {
|
privateIcon = <InviteOnlyIcon />;
|
||||||
privateIcon = <InviteOnlyIcon />;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.onCancelClick) {
|
if (this.props.onCancelClick) {
|
||||||
|
|
|
@ -155,9 +155,6 @@ export default createReactClass({
|
||||||
if (!cli.isRoomEncrypted(this.props.room.roomId)) {
|
if (!cli.isRoomEncrypted(this.props.room.roomId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At this point, the user has encryption on and cross-signing on */
|
/* At this point, the user has encryption on and cross-signing on */
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -515,10 +512,8 @@ export default createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
let privateIcon = null;
|
let privateIcon = null;
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
if (this.state.joinRule === "invite" && !dmUserId) {
|
||||||
if (this.state.joinRule == "invite" && !dmUserId) {
|
privateIcon = <InviteOnlyIcon collapsedPanel={this.props.collapsed} />;
|
||||||
privateIcon = <InviteOnlyIcon collapsedPanel={this.props.collapsed} />;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let e2eIcon = null;
|
let e2eIcon = null;
|
||||||
|
|
|
@ -194,6 +194,8 @@ export default class CrossSigningPanel extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: determine how better to expose this to users in addition to prompts at login/toast
|
||||||
let bootstrapButton;
|
let bootstrapButton;
|
||||||
if (
|
if (
|
||||||
(!enabledForAccount || !crossSigningPublicKeysOnDevice) &&
|
(!enabledForAccount || !crossSigningPublicKeysOnDevice) &&
|
||||||
|
|
|
@ -316,7 +316,7 @@ export default class KeyBackupPanel extends React.PureComponent {
|
||||||
trustedLocally = _t("This backup is trusted because it has been restored on this session");
|
trustedLocally = _t("This backup is trusted because it has been restored on this session");
|
||||||
}
|
}
|
||||||
|
|
||||||
let buttonRow = (
|
const buttonRow = (
|
||||||
<div className="mx_KeyBackupPanel_buttonRow">
|
<div className="mx_KeyBackupPanel_buttonRow">
|
||||||
<AccessibleButton kind="primary" onClick={this._restoreBackup}>
|
<AccessibleButton kind="primary" onClick={this._restoreBackup}>
|
||||||
{restoreButtonCaption}
|
{restoreButtonCaption}
|
||||||
|
@ -326,13 +326,6 @@ export default class KeyBackupPanel extends React.PureComponent {
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
if (this.state.backupKeyStored && !SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
buttonRow = <p>⚠️ {_t(
|
|
||||||
"Backup key stored in secret storage, but this feature is not " +
|
|
||||||
"enabled on this session. Please enable cross-signing in Labs to " +
|
|
||||||
"modify key backup state.",
|
|
||||||
)}</p>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<div>{clientBackupStatus}</div>
|
<div>{clientBackupStatus}</div>
|
||||||
|
|
|
@ -306,9 +306,7 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
// in having advanced details here once all flows are implemented, we
|
// in having advanced details here once all flows are implemented, we
|
||||||
// can remove this.
|
// can remove this.
|
||||||
const CrossSigningPanel = sdk.getComponent('views.settings.CrossSigningPanel');
|
const CrossSigningPanel = sdk.getComponent('views.settings.CrossSigningPanel');
|
||||||
let crossSigning;
|
const crossSigning = (
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
crossSigning = (
|
|
||||||
<div className='mx_SettingsTab_section'>
|
<div className='mx_SettingsTab_section'>
|
||||||
<span className="mx_SettingsTab_subheading">{_t("Cross-signing")}</span>
|
<span className="mx_SettingsTab_subheading">{_t("Cross-signing")}</span>
|
||||||
<div className='mx_SettingsTab_subsectionText'>
|
<div className='mx_SettingsTab_subsectionText'>
|
||||||
|
@ -316,7 +314,6 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
|
const E2eAdvancedPanel = sdk.getComponent('views.settings.E2eAdvancedPanel');
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import dis from "./dispatcher/dispatcher";
|
||||||
import * as Rooms from "./Rooms";
|
import * as Rooms from "./Rooms";
|
||||||
import DMRoomMap from "./utils/DMRoomMap";
|
import DMRoomMap from "./utils/DMRoomMap";
|
||||||
import {getAddressType} from "./UserAddress";
|
import {getAddressType} from "./UserAddress";
|
||||||
import SettingsStore from "./settings/SettingsStore";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new room, and switch to it.
|
* Create a new room, and switch to it.
|
||||||
|
@ -226,10 +225,7 @@ export async function ensureDMExists(client, userId) {
|
||||||
if (existingDMRoom) {
|
if (existingDMRoom) {
|
||||||
roomId = existingDMRoom.roomId;
|
roomId = existingDMRoom.roomId;
|
||||||
} else {
|
} else {
|
||||||
let encryption;
|
const encryption = canEncryptToAllUsers(client, [userId]);
|
||||||
if (SettingsStore.getValue("feature_cross_signing")) {
|
|
||||||
encryption = canEncryptToAllUsers(client, [userId]);
|
|
||||||
}
|
|
||||||
roomId = await createRoom({encryption, dmUserId: userId, spinner: false, andView: false});
|
roomId = await createRoom({encryption, dmUserId: userId, spinner: false, andView: false});
|
||||||
await _waitForMember(client, roomId, userId);
|
await _waitForMember(client, roomId, userId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,13 +164,6 @@ export const SETTINGS = {
|
||||||
supportedLevels: ['account'],
|
supportedLevels: ['account'],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
"feature_cross_signing": {
|
|
||||||
// XXX: We shouldn't be using the feature prefix for non-feature settings. There is an exception
|
|
||||||
// for this case though as we're converting a feature to a setting for a temporary safety net.
|
|
||||||
displayName: _td("Enable cross-signing to verify per-user instead of per-session"),
|
|
||||||
supportedLevels: ['device', 'config'], // we shouldn't use LEVELS_FEATURE for non-features, so copy it here.
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
"feature_bridge_state": {
|
"feature_bridge_state": {
|
||||||
isFeature: true,
|
isFeature: true,
|
||||||
supportedLevels: LEVELS_FEATURE,
|
supportedLevels: LEVELS_FEATURE,
|
||||||
|
|
|
@ -22,12 +22,11 @@ import { _t } from './languageHandler';
|
||||||
import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases";
|
import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases";
|
||||||
import {findDMForUser} from './createRoom';
|
import {findDMForUser} from './createRoom';
|
||||||
import {accessSecretStorage} from './CrossSigningManager';
|
import {accessSecretStorage} from './CrossSigningManager';
|
||||||
import SettingsStore from './settings/SettingsStore';
|
|
||||||
import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
import {verificationMethods} from 'matrix-js-sdk/src/crypto';
|
||||||
|
|
||||||
async function enable4SIfNeeded() {
|
async function enable4SIfNeeded() {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
if (!cli.isCryptoEnabled() || !SettingsStore.getValue("feature_cross_signing")) {
|
if (!cli.isCryptoEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const usk = cli.getCrossSigningId("user_signing");
|
const usk = cli.getCrossSigningId("user_signing");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue