From d94553bafc09c531f18c5cc61e4b953b96b22d0e Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 14 Sep 2018 17:08:02 +0100 Subject: [PATCH] UI for whether the key backup is enabled or not --- res/css/_components.scss | 1 + res/css/views/settings/_KeyBackupPanel.scss | 32 +++++++++ .../views/settings/KeyBackupPanel.js | 67 ++++++++++++++++++- src/i18n/strings/en_EN.json | 15 +++-- 4 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 res/css/views/settings/_KeyBackupPanel.scss diff --git a/res/css/_components.scss b/res/css/_components.scss index e8a8877d62..6ce8d6efa9 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -109,6 +109,7 @@ @import "./views/rooms/_TopUnreadMessagesBar.scss"; @import "./views/settings/_DevicesPanel.scss"; @import "./views/settings/_IntegrationsManager.scss"; +@import "./views/settings/_KeyBackupPanel.scss"; @import "./views/settings/_Notifications.scss"; @import "./views/voip/_CallView.scss"; @import "./views/voip/_IncomingCallbox.scss"; diff --git a/res/css/views/settings/_KeyBackupPanel.scss b/res/css/views/settings/_KeyBackupPanel.scss new file mode 100644 index 0000000000..1bcc0ab10d --- /dev/null +++ b/res/css/views/settings/_KeyBackupPanel.scss @@ -0,0 +1,32 @@ +/* +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. +*/ + +.mx_KeyBackupPanel_sigValid, .mx_KeyBackupPanel_sigInvalid, +.mx_KeyBackupPanel_deviceVerified, .mx_KeyBackupPanel_deviceNotVerified { + font-weight: bold; +} + +.mx_KeyBackupPanel_sigValid, .mx_KeyBackupPanel_deviceVerified { + color: $e2e-verified-color; +} + +.mx_KeyBackupPanel_sigInvalid, .mx_KeyBackupPanel_deviceNotVerified { + color: $e2e-warning-color; +} + +.mx_KeyBackupPanel_deviceName { + font-style: italic; +} diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/KeyBackupPanel.js index 3b452e77f8..1794b94792 100644 --- a/src/components/views/settings/KeyBackupPanel.js +++ b/src/components/views/settings/KeyBackupPanel.js @@ -28,6 +28,8 @@ export default class KeyBackupPanel extends React.Component { this._startNewBackup = this._startNewBackup.bind(this); this._deleteBackup = this._deleteBackup.bind(this); + this._verifyDevice = this._verifyDevice.bind(this); + this._onKeyBackupStatus = this._onKeyBackupStatus.bind(this); this._unmounted = false; this.state = { @@ -35,20 +37,33 @@ export default class KeyBackupPanel extends React.Component { error: null, backupInfo: null, }; + } + + componentWillMount() { this._loadBackupStatus(); + + MatrixClientPeg.get().on('keyBackupStatus', this._onKeyBackupStatus); } componentWillUnmount() { this._unmounted = true; + + MatrixClientPeg.get().removeListener('keyBackupStatus', this._onKeyBackupStatus); + } + + _onKeyBackupStatus() { + this._loadBackupStatus(); } async _loadBackupStatus() { this.setState({loading: true}); try { const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); + const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo); if (this._unmounted) return; this.setState({ backupInfo, + backupSigStatus, loading: false, }); } catch (e) { @@ -92,6 +107,19 @@ export default class KeyBackupPanel extends React.Component { } + _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"); @@ -112,10 +140,47 @@ export default class KeyBackupPanel extends React.Component { // XXX: display why and how to fix it clientBackupStatus = _t("This device is not uploading keys to this backup", {}, {b: x => {x}}); } + + let backupSigStatuses = this.state.backupSigStatus.sigs.map((sig, i) => { + const sigStatSub = { + validity: sub => {sub}, + verify: sub => {sub}, + device: sub => {sig.device.getDisplayName()}, + }; + let sigStat; + if (sig.valid && sig.device.isVerified()) { + sigStat = _t("Backup has a valid signature from verified device x", {}, sigStatSub); + } else if (sig.valid && !sig.device.isVerified()) { + sigStat = _t("Backup has a valid signature from unverified device ", {}, sigStatSub); + } else if (!sig.valid && sig.device.isVerified()) { + sigStat = _t("Backup has an invalid signature from verified device ", {}, sigStatSub); + } else if (!sig.valid && !sig.device.isVerified()) { + sigStat = _t("Backup has an invalid signature from unverified device ", {}, sigStatSub); + } + + let verifyButton; + if (!sig.device.isVerified()) { + verifyButton =

+ { _t("Verify...") } +
; + } + + return
+ {sigStat} + {verifyButton} +
; + }); + if (this.state.backupSigStatus.sigs.length === 0) { + backupSigStatuses = _t("Backup is not signed by any of your devices"); + } + return
{_t("Backup version: ")}{this.state.backupInfo.version}
{_t("Algorithm: ")}{this.state.backupInfo.algorithm}
- {clientBackupStatus}

+ {clientBackupStatus}
+
{backupSigStatuses}

+
{ _t("Delete backup") } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 16695c8ec8..acad2b7e33 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -304,6 +304,11 @@ "Unable to load key backup status": "Unable to load key backup status", "This device is uploading keys to this backup": "This device is uploading keys to this backup", "This device is not uploading keys to this backup": "This device is not uploading keys to this backup", + "Backup has a valid signature from verified device x": "Backup has a valid signature from verified device x", + "Backup has a valid signature from unverified device ": "Backup has a valid signature from unverified device ", + "Backup has an invalid signature from verified device ": "Backup has an invalid signature from verified device ", + "Backup has an invalid signature from unverified device ": "Backup has an invalid signature from unverified device ", + "Backup is not signed by any of your devices": "Backup is not signed by any of your devices", "Backup version: ": "Backup version: ", "Algorithm: ": "Algorithm: ", "No backup is present": "No backup is present", @@ -937,6 +942,10 @@ "Share Room Message": "Share Room Message", "Link to selected message": "Link to selected message", "COPY": "COPY", + "Restore encryption keys": "Restore encryption keys", + "Verify this device": "Verify this device", + "Restore from online backup": "Restore from online backup", + "Restore from offline backup": "Restore from offline backup", "You are currently blacklisting unverified devices; to send messages to these devices you must verify them.": "You are currently blacklisting unverified devices; to send messages to these devices you must verify them.", "We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.": "We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.", "Room contains unknown devices": "Room contains unknown devices", @@ -957,12 +966,6 @@ "Creating backup...": "Creating backup...", "Uploading keys...": "Uploading keys...", "Create Key Backup": "Create Key Backup", - "Backup encryption keys on your server?": "Backup encryption keys on your server?", - "Generate recovery key and enable online backups": "Generate recovery key and enable online backups", - "Restore encryption keys": "Restore encryption keys", - "Verify this device": "Verify this device", - "Restore from online backup": "Restore from online backup", - "Restore from offline backup": "Restore from offline backup", "Private Chat": "Private Chat", "Public Chat": "Public Chat", "Custom": "Custom",