Merge pull request #2594 from matrix-org/dbkr/dont_verify_restore

Prompt to restore backup rather than verify
This commit is contained in:
David Baker 2019-02-08 17:49:04 +00:00 committed by GitHub
commit 742af81224
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 104 deletions

View file

@ -38,7 +38,7 @@ export default class RoomRecoveryReminder extends React.PureComponent {
this.state = {
loading: true,
error: null,
unverifiedDevice: null,
backupInfo: null,
};
}
@ -47,10 +47,12 @@ export default class RoomRecoveryReminder extends React.PureComponent {
}
async _loadBackupStatus() {
let backupSigStatus;
try {
const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo);
this.setState({
loading: false,
backupInfo,
});
} catch (e) {
console.log("Unable to fetch key backup status", e);
this.setState({
@ -59,44 +61,20 @@ export default class RoomRecoveryReminder extends React.PureComponent {
});
return;
}
let unverifiedDevice;
for (const sig of backupSigStatus.sigs) {
if (sig.device && !sig.device.isVerified()) {
unverifiedDevice = sig.device;
break;
}
}
this.setState({
loading: false,
unverifiedDevice,
});
}
showSetupDialog = () => {
if (this.state.unverifiedDevice) {
if (this.state.backupInfo) {
// 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,
});
return;
// verified, so restore the backup which will give us the keys from it and
// allow us to trust it (ie. upload keys to it)
const RestoreKeyBackupDialog = sdk.getComponent('dialogs.keybackup.RestoreKeyBackupDialog');
Modal.createTrackedDialog('Restore Backup', '', RestoreKeyBackupDialog, {});
} else {
Modal.createTrackedDialogAsync("Key Backup", "Key Backup",
import("../../../async-components/views/dialogs/keybackup/CreateKeyBackupDialog"),
);
}
// 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"),
);
}
onDontAskAgainClick = () => {
@ -133,53 +111,40 @@ export default class RoomRecoveryReminder extends React.PureComponent {
const AccessibleButton = sdk.getComponent("views.elements.AccessibleButton");
let body;
let primaryCaption = _t("Set up");
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.
} else if (this.state.backupInfo) {
// A key backup exists for this account, but we're not using it.
body = <div>
<p>{_t(
"Secure Message Recovery has been set up on another device: <deviceName></deviceName>",
{},
{
deviceName: () => <i>{this.state.unverifiedDevice.unsigned.device_display_name}</i>,
},
)}</p>
<p>{_t(
"To view your secure message history and ensure you can view new " +
"messages on future devices, verify that device now.",
"Secure Key Backup should be active on all of your devices to avoid " +
"losing access to your encrypted messages.",
)}</p>
</div>;
primaryCaption = _t("Verify device");
} 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.",
"Securely back up your decryption keys to the server to make sure " +
"you'll always be able to read your encrypted messages.",
);
}
return (
<div className="mx_RoomRecoveryReminder">
<div className="mx_RoomRecoveryReminder_header">{_t(
"Secure Message Recovery",
"Don't risk losing your encrypted messages!",
)}</div>
<div className="mx_RoomRecoveryReminder_body">{body}</div>
<div className="mx_RoomRecoveryReminder_buttons">
<AccessibleButton className="mx_RoomRecoveryReminder_button mx_RoomRecoveryReminder_secondary"
onClick={this.onDontAskAgainClick}>
{ _t("Don't ask again") }
</AccessibleButton>
<AccessibleButton className="mx_RoomRecoveryReminder_button"
onClick={this.onSetupClick}>
{primaryCaption}
{_t("Activate Secure Key Backup")}
</AccessibleButton>
<p><AccessibleButton className="mx_RoomRecoveryReminder_secondary mx_linkButton"
onClick={this.onDontAskAgainClick}>
{ _t("No thanks, I'll download a copy of my decryption keys before I log out") }
</AccessibleButton></p>
</div>
</div>
);

View file

@ -27,7 +27,6 @@ export default class KeyBackupPanel extends React.PureComponent {
this._startNewBackup = this._startNewBackup.bind(this);
this._deleteBackup = this._deleteBackup.bind(this);
this._verifyDevice = this._verifyDevice.bind(this);
this._onKeyBackupSessionsRemaining =
this._onKeyBackupSessionsRemaining.bind(this);
this._onKeyBackupStatus = this._onKeyBackupStatus.bind(this);
@ -133,19 +132,6 @@ export default class KeyBackupPanel extends React.PureComponent {
});
}
_verifyDevice(e) {
const device = this.state.backupSigStatus.sigs[e.target.getAttribute('data-sigindex')].device;
const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog');
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
userId: MatrixClientPeg.get().credentials.userId,
device: device,
onFinished: () => {
this._loadBackupStatus();
},
});
}
render() {
const Spinner = sdk.getComponent("elements.Spinner");
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
@ -163,9 +149,8 @@ export default class KeyBackupPanel extends React.PureComponent {
if (MatrixClientPeg.get().getKeyBackupEnabled()) {
clientBackupStatus = _t("This device is using key backup");
} else {
// XXX: display why and how to fix it
clientBackupStatus = _t(
"This device is <b>not</b> using key backup", {},
"This device is <b>not</b> using key backup. Restore the backup to start using it.", {},
{b: x => <b>{x}</b>},
);
}
@ -233,17 +218,8 @@ export default class KeyBackupPanel extends React.PureComponent {
);
}
let verifyButton;
if (sig.device && !sig.device.isVerified()) {
verifyButton = <div><br /><AccessibleButton className="mx_GeneralButton"
onClick={this._verifyDevice} data-sigindex={i}>
{ _t("Verify...") }
</AccessibleButton></div>;
}
return <div key={i}>
{sigStatus}
{verifyButton}
</div>;
});
if (this.state.backupSigStatus.sigs.length === 0) {
@ -256,12 +232,15 @@ export default class KeyBackupPanel extends React.PureComponent {
}
return <div>
<div>{_t("Backup version: ")}{this.state.backupInfo.version}</div>
<div>{_t("Algorithm: ")}{this.state.backupInfo.algorithm}</div>
<div>{clientBackupStatus}</div>
{uploadStatus}
<div>{backupSigStatuses}</div>
<div>{trustedLocally}</div>
<details>
<summary>{_t("Advanced")}</summary>
<div>{_t("Backup version: ")}{this.state.backupInfo.version}</div>
<div>{_t("Algorithm: ")}{this.state.backupInfo.algorithm}</div>
{uploadStatus}
<div>{backupSigStatuses}</div>
<div>{trustedLocally}</div>
</details>
<p>
<AccessibleButton kind="primary" onClick={this._restoreBackup}>
{ _t("Restore backup") }