Add independent set up / reset actions in Settings

This adds set up and reset actions to each of cross-signing and secure backup
that do separate things, rather than mixing concerns together. (It's temporarily
still a bit of lie for backup, as more changes are needed to stop resetting
cross-signing as well.)
This commit is contained in:
J. Ryan Stinnett 2020-09-08 18:01:56 +01:00
parent aae68f7d1a
commit bbe2084f66
6 changed files with 90 additions and 45 deletions

View file

@ -34,6 +34,10 @@ limitations under the License.
.mx_SecureBackupPanel_buttonRow {
margin: 1em 0;
:nth-child(n + 1) {
margin-inline-end: 10px;
}
}
.mx_SecureBackupPanel_statusList {

View file

@ -250,7 +250,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
'Cross-signing keys dialog', '', InteractiveAuthDialog,
{
title: _t("Setting up keys"),
matrixClient: MatrixClientPeg.get(),
matrixClient: cli,
makeRequest,
},
);

View file

@ -280,6 +280,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
const { forceReset } = this.props;
try {
// JRS: In an upcoming change, the cross-signing steps will be
// removed from here and this will instead be about secret storage
// only.
if (forceReset) {
console.log("Forcing cross-signing and secret storage reset");
await cli.bootstrapSecretStorage({

View file

@ -19,9 +19,9 @@ import React from 'react';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import { _t } from '../../../languageHandler';
import * as sdk from '../../../index';
import { accessSecretStorage } from '../../../SecurityManager';
import Modal from '../../../Modal';
import Spinner from '../elements/Spinner';
import InteractiveAuthDialog from '../dialogs/InteractiveAuthDialog';
export default class CrossSigningPanel extends React.PureComponent {
constructor(props) {
@ -66,7 +66,7 @@ export default class CrossSigningPanel extends React.PureComponent {
};
_onBootstrapClick = () => {
this._bootstrapSecureSecretStorage(false);
this._bootstrapCrossSigning({ forceReset: false });
};
onStatusChanged = () => {
@ -99,35 +99,50 @@ export default class CrossSigningPanel extends React.PureComponent {
}
/**
* Bootstrapping secret storage may take one of these paths:
* 1. Create secret storage from a passphrase and store cross-signing keys
* in secret storage.
* Bootstrapping cross-signing take one of these paths:
* 1. Create cross-signing keys locally and store in secret storage (if it
* already exists on the account).
* 2. Access existing secret storage by requesting passphrase and accessing
* cross-signing keys as needed.
* 3. All keys are loaded and there's nothing to do.
* @param {bool} [forceReset] Bootstrap again even if keys already present
*/
_bootstrapSecureSecretStorage = async (forceReset=false) => {
_bootstrapCrossSigning = async ({ forceReset = false }) => {
this.setState({ error: null });
try {
await accessSecretStorage(() => undefined, forceReset);
const cli = MatrixClientPeg.get();
await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: async (makeRequest) => {
const { finished } = Modal.createTrackedDialog(
'Cross-signing keys dialog', '', InteractiveAuthDialog,
{
title: _t("Setting up keys"),
matrixClient: cli,
makeRequest,
},
);
const [confirmed] = await finished;
if (!confirmed) {
throw new Error("Cross-signing key upload auth canceled");
}
},
setupNewCrossSigning: forceReset,
});
} catch (e) {
this.setState({ error: e });
console.error("Error bootstrapping secret storage", e);
console.error("Error bootstrapping cross-signing", e);
}
if (this._unmounted) return;
this._getUpdatedStatus();
}
onDestroyStorage = (act) => {
if (!act) return;
this._bootstrapSecureSecretStorage(true);
}
_destroySecureSecretStorage = () => {
_resetCrossSigning = () => {
const ConfirmDestroyCrossSigningDialog = sdk.getComponent("dialogs.ConfirmDestroyCrossSigningDialog");
Modal.createDialog(ConfirmDestroyCrossSigningDialog, {
onFinished: this.onDestroyStorage,
onFinished: (act) => {
if (!act) return;
this._bootstrapCrossSigning({ forceReset: true });
},
});
}
@ -184,8 +199,8 @@ export default class CrossSigningPanel extends React.PureComponent {
if (keysExistAnywhere) {
resetButton = (
<div className="mx_CrossSigningPanel_buttonRow">
<AccessibleButton kind="danger" onClick={this._destroySecureSecretStorage}>
{_t("Reset cross-signing and secret storage")}
<AccessibleButton kind="danger" onClick={this._resetCrossSigning}>
{_t("Reset")}
</AccessibleButton>
</div>
);
@ -197,7 +212,7 @@ export default class CrossSigningPanel extends React.PureComponent {
bootstrapButton = (
<div className="mx_CrossSigningPanel_buttonRow">
<AccessibleButton kind="primary" onClick={this._onBootstrapClick}>
{_t("Bootstrap cross-signing and secret storage")}
{_t("Set up")}
</AccessibleButton>
</div>
);

View file

@ -25,6 +25,7 @@ import Spinner from '../elements/Spinner';
import AccessibleButton from '../elements/AccessibleButton';
import QuestionDialog from '../dialogs/QuestionDialog';
import RestoreKeyBackupDialog from '../dialogs/keybackup/RestoreKeyBackupDialog';
import { accessSecretStorage } from '../../../SecurityManager';
export default class SecureBackupPanel extends React.PureComponent {
constructor(props) {
@ -184,6 +185,19 @@ export default class SecureBackupPanel extends React.PureComponent {
);
}
_resetSecretStorage = async () => {
this.setState({ error: null });
try {
await accessSecretStorage(() => { }, /* forceReset = */ true);
} catch (e) {
console.error("Error resetting secret storage", e);
if (this._unmounted) return;
this.setState({ error: e });
}
if (this._unmounted) return;
this._loadBackupStatus();
}
render() {
const {
loading,
@ -201,7 +215,7 @@ export default class SecureBackupPanel extends React.PureComponent {
let statusDescription;
let extraDetailsTableRows;
let extraDetails;
let actions;
let actions = [];
if (error) {
statusDescription = (
<div className="error">
@ -335,13 +349,6 @@ export default class SecureBackupPanel extends React.PureComponent {
trustedLocally = _t("This backup is trusted because it has been restored on this session");
}
let deleteBackupButton;
if (!isSecureBackupRequired()) {
deleteBackupButton = <AccessibleButton kind="danger" onClick={this._deleteBackup}>
{_t("Delete Backup")}
</AccessibleButton>;
}
extraDetailsTableRows = <>
<tr>
<td>{_t("Backup version:")}</td>
@ -359,14 +366,19 @@ export default class SecureBackupPanel extends React.PureComponent {
<div>{trustedLocally}</div>
</>;
actions = (
<div className="mx_SecureBackupPanel_buttonRow">
<AccessibleButton kind="primary" onClick={this._restoreBackup}>
{restoreButtonCaption}
</AccessibleButton>&nbsp;&nbsp;&nbsp;
{deleteBackupButton}
</div>
actions.push(
<AccessibleButton kind="primary" onClick={this._restoreBackup}>
{restoreButtonCaption}
</AccessibleButton>,
);
if (!isSecureBackupRequired()) {
actions.push(
<AccessibleButton kind="danger" onClick={this._deleteBackup}>
{_t("Delete Backup")}
</AccessibleButton>,
);
}
} else {
statusDescription = <>
<p>{_t(
@ -375,12 +387,18 @@ export default class SecureBackupPanel extends React.PureComponent {
)}</p>
<p>{_t("Back up your keys before signing out to avoid losing them.")}</p>
</>;
actions = (
<div className="mx_SecureBackupPanel_buttonRow">
<AccessibleButton kind="primary" onClick={this._startNewBackup}>
{_t("Start using Key Backup")}
</AccessibleButton>
</div>
actions.push(
<AccessibleButton kind="primary" onClick={this._startNewBackup}>
{_t("Set up")}
</AccessibleButton>,
);
}
if (secretStorageKeyInAccount) {
actions.push(
<AccessibleButton kind="danger" onClick={this._resetSecretStorage}>
{_t("Reset")}
</AccessibleButton>,
);
}
@ -394,6 +412,13 @@ export default class SecureBackupPanel extends React.PureComponent {
}
}
let actionRow;
if (actions.length) {
actionRow = <div className="mx_SecureBackupPanel_buttonRow">
{actions}
</div>;
}
return (
<div>
<p>{_t(
@ -430,7 +455,7 @@ export default class SecureBackupPanel extends React.PureComponent {
</tbody></table>
{extraDetails}
</details>
{actions}
{actionRow}
</div>
);
}

View file

@ -648,8 +648,7 @@
"Cross-signing is ready for use.": "Cross-signing is ready for use.",
"Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.",
"Cross-signing is not set up.": "Cross-signing is not set up.",
"Reset cross-signing and secret storage": "Reset cross-signing and secret storage",
"Bootstrap cross-signing and secret storage": "Bootstrap cross-signing and secret storage",
"Reset": "Reset",
"Cross-signing public keys:": "Cross-signing public keys:",
"in memory": "in memory",
"not found": "not found",
@ -748,7 +747,6 @@
"Algorithm:": "Algorithm:",
"Your keys are <b>not being backed up from this session</b>.": "Your keys are <b>not being backed up from this session</b>.",
"Back up your keys before signing out to avoid losing them.": "Back up your keys before signing out to avoid losing them.",
"Start using Key Backup": "Start using Key Backup",
"well formed": "well formed",
"unexpected type": "unexpected type",
"Back up your encryption keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Recovery Key.": "Back up your encryption keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Recovery Key.",
@ -948,7 +946,6 @@
"Uploaded sound": "Uploaded sound",
"Sounds": "Sounds",
"Notification sound": "Notification sound",
"Reset": "Reset",
"Set a new custom sound": "Set a new custom sound",
"Browse": "Browse",
"Change room avatar": "Change room avatar",
@ -1173,6 +1170,7 @@
"%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.",
"Try again later, or ask a room admin to check if you have access.": "Try again later, or ask a room admin to check if you have access.",
"%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please <issueLink>submit a bug report</issueLink>.": "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please <issueLink>submit a bug report</issueLink>.",
"Start using Key Backup": "Start using Key Backup",
"Never lose encrypted messages": "Never lose encrypted messages",
"Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.",
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Securely back up your keys to avoid losing them. <a>Learn more.</a>",