Show in-room reminder when key backup creating device unverified
If the current device hasn't verified the device that created the account's current key backup version, then the current device is won't use the key backup. This change adjusts an existing in-room reminder to do the right thing for this case by allowing the user to verify the device that created the key backup. Fixes vector-im/riot-web#7902.pull/21833/head
parent
a3778dc822
commit
402f58225f
|
@ -161,6 +161,7 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember);
|
||||
MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership);
|
||||
MatrixClientPeg.get().on("accountData", this.onAccountData);
|
||||
MatrixClientPeg.get().on("crypto.keyBackupStatus", this.onKeyBackupStatus);
|
||||
this._fetchMediaConfig();
|
||||
// Start listening for RoomViewStore updates
|
||||
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
|
||||
|
@ -449,6 +450,7 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().removeListener("Room.myMembership", this.onMyMembership);
|
||||
MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
|
||||
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
||||
MatrixClientPeg.get().removeListener("crypto.keyBackupStatus", this.onKeyBackupStatus);
|
||||
}
|
||||
|
||||
window.removeEventListener('beforeunload', this.onPageUnload);
|
||||
|
@ -618,6 +620,11 @@ module.exports = React.createClass({
|
|||
false,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
onKeyBackupStatus() {
|
||||
// Key backup status changes affect whether the in-room recovery
|
||||
// reminder is displayed.
|
||||
this.forceUpdate();
|
||||
},
|
||||
|
||||
|
|
|
@ -19,13 +19,76 @@ import PropTypes from "prop-types";
|
|||
import sdk from "../../../index";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import Modal from "../../../Modal";
|
||||
import MatrixClientPeg from "../../../MatrixClientPeg";
|
||||
|
||||
export default class RoomRecoveryReminder extends React.PureComponent {
|
||||
static propTypes = {
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
showKeyBackupDialog = () => {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loading: true,
|
||||
error: null,
|
||||
unverifiedDevice: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this._loadBackupStatus();
|
||||
}
|
||||
|
||||
async _loadBackupStatus() {
|
||||
let backupSigStatus;
|
||||
try {
|
||||
const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
|
||||
backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo);
|
||||
} catch (e) {
|
||||
console.log("Unable to fetch key backup status", e);
|
||||
this.setState({
|
||||
loading: false,
|
||||
error: e,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let unverifiedDevice;
|
||||
for (const sig of backupSigStatus.sigs) {
|
||||
if (!sig.device.isVerified()) {
|
||||
unverifiedDevice = sig.device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
loading: false,
|
||||
unverifiedDevice,
|
||||
});
|
||||
}
|
||||
|
||||
showSetupDialog = () => {
|
||||
if (this.state.unverifiedDevice) {
|
||||
// A key backup exists for this account, but the creating device is not
|
||||
// verified, so we'll show the device verify dialog.
|
||||
// TODO: Should change to a restore key backup flow that checks the recovery
|
||||
// passphrase while at the same time also cross-signing the device as well in
|
||||
// a single flow (for cases where a key backup exists but the backup creating
|
||||
// device is unverified). Since we don't have that yet, we'll look for an
|
||||
// unverified device and verify it. Note that this means we won't restore
|
||||
// keys yet; instead we'll only trust the backup for sending our own new keys
|
||||
// to it.
|
||||
const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog');
|
||||
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
|
||||
userId: MatrixClientPeg.get().credentials.userId,
|
||||
device: this.state.unverifiedDevice,
|
||||
onFinished: this.props.onFinished,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// The default case assumes that a key backup doesn't exist for this account, so
|
||||
// we'll show the create key backup flow.
|
||||
Modal.createTrackedDialogAsync("Key Backup", "Key Backup",
|
||||
import("../../../async-components/views/dialogs/keybackup/CreateKeyBackupDialog"),
|
||||
{
|
||||
|
@ -46,29 +109,51 @@ export default class RoomRecoveryReminder extends React.PureComponent {
|
|||
this.props.onFinished(false);
|
||||
},
|
||||
onSetup: () => {
|
||||
this.showKeyBackupDialog();
|
||||
this.showSetupDialog();
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
onSetupClick = () => {
|
||||
this.showKeyBackupDialog();
|
||||
this.showSetupDialog();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.loading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
|
||||
|
||||
let body;
|
||||
if (this.state.error) {
|
||||
body = <div className="error">
|
||||
{_t("Unable to load key backup status")}
|
||||
</div>;
|
||||
} else if (this.state.unverifiedDevice) {
|
||||
// A key backup exists for this account, but the creating device is not
|
||||
// verified.
|
||||
body = _t(
|
||||
"To view your secure message history and ensure you can view new " +
|
||||
"messages on future devices, set up Secure Message Recovery.",
|
||||
);
|
||||
} else {
|
||||
// The default case assumes that a key backup doesn't exist for this account.
|
||||
// (This component doesn't currently check that itself.)
|
||||
body = _t(
|
||||
"If you log out or use another device, you'll lose your " +
|
||||
"secure message history. To prevent this, set up Secure " +
|
||||
"Message Recovery.",
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_RoomRecoveryReminder">
|
||||
<div className="mx_RoomRecoveryReminder_header">{_t(
|
||||
"Secure Message Recovery",
|
||||
)}</div>
|
||||
<div className="mx_RoomRecoveryReminder_body">{_t(
|
||||
"If you log out or use another device, you'll lose your " +
|
||||
"secure message history. To prevent this, set up Secure " +
|
||||
"Message Recovery.",
|
||||
)}</div>
|
||||
<div className="mx_RoomRecoveryReminder_body">{body}</div>
|
||||
<div className="mx_RoomRecoveryReminder_buttons">
|
||||
<AccessibleButton className="mx_RoomRecoveryReminder_button mx_RoomRecoveryReminder_secondary"
|
||||
onClick={this.onDontAskAgainClick}>
|
||||
|
|
|
@ -569,8 +569,9 @@
|
|||
"You are trying to access a room.": "You are trying to access a room.",
|
||||
"<a>Click here</a> to join the discussion!": "<a>Click here</a> to join the discussion!",
|
||||
"This is a preview of this room. Room interactions have been disabled": "This is a preview of this room. Room interactions have been disabled",
|
||||
"Secure Message Recovery": "Secure Message Recovery",
|
||||
"To view your secure message history and ensure you can view new messages on future devices, set up Secure Message Recovery.": "To view your secure message history and ensure you can view new messages on future devices, set up Secure Message Recovery.",
|
||||
"If you log out or use another device, you'll lose your secure message history. To prevent this, set up Secure Message Recovery.": "If you log out or use another device, you'll lose your secure message history. To prevent this, set up Secure Message Recovery.",
|
||||
"Secure Message Recovery": "Secure Message Recovery",
|
||||
"Don't ask again": "Don't ask again",
|
||||
"Set up": "Set up",
|
||||
"To change the room's avatar, you must be a": "To change the room's avatar, you must be a",
|
||||
|
|
Loading…
Reference in New Issue