Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
f00af760ec
10 changed files with 186 additions and 14 deletions
|
@ -92,25 +92,33 @@ export default React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
_createBackup: function() {
|
||||
_createBackup: async function() {
|
||||
this.setState({
|
||||
phase: PHASE_BACKINGUP,
|
||||
error: null,
|
||||
});
|
||||
this._createBackupPromise = MatrixClientPeg.get().createKeyBackupVersion(
|
||||
this._keyBackupInfo,
|
||||
).then((info) => {
|
||||
return MatrixClientPeg.get().backupAllGroupSessions(info.version);
|
||||
}).then(() => {
|
||||
let info;
|
||||
try {
|
||||
info = await MatrixClientPeg.get().createKeyBackupVersion(
|
||||
this._keyBackupInfo,
|
||||
);
|
||||
await MatrixClientPeg.get().backupAllGroupSessions(info.version);
|
||||
this.setState({
|
||||
phase: PHASE_DONE,
|
||||
});
|
||||
}).catch(e => {
|
||||
} catch (e) {
|
||||
console.log("Error creating key backup", e);
|
||||
// TODO: If creating a version succeeds, but backup fails, should we
|
||||
// delete the version, disable backup, or do nothing? If we just
|
||||
// disable without deleting, we'll enable on next app reload since
|
||||
// it is trusted.
|
||||
if (info) {
|
||||
MatrixClientPeg.get().deleteKeyBackupVersion(info.version);
|
||||
}
|
||||
this.setState({
|
||||
error: e,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_onCancel: function() {
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright 2018 New Vector Ltd
|
||||
|
||||
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 sdk from "../../../../index";
|
||||
import MatrixClientPeg from '../../../../MatrixClientPeg';
|
||||
import dis from "../../../../dispatcher";
|
||||
import { _t } from "../../../../languageHandler";
|
||||
import Modal from "../../../../Modal";
|
||||
|
||||
export default class NewRecoveryMethodDialog extends React.PureComponent {
|
||||
static propTypes = {
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
onGoToSettingsClick = () => {
|
||||
this.props.onFinished();
|
||||
dis.dispatch({ action: 'view_user_settings' });
|
||||
}
|
||||
|
||||
onSetupClick = async() => {
|
||||
// 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. 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.
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
let unverifiedDevice;
|
||||
for (const sig of backupSigStatus.sigs) {
|
||||
if (!sig.device.isVerified()) {
|
||||
unverifiedDevice = sig.device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!unverifiedDevice) {
|
||||
console.log("Unable to find a device to verify.");
|
||||
return;
|
||||
}
|
||||
|
||||
const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog');
|
||||
Modal.createTrackedDialog('Device Verify Dialog', '', DeviceVerifyDialog, {
|
||||
userId: MatrixClientPeg.get().credentials.userId,
|
||||
device: unverifiedDevice,
|
||||
onFinished: this.props.onFinished,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const BaseDialog = sdk.getComponent("views.dialogs.BaseDialog");
|
||||
const DialogButtons = sdk.getComponent("views.elements.DialogButtons");
|
||||
const title = <span className="mx_NewRecoveryMethodDialog_title">
|
||||
{_t("New Recovery Method")}
|
||||
</span>;
|
||||
|
||||
return (
|
||||
<BaseDialog className="mx_NewRecoveryMethodDialog"
|
||||
onFinished={this.props.onFinished}
|
||||
title={title}
|
||||
hasCancel={false}
|
||||
>
|
||||
<div>
|
||||
<p>{_t(
|
||||
"A new recovery passphrase and key for Secure " +
|
||||
"Messages has been detected.",
|
||||
)}</p>
|
||||
<p>{_t(
|
||||
"Setting up Secure Messages on this device " +
|
||||
"will re-encrypt this device's message history with " +
|
||||
"the new recovery method.",
|
||||
)}</p>
|
||||
<p className="warning">{_t(
|
||||
"If you didn't set the new recovery method, an " +
|
||||
"attacker may be trying to access your account. " +
|
||||
"Change your account password and set a new recovery " +
|
||||
"method immediately in Settings.",
|
||||
)}</p>
|
||||
<DialogButtons
|
||||
primaryButton={_t("Set up Secure Messages")}
|
||||
onPrimaryButtonClick={this.onSetupClick}
|
||||
cancelButton={_t("Go to Settings")}
|
||||
onCancel={this.onGoToSettingsClick}
|
||||
/>
|
||||
</div>
|
||||
</BaseDialog>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1430,6 +1430,11 @@ export default React.createClass({
|
|||
break;
|
||||
}
|
||||
});
|
||||
cli.on("crypto.keyBackupFailed", () => {
|
||||
Modal.createTrackedDialogAsync('New Recovery Method', 'New Recovery Method',
|
||||
import('../../async-components/views/dialogs/keybackup/NewRecoveryMethodDialog'),
|
||||
);
|
||||
});
|
||||
|
||||
// Fire the tinter right on startup to ensure the default theme is applied
|
||||
// A later sync can/will correct the tint to be the right value for the user
|
||||
|
|
|
@ -57,8 +57,7 @@ export default React.createClass({
|
|||
className: PropTypes.string,
|
||||
|
||||
// Title for the dialog.
|
||||
// (could probably actually be something more complicated than a string if desired)
|
||||
title: PropTypes.string.isRequired,
|
||||
title: PropTypes.node.isRequired,
|
||||
|
||||
// children should be the content of the dialog
|
||||
children: PropTypes.node,
|
||||
|
|
|
@ -154,6 +154,7 @@ export default class KeyBackupPanel extends React.Component {
|
|||
}
|
||||
|
||||
let backupSigStatuses = this.state.backupSigStatus.sigs.map((sig, i) => {
|
||||
const deviceName = sig.device.getDisplayName() || sig.device.deviceId;
|
||||
const sigStatusSubstitutions = {
|
||||
validity: sub =>
|
||||
<span className={sig.valid ? 'mx_KeyBackupPanel_sigValid' : 'mx_KeyBackupPanel_sigInvalid'}>
|
||||
|
@ -163,7 +164,7 @@ export default class KeyBackupPanel extends React.Component {
|
|||
<span className={sig.device.isVerified() ? 'mx_KeyBackupPanel_deviceVerified' : 'mx_KeyBackupPanel_deviceNotVerified'}>
|
||||
{sub}
|
||||
</span>,
|
||||
device: sub => <span className="mx_KeyBackupPanel_deviceName">{sig.device.getDisplayName()}</span>,
|
||||
device: sub => <span className="mx_KeyBackupPanel_deviceName">{deviceName}</span>,
|
||||
};
|
||||
let sigStatus;
|
||||
if (sig.device.getFingerprint() === MatrixClientPeg.get().getDeviceEd25519Key()) {
|
||||
|
@ -174,7 +175,7 @@ export default class KeyBackupPanel extends React.Component {
|
|||
} else if (sig.valid && sig.device.isVerified()) {
|
||||
sigStatus = _t(
|
||||
"Backup has a <validity>valid</validity> signature from " +
|
||||
"<verify>verified</verify> device <device>x</device>",
|
||||
"<verify>verified</verify> device <device></device>",
|
||||
{}, sigStatusSubstitutions,
|
||||
);
|
||||
} else if (sig.valid && !sig.device.isVerified()) {
|
||||
|
|
|
@ -351,7 +351,7 @@
|
|||
"This device is uploading keys to this backup": "This device is uploading keys to this backup",
|
||||
"This device is <b>not</b> uploading keys to this backup": "This device is <b>not</b> uploading keys to this backup",
|
||||
"Backup has a <validity>valid</validity> signature from this device": "Backup has a <validity>valid</validity> signature from this device",
|
||||
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> device <device>x</device>": "Backup has a <validity>valid</validity> signature from <verify>verified</verify> device <device>x</device>",
|
||||
"Backup has a <validity>valid</validity> signature from <verify>verified</verify> device <device></device>": "Backup has a <validity>valid</validity> signature from <verify>verified</verify> device <device></device>",
|
||||
"Backup has a <validity>valid</validity> signature from <verify>unverified</verify> device <device></device>": "Backup has a <validity>valid</validity> signature from <verify>unverified</verify> device <device></device>",
|
||||
"Backup has an <validity>invalid</validity> signature from <verify>verified</verify> device <device></device>": "Backup has an <validity>invalid</validity> signature from <verify>verified</verify> device <device></device>",
|
||||
"Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> device <device></device>": "Backup has an <validity>invalid</validity> signature from <verify>unverified</verify> device <device></device>",
|
||||
|
@ -1401,6 +1401,12 @@
|
|||
"Retry": "Retry",
|
||||
"Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.": "Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.",
|
||||
"If you don't want to set this up now, you can later in Settings.": "If you don't want to set this up now, you can later in Settings.",
|
||||
"New Recovery Method": "New Recovery Method",
|
||||
"A new recovery passphrase and key for Secure Messages has been detected.": "A new recovery passphrase and key for Secure Messages has been detected.",
|
||||
"Setting up Secure Messages on this device will re-encrypt this device's message history with the new recovery method.": "Setting up Secure Messages on this device will re-encrypt this device's message history with the new recovery method.",
|
||||
"If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.",
|
||||
"Set up Secure Messages": "Set up Secure Messages",
|
||||
"Go to Settings": "Go to Settings",
|
||||
"Failed to set direct chat tag": "Failed to set direct chat tag",
|
||||
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
|
||||
"Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue