[CONFLICT CHUNKS] Merge branch 'develop' into travis/sourcemaps-develop

This commit is contained in:
Travis Ralston 2020-01-09 14:15:09 -07:00
commit fde32f13a5
190 changed files with 6185 additions and 2225 deletions

View file

@ -14,7 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
<<<<<<< HEAD
import React from "react";
=======
import {Key} from "../../../Keyboard";
const React = require("react");
>>>>>>> develop
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
@ -22,7 +28,14 @@ import {MatrixClientPeg} from "../../../MatrixClientPeg";
const sdk = require('../../../index');
<<<<<<< HEAD
export default createReactClass({
=======
// XXX: This component is not cross-signing aware.
// https://github.com/vector-im/riot-web/issues/11752 tracks either updating this
// component or taking it out to pasture.
module.exports = createReactClass({
>>>>>>> develop
displayName: 'EncryptedEventDialog',
propTypes: {
@ -84,7 +97,7 @@ export default createReactClass({
},
onKeyDown: function(e) {
if (e.keyCode === 27) { // escape
if (e.key === Key.ESCAPE) {
e.stopPropagation();
e.preventDefault();
this.props.onFinished(false);

View file

@ -1,6 +1,6 @@
/*
Copyright 2018, 2019 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2019, 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.
@ -17,10 +17,19 @@ limitations under the License.
import React from 'react';
import FileSaver from 'file-saver';
<<<<<<< HEAD
import * as sdk from '../../../../index';
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
=======
import PropTypes from 'prop-types';
import sdk from '../../../../index';
import MatrixClientPeg from '../../../../MatrixClientPeg';
>>>>>>> develop
import { scorePassword } from '../../../../utils/PasswordScorer';
import { _t } from '../../../../languageHandler';
import { accessSecretStorage } from '../../../../CrossSigningManager';
import SettingsStore from '../../../../settings/SettingsStore';
const PHASE_PASSPHRASE = 0;
const PHASE_PASSPHRASE_CONFIRM = 1;
@ -48,10 +57,20 @@ function selectText(target) {
* on the server.
*/
export default class CreateKeyBackupDialog extends React.PureComponent {
static propTypes = {
secureSecretStorage: PropTypes.bool,
onFinished: PropTypes.func.isRequired,
}
constructor(props) {
super(props);
this._recoveryKeyNode = null;
this._keyBackupInfo = null;
this._setZxcvbnResultTimeout = null;
this.state = {
secureSecretStorage: props.secureSecretStorage,
phase: PHASE_PASSPHRASE,
passPhrase: '',
passPhraseConfirm: '',
@ -60,12 +79,25 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
zxcvbnResult: null,
setPassPhrase: false,
};
if (this.state.secureSecretStorage === undefined) {
this.state.secureSecretStorage =
SettingsStore.isFeatureEnabled("feature_cross_signing");
}
// If we're using secret storage, skip ahead to the backing up step, as
// `accessSecretStorage` will handle passphrases as needed.
if (this.state.secureSecretStorage) {
this.state.phase = PHASE_BACKINGUP;
}
}
componentWillMount() {
this._recoveryKeyNode = null;
this._keyBackupInfo = null;
this._setZxcvbnResultTimeout = null;
componentDidMount() {
// If we're using secret storage, skip ahead to the backing up step, as
// `accessSecretStorage` will handle passphrases as needed.
if (this.state.secureSecretStorage) {
this._createBackup();
}
}
componentWillUnmount() {
@ -102,15 +134,26 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
}
_createBackup = async () => {
const { secureSecretStorage } = this.state;
this.setState({
phase: PHASE_BACKINGUP,
error: null,
});
let info;
try {
info = await MatrixClientPeg.get().createKeyBackupVersion(
this._keyBackupInfo,
);
if (secureSecretStorage) {
await accessSecretStorage(async () => {
info = await MatrixClientPeg.get().prepareKeyBackupVersion(
null /* random key */,
{ secureSecretStorage: true },
);
info = await MatrixClientPeg.get().createKeyBackupVersion(info);
});
} else {
info = await MatrixClientPeg.get().createKeyBackupVersion(
this._keyBackupInfo,
);
}
await MatrixClientPeg.get().scheduleAllGroupSessionsForBackup();
this.setState({
phase: PHASE_DONE,

View file

@ -1,5 +1,6 @@
/*
Copyright 2018-2019 New Vector Ltd
Copyright 2018, 2019 New Vector Ltd
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.
@ -40,9 +41,11 @@ export default class NewRecoveryMethodDialog extends React.PureComponent {
onSetupClick = async () => {
const RestoreKeyBackupDialog = sdk.getComponent('dialogs.keybackup.RestoreKeyBackupDialog');
Modal.createTrackedDialog('Restore Backup', '', RestoreKeyBackupDialog, {
onFinished: this.props.onFinished,
});
Modal.createTrackedDialog(
'Restore Backup', '', RestoreKeyBackupDialog, {
onFinished: this.props.onFinished,
}, null, /* priority = */ false, /* static = */ true,
);
}
render() {

View file

@ -1,5 +1,6 @@
/*
Copyright 2019 New Vector Ltd
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.
@ -35,6 +36,7 @@ export default class RecoveryMethodRemovedDialog extends React.PureComponent {
this.props.onFinished();
Modal.createTrackedDialogAsync("Key Backup", "Key Backup",
import("./CreateKeyBackupDialog"),
null, null, /* priority = */ false, /* static = */ true,
);
}

View file

@ -23,13 +23,15 @@ import FileSaver from 'file-saver';
import { _t } from '../../../../languageHandler';
import Modal from '../../../../Modal';
const PHASE_PASSPHRASE = 0;
const PHASE_PASSPHRASE_CONFIRM = 1;
const PHASE_SHOWKEY = 2;
const PHASE_KEEPITSAFE = 3;
const PHASE_STORING = 4;
const PHASE_DONE = 5;
const PHASE_OPTOUT_CONFIRM = 6;
const PHASE_LOADING = 0;
const PHASE_MIGRATE = 1;
const PHASE_PASSPHRASE = 2;
const PHASE_PASSPHRASE_CONFIRM = 3;
const PHASE_SHOWKEY = 4;
const PHASE_KEEPITSAFE = 5;
const PHASE_STORING = 6;
const PHASE_DONE = 7;
const PHASE_OPTOUT_CONFIRM = 8;
const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc.
const PASSPHRASE_FEEDBACK_DELAY = 500; // How long after keystroke to offer passphrase feedback, ms.
@ -58,7 +60,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
this._setZxcvbnResultTimeout = null;
this.state = {
phase: PHASE_PASSPHRASE,
phase: PHASE_LOADING,
passPhrase: '',
passPhraseConfirm: '',
copied: false,
@ -66,6 +68,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
zxcvbnResult: null,
setPassPhrase: false,
};
this._fetchBackupInfo();
}
componentWillUnmount() {
@ -74,10 +78,23 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
}
}
async _fetchBackupInfo() {
const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
this.setState({
phase: backupInfo ? PHASE_MIGRATE: PHASE_PASSPHRASE,
backupInfo,
});
}
_collectRecoveryKeyNode = (n) => {
this._recoveryKeyNode = n;
}
_onMigrateNextClick = () => {
this._bootstrapSecretStorage();
}
_onCopyClick = () => {
selectText(this._recoveryKeyNode);
const successful = document.execCommand('copy');
@ -125,6 +142,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
}
},
createSecretStorageKey: async () => this._keyInfo,
keyBackupInfo: this.state.backupInfo,
});
this.setState({
phase: PHASE_DONE,
@ -250,6 +268,27 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
return this.state.zxcvbnResult && this.state.zxcvbnResult.score >= PASSWORD_MIN_SCORE;
}
_renderPhaseMigrate() {
// TODO: This is a temporary screen so people who have the labs flag turned on and
// click the button are aware they're making a change to their account.
// Once we're confident enough in this (and it's supported enough) we can do
// it automatically.
// https://github.com/vector-im/riot-web/issues/11696
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return <div>
<p>{_t(
"Secret Storage will be set up using your existing key backup details." +
"Your secret storage passphrase and recovery key will be the same as " +
" they were for your key backup",
)}</p>
<DialogButtons primaryButton={_t('Next')}
onPrimaryButtonClick={this._onMigrateNextClick}
hasCancel={true}
onCancel={this._onCancel}
/>
</div>;
}
_renderPhasePassPhrase() {
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
@ -449,7 +488,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
</div>;
}
_renderBusyPhase(text) {
_renderBusyPhase() {
const Spinner = sdk.getComponent('views.elements.Spinner');
return <div>
<Spinner />
@ -488,6 +527,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
_titleForPhase(phase) {
switch (phase) {
case PHASE_MIGRATE:
return _t('Migrate from Key Backup');
case PHASE_PASSPHRASE:
return _t('Secure your encrypted messages with a passphrase');
case PHASE_PASSPHRASE_CONFIRM:
@ -525,6 +566,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
</div>;
} else {
switch (this.state.phase) {
case PHASE_LOADING:
content = this._renderBusyPhase();
break;
case PHASE_MIGRATE:
content = this._renderPhaseMigrate();
break;
case PHASE_PASSPHRASE:
content = this._renderPhasePassPhrase();
break;