Merge pull request #3728 from matrix-org/jryans/verify-users
Verify users when cross-signing enabled
This commit is contained in:
commit
be914c7b0c
10 changed files with 122 additions and 30 deletions
|
@ -22,7 +22,9 @@ limitations under the License.
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_E2EIcon_verified::after, .mx_E2EIcon_warning::after {
|
.mx_E2EIcon_warning::after,
|
||||||
|
.mx_E2EIcon_normal::after,
|
||||||
|
.mx_E2EIcon_verified::after {
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -34,10 +36,14 @@ limitations under the License.
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_E2EIcon_verified::after {
|
|
||||||
background-image: url('$(res)/img/e2e/verified.svg');
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_E2EIcon_warning::after {
|
.mx_E2EIcon_warning::after {
|
||||||
background-image: url('$(res)/img/e2e/warning.svg');
|
background-image: url('$(res)/img/e2e/warning.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_E2EIcon_normal::after {
|
||||||
|
background-image: url('$(res)/img/e2e/normal.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_E2EIcon_verified::after {
|
||||||
|
background-image: url('$(res)/img/e2e/verified.svg');
|
||||||
|
}
|
||||||
|
|
|
@ -1492,7 +1492,7 @@ export default createReactClass({
|
||||||
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
|
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
|
||||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||||
verifier,
|
verifier,
|
||||||
});
|
}, null, /* priority = */ false, /* static = */ true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Fire the tinter right on startup to ensure the default theme is applied
|
// Fire the tinter right on startup to ensure the default theme is applied
|
||||||
|
|
|
@ -792,11 +792,12 @@ module.exports = createReactClass({
|
||||||
this._updateE2EStatus(room);
|
this._updateE2EStatus(room);
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateE2EStatus: function(room) {
|
_updateE2EStatus: async function(room) {
|
||||||
if (!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) {
|
const cli = MatrixClientPeg.get();
|
||||||
|
if (!cli.isRoomEncrypted(room.roomId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!MatrixClientPeg.get().isCryptoEnabled()) {
|
if (!cli.isCryptoEnabled()) {
|
||||||
// If crypto is not currently enabled, we aren't tracking devices at all,
|
// If crypto is not currently enabled, we aren't tracking devices at all,
|
||||||
// so we don't know what the answer is. Let's error on the safe side and show
|
// so we don't know what the answer is. Let's error on the safe side and show
|
||||||
// a warning for this case.
|
// a warning for this case.
|
||||||
|
@ -805,11 +806,39 @@ module.exports = createReactClass({
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) {
|
||||||
room.hasUnverifiedDevices().then((hasUnverifiedDevices) => {
|
room.hasUnverifiedDevices().then((hasUnverifiedDevices) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
e2eStatus: hasUnverifiedDevices ? "warning" : "verified",
|
e2eStatus: hasUnverifiedDevices ? "warning" : "verified",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const e2eMembers = await room.getEncryptionTargetMembers();
|
||||||
|
for (const member of e2eMembers) {
|
||||||
|
const { userId } = member;
|
||||||
|
const userVerified = cli.checkUserTrust(userId).isCrossSigningVerified();
|
||||||
|
if (!userVerified) {
|
||||||
|
this.setState({
|
||||||
|
e2eStatus: "warning",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const devices = await cli.getStoredDevicesForUser(userId);
|
||||||
|
const allDevicesVerified = devices.every(device => {
|
||||||
|
const { deviceId } = device;
|
||||||
|
return cli.checkDeviceTrust(userId, deviceId).isCrossSigningVerified();
|
||||||
|
});
|
||||||
|
if (!allDevicesVerified) {
|
||||||
|
this.setState({
|
||||||
|
e2eStatus: "warning",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
e2eStatus: "verified",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateTint: function() {
|
updateTint: function() {
|
||||||
|
|
|
@ -99,7 +99,7 @@ export default createReactClass({
|
||||||
this.props.onFinished(true);
|
this.props.onFinished(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
}, null, /* priority = */ false, /* static = */ true);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onShareClicked: function() {
|
_onShareClicked: function() {
|
||||||
|
|
|
@ -59,7 +59,7 @@ export default createReactClass({
|
||||||
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
|
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
|
||||||
userId: this.props.userId,
|
userId: this.props.userId,
|
||||||
device: this.state.device,
|
device: this.state.device,
|
||||||
});
|
}, null, /* priority = */ false, /* static = */ true);
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnverifyClick: function() {
|
onUnverifyClick: function() {
|
||||||
|
|
|
@ -52,7 +52,7 @@ export default class MKeyVerificationRequest extends React.Component {
|
||||||
const verifier = MatrixClientPeg.get().acceptVerificationDM(this.props.mxEvent, verificationMethods.SAS);
|
const verifier = MatrixClientPeg.get().acceptVerificationDM(this.props.mxEvent, verificationMethods.SAS);
|
||||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||||
verifier,
|
verifier,
|
||||||
});
|
}, null, /* priority = */ false, /* static = */ true);
|
||||||
};
|
};
|
||||||
|
|
||||||
_onRejectClicked = () => {
|
_onRejectClicked = () => {
|
||||||
|
|
|
@ -58,9 +58,20 @@ const _disambiguateDevices = (devices) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const _getE2EStatus = (devices) => {
|
const _getE2EStatus = (cli, userId, devices) => {
|
||||||
|
if (!SettingsStore.isFeatureEnabled("feature_cross_signing")) {
|
||||||
const hasUnverifiedDevice = devices.some((device) => device.isUnverified());
|
const hasUnverifiedDevice = devices.some((device) => device.isUnverified());
|
||||||
return hasUnverifiedDevice ? "warning" : "verified";
|
return hasUnverifiedDevice ? "warning" : "verified";
|
||||||
|
}
|
||||||
|
const userVerified = cli.checkUserTrust(userId).isCrossSigningVerified();
|
||||||
|
const allDevicesVerified = devices.every(device => {
|
||||||
|
const { deviceId } = device;
|
||||||
|
return cli.checkDeviceTrust(userId, deviceId).isCrossSigningVerified();
|
||||||
|
});
|
||||||
|
if (allDevicesVerified) {
|
||||||
|
return userVerified ? "verified" : "normal";
|
||||||
|
}
|
||||||
|
return "warning";
|
||||||
};
|
};
|
||||||
|
|
||||||
async function unverifyUser(matrixClient, userId) {
|
async function unverifyUser(matrixClient, userId) {
|
||||||
|
@ -114,7 +125,7 @@ function verifyDevice(userId, device) {
|
||||||
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
|
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
|
||||||
userId: userId,
|
userId: userId,
|
||||||
device: device,
|
device: device,
|
||||||
});
|
}, null, /* priority = */ false, /* static = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DeviceItem({userId, device}) {
|
function DeviceItem({userId, device}) {
|
||||||
|
@ -1264,7 +1275,8 @@ const UserInfo = withLegacyMatrixClient(({matrixClient: cli, user, groupId, room
|
||||||
|
|
||||||
let e2eIcon;
|
let e2eIcon;
|
||||||
if (isRoomEncrypted && devices) {
|
if (isRoomEncrypted && devices) {
|
||||||
e2eIcon = <E2EIcon size={18} status={_getE2EStatus(devices)} isUser={true} />;
|
const e2eStatus = _getE2EStatus(cli, user.userId, devices);
|
||||||
|
e2eIcon = <E2EIcon size={18} status={e2eStatus} isUser={true} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -17,24 +17,62 @@ limitations under the License.
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import SettingsStore from '../../../settings/SettingsStore';
|
||||||
|
|
||||||
export default function(props) {
|
export default function(props) {
|
||||||
|
const { isUser } = props;
|
||||||
|
const isNormal = props.status === "normal";
|
||||||
const isWarning = props.status === "warning";
|
const isWarning = props.status === "warning";
|
||||||
const isVerified = props.status === "verified";
|
const isVerified = props.status === "verified";
|
||||||
const e2eIconClasses = classNames({
|
const e2eIconClasses = classNames({
|
||||||
mx_E2EIcon: true,
|
mx_E2EIcon: true,
|
||||||
mx_E2EIcon_warning: isWarning,
|
mx_E2EIcon_warning: isWarning,
|
||||||
|
mx_E2EIcon_normal: isNormal,
|
||||||
mx_E2EIcon_verified: isVerified,
|
mx_E2EIcon_verified: isVerified,
|
||||||
}, props.className);
|
}, props.className);
|
||||||
let e2eTitle;
|
let e2eTitle;
|
||||||
|
|
||||||
|
const crossSigning = SettingsStore.isFeatureEnabled("feature_cross_signing");
|
||||||
|
if (crossSigning && isUser) {
|
||||||
if (isWarning) {
|
if (isWarning) {
|
||||||
e2eTitle = props.isUser ?
|
e2eTitle = _t(
|
||||||
_t("Some devices for this user are not trusted") :
|
"This user has not verified all of their devices.",
|
||||||
_t("Some devices in this encrypted room are not trusted");
|
);
|
||||||
|
} else if (isNormal) {
|
||||||
|
e2eTitle = _t(
|
||||||
|
"You have not verified this user. " +
|
||||||
|
"This user has verified all of their devices.",
|
||||||
|
);
|
||||||
} else if (isVerified) {
|
} else if (isVerified) {
|
||||||
e2eTitle = props.isUser ?
|
e2eTitle = _t(
|
||||||
_t("All devices for this user are trusted") :
|
"You have verified this user. " +
|
||||||
_t("All devices in this encrypted room are trusted");
|
"This user has verified all of their devices.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (crossSigning && !isUser) {
|
||||||
|
if (isWarning) {
|
||||||
|
e2eTitle = _t(
|
||||||
|
"Some users in this encrypted room are not verified by you or " +
|
||||||
|
"they have not verified their own devices.",
|
||||||
|
);
|
||||||
|
} else if (isVerified) {
|
||||||
|
e2eTitle = _t(
|
||||||
|
"All users in this encrypted room are verified by you and " +
|
||||||
|
"they have verified their own devices.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (!crossSigning && isUser) {
|
||||||
|
if (isWarning) {
|
||||||
|
e2eTitle = _t("Some devices for this user are not trusted");
|
||||||
|
} else if (isVerified) {
|
||||||
|
e2eTitle = _t("All devices for this user are trusted");
|
||||||
|
}
|
||||||
|
} else if (!crossSigning && !isUser) {
|
||||||
|
if (isWarning) {
|
||||||
|
e2eTitle = _t("Some devices in this encrypted room are not trusted");
|
||||||
|
} else if (isVerified) {
|
||||||
|
e2eTitle = _t("All devices in this encrypted room are trusted");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let style = null;
|
let style = null;
|
||||||
|
|
|
@ -90,7 +90,9 @@ export default class VerificationRequestToast extends React.PureComponent {
|
||||||
|
|
||||||
const verifier = this.props.request.beginKeyVerification(verificationMethods.SAS);
|
const verifier = this.props.request.beginKeyVerification(verificationMethods.SAS);
|
||||||
const IncomingSasDialog = sdk.getComponent('views.dialogs.IncomingSasDialog');
|
const IncomingSasDialog = sdk.getComponent('views.dialogs.IncomingSasDialog');
|
||||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {verifier});
|
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||||
|
verifier,
|
||||||
|
}, null, /* priority = */ false, /* static = */ true);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -857,9 +857,14 @@
|
||||||
" (unsupported)": " (unsupported)",
|
" (unsupported)": " (unsupported)",
|
||||||
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.",
|
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.",
|
||||||
"Ongoing conference call%(supportedText)s.": "Ongoing conference call%(supportedText)s.",
|
"Ongoing conference call%(supportedText)s.": "Ongoing conference call%(supportedText)s.",
|
||||||
|
"This user has not verified all of their devices.": "This user has not verified all of their devices.",
|
||||||
|
"You have not verified this user. This user has verified all of their devices.": "You have not verified this user. This user has verified all of their devices.",
|
||||||
|
"You have verified this user. This user has verified all of their devices.": "You have verified this user. This user has verified all of their devices.",
|
||||||
|
"Some users in this encrypted room are not verified by you or they have not verified their own devices.": "Some users in this encrypted room are not verified by you or they have not verified their own devices.",
|
||||||
|
"All users in this encrypted room are verified by you and they have verified their own devices.": "All users in this encrypted room are verified by you and they have verified their own devices.",
|
||||||
"Some devices for this user are not trusted": "Some devices for this user are not trusted",
|
"Some devices for this user are not trusted": "Some devices for this user are not trusted",
|
||||||
"Some devices in this encrypted room are not trusted": "Some devices in this encrypted room are not trusted",
|
|
||||||
"All devices for this user are trusted": "All devices for this user are trusted",
|
"All devices for this user are trusted": "All devices for this user are trusted",
|
||||||
|
"Some devices in this encrypted room are not trusted": "Some devices in this encrypted room are not trusted",
|
||||||
"All devices in this encrypted room are trusted": "All devices in this encrypted room are trusted",
|
"All devices in this encrypted room are trusted": "All devices in this encrypted room are trusted",
|
||||||
"Edit message": "Edit message",
|
"Edit message": "Edit message",
|
||||||
"This event could not be displayed": "This event could not be displayed",
|
"This event could not be displayed": "This event could not be displayed",
|
||||||
|
|
Loading…
Reference in a new issue