mirror of
https://github.com/element-hq/element-web
synced 2024-11-28 20:38:55 +03:00
Merge pull request #4041 from matrix-org/foldleft/12221-reset-cross-signing
Button to reset cross-signing and SSSS keys
This commit is contained in:
commit
d47d13256f
5 changed files with 107 additions and 8 deletions
|
@ -148,18 +148,21 @@ export const crossSigningCallbacks = {
|
||||||
*
|
*
|
||||||
* @param {Function} [func] An operation to perform once secret storage has been
|
* @param {Function} [func] An operation to perform once secret storage has been
|
||||||
* bootstrapped. Optional.
|
* bootstrapped. Optional.
|
||||||
|
* @param {bool} [force] Reset secret storage even if it's already set up
|
||||||
*/
|
*/
|
||||||
export async function accessSecretStorage(func = async () => { }) {
|
export async function accessSecretStorage(func = async () => { }, force = false) {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
secretStorageBeingAccessed = true;
|
secretStorageBeingAccessed = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!await cli.hasSecretStorageKey()) {
|
if (!await cli.hasSecretStorageKey() || force) {
|
||||||
// This dialog calls bootstrap itself after guiding the user through
|
// This dialog calls bootstrap itself after guiding the user through
|
||||||
// passphrase creation.
|
// passphrase creation.
|
||||||
const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '',
|
const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '',
|
||||||
import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"),
|
import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"),
|
||||||
null, null, /* priority = */ false, /* static = */ true,
|
{
|
||||||
|
force,
|
||||||
|
},
|
||||||
|
null, /* priority = */ false, /* static = */ true,
|
||||||
);
|
);
|
||||||
const [confirmed] = await finished;
|
const [confirmed] = await finished;
|
||||||
if (!confirmed) {
|
if (!confirmed) {
|
||||||
|
|
|
@ -55,10 +55,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
hasCancel: PropTypes.bool,
|
hasCancel: PropTypes.bool,
|
||||||
accountPassword: PropTypes.string,
|
accountPassword: PropTypes.string,
|
||||||
|
force: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
hasCancel: true,
|
hasCancel: true,
|
||||||
|
force: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -107,7 +109,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo)
|
MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo)
|
||||||
);
|
);
|
||||||
|
|
||||||
const phase = backupInfo ? PHASE_MIGRATE : PHASE_PASSPHRASE;
|
const { force } = this.props;
|
||||||
|
const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_PASSPHRASE;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
phase,
|
phase,
|
||||||
|
@ -219,12 +222,15 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
|
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
|
const { force } = this.props;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await cli.bootstrapSecretStorage({
|
await cli.bootstrapSecretStorage({
|
||||||
|
setupNewSecretStorage: force,
|
||||||
authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
|
authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
|
||||||
createSecretStorageKey: async () => this._keyInfo,
|
createSecretStorageKey: async () => this._keyInfo,
|
||||||
keyBackupInfo: this.state.backupInfo,
|
keyBackupInfo: this.state.backupInfo,
|
||||||
setupNewKeyBackup: !this.state.backupInfo && this.state.useKeyBackup,
|
setupNewKeyBackup: force || !this.state.backupInfo && this.state.useKeyBackup,
|
||||||
});
|
});
|
||||||
this.setState({
|
this.setState({
|
||||||
phase: PHASE_DONE,
|
phase: PHASE_DONE,
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
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 {_t} from "../../../languageHandler";
|
||||||
|
import * as sdk from "../../../index";
|
||||||
|
|
||||||
|
export default class ConfirmDestroyCrossSigningDialog extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
onFinished: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
_onConfirm = () => {
|
||||||
|
this.props.onFinished(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
_onDecline = () => {
|
||||||
|
this.props.onFinished(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseDialog
|
||||||
|
className='mx_ConfirmDestroyCrossSigningDialog'
|
||||||
|
hasCancel={true}
|
||||||
|
onFinished={this.props.onFinished}
|
||||||
|
title={_t("Destroy cross-signing keys?")}>
|
||||||
|
<div className='mx_ConfirmDestroyCrossSigningDialog_content'>
|
||||||
|
<p>
|
||||||
|
{_t(
|
||||||
|
"Deleting cross-signing keys is permanent. " +
|
||||||
|
"Anyone you have verified with will see security alerts. " +
|
||||||
|
"You almost certainly don't want to do this, unless " +
|
||||||
|
"you've lost every device you can cross-sign from.",
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<DialogButtons
|
||||||
|
primaryButton={_t("Clear cross-signing keys")}
|
||||||
|
onPrimaryButtonClick={this._onConfirm}
|
||||||
|
primaryButtonClass="danger"
|
||||||
|
cancelButton={_t("Cancel")}
|
||||||
|
onCancel={this._onDecline}
|
||||||
|
/>
|
||||||
|
</BaseDialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import { accessSecretStorage } from '../../../CrossSigningManager';
|
import { accessSecretStorage } from '../../../CrossSigningManager';
|
||||||
|
import Modal from '../../../Modal';
|
||||||
|
|
||||||
export default class CrossSigningPanel extends React.PureComponent {
|
export default class CrossSigningPanel extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -86,11 +87,12 @@ export default class CrossSigningPanel extends React.PureComponent {
|
||||||
* 2. Access existing secret storage by requesting passphrase and accessing
|
* 2. Access existing secret storage by requesting passphrase and accessing
|
||||||
* cross-signing keys as needed.
|
* cross-signing keys as needed.
|
||||||
* 3. All keys are loaded and there's nothing to do.
|
* 3. All keys are loaded and there's nothing to do.
|
||||||
|
* @param {bool} [force] Bootstrap again even if keys already present
|
||||||
*/
|
*/
|
||||||
_bootstrapSecureSecretStorage = async () => {
|
_bootstrapSecureSecretStorage = async (force=false) => {
|
||||||
this.setState({ error: null });
|
this.setState({ error: null });
|
||||||
try {
|
try {
|
||||||
await accessSecretStorage();
|
await accessSecretStorage(() => undefined, force);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.setState({ error: e });
|
this.setState({ error: e });
|
||||||
console.error("Error bootstrapping secret storage", e);
|
console.error("Error bootstrapping secret storage", e);
|
||||||
|
@ -99,6 +101,19 @@ export default class CrossSigningPanel extends React.PureComponent {
|
||||||
this._getUpdatedStatus();
|
this._getUpdatedStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDestroyStorage = (act) => {
|
||||||
|
if (!act) return;
|
||||||
|
console.log("Destroy secret storage:", act);
|
||||||
|
this._bootstrapSecureSecretStorage(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_destroySecureSecretStorage = () => {
|
||||||
|
const ConfirmDestoryCrossSigningDialog = sdk.getComponent("dialogs.ConfirmDestroyCrossSigningDialog");
|
||||||
|
Modal.createDialog(ConfirmDestoryCrossSigningDialog, {
|
||||||
|
onFinished: this.onDestroyStorage,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
||||||
const {
|
const {
|
||||||
|
@ -142,6 +157,12 @@ export default class CrossSigningPanel extends React.PureComponent {
|
||||||
{_t("Bootstrap cross-signing and secret storage")}
|
{_t("Bootstrap cross-signing and secret storage")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>;
|
</div>;
|
||||||
|
} else {
|
||||||
|
bootstrapButton = <div className="mx_CrossSigningPanel_buttonRow">
|
||||||
|
<AccessibleButton kind="danger" onClick={this._destroySecureSecretStorage}>
|
||||||
|
{_t("Reset cross-signing and secret storage")}
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -558,6 +558,7 @@
|
||||||
"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.",
|
"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 and secret storage are not yet set up.": "Cross-signing and secret storage are not yet set up.",
|
"Cross-signing and secret storage are not yet set up.": "Cross-signing and secret storage are not yet set up.",
|
||||||
"Bootstrap cross-signing and secret storage": "Bootstrap cross-signing and secret storage",
|
"Bootstrap cross-signing and secret storage": "Bootstrap cross-signing and secret storage",
|
||||||
|
"Reset cross-signing and secret storage": "Reset cross-signing and secret storage",
|
||||||
"Cross-signing public keys:": "Cross-signing public keys:",
|
"Cross-signing public keys:": "Cross-signing public keys:",
|
||||||
"in memory": "in memory",
|
"in memory": "in memory",
|
||||||
"not found": "not found",
|
"not found": "not found",
|
||||||
|
@ -1435,6 +1436,9 @@
|
||||||
"Changelog": "Changelog",
|
"Changelog": "Changelog",
|
||||||
"You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)",
|
"You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)",
|
||||||
"Removing…": "Removing…",
|
"Removing…": "Removing…",
|
||||||
|
"Destroy cross-signing keys?": "Destroy cross-signing keys?",
|
||||||
|
"Deleting cross-signing keys is permanent. Anyone you have verified with will see security alerts. You almost certainly don't want to do this, unless you've lost every device you can cross-sign from.": "Deleting cross-signing keys is permanent. Anyone you have verified with will see security alerts. You almost certainly don't want to do this, unless you've lost every device you can cross-sign from.",
|
||||||
|
"Clear cross-signing keys": "Clear cross-signing keys",
|
||||||
"Confirm Removal": "Confirm Removal",
|
"Confirm Removal": "Confirm Removal",
|
||||||
"Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.",
|
"Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.",
|
||||||
"Clear all data in this session?": "Clear all data in this session?",
|
"Clear all data in this session?": "Clear all data in this session?",
|
||||||
|
|
Loading…
Reference in a new issue