Implement first screen (recovery key / passphrase choice)

This commit is contained in:
David Baker 2020-06-23 15:04:39 +01:00
parent 086177d808
commit 6ce8584337
7 changed files with 151 additions and 12 deletions

View file

@ -26,20 +26,26 @@ import { promptForBackupPassphrase } from '../../../../CrossSigningManager';
import {copyNode} from "../../../../utils/strings";
import {SSOAuthEntry} from "../../../../components/views/auth/InteractiveAuthEntryComponents";
import PassphraseField from "../../../../components/views/auth/PassphraseField";
import StyledRadioButton from '../../../../components/views/elements/StyledRadioButton';
const PHASE_LOADING = 0;
const PHASE_LOADERROR = 1;
const PHASE_MIGRATE = 2;
const PHASE_PASSPHRASE = 3;
const PHASE_PASSPHRASE_CONFIRM = 4;
const PHASE_SHOWKEY = 5;
const PHASE_KEEPITSAFE = 6;
const PHASE_STORING = 7;
const PHASE_DONE = 8;
const PHASE_CONFIRM_SKIP = 9;
const PHASE_CHOOSE_KEY_PASSPHRASE = 2;
const PHASE_MIGRATE = 3;
const PHASE_PASSPHRASE = 4;
const PHASE_PASSPHRASE_CONFIRM = 5;
const PHASE_SHOWKEY = 6;
const PHASE_KEEPITSAFE = 7;
const PHASE_STORING = 8;
const PHASE_DONE = 9;
const PHASE_CONFIRM_SKIP = 10;
const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc.
// these end up as strings from being values in the radio buttons, so just use strings
const CREATESTORAGE_OPTION_KEY = 'key';
const CREATESTORAGE_OPTION_PASSPHRASE = 'passphrase';
/*
* Walks the user through the process of creating a passphrase to guard Secure
* Secret Storage in account data.
@ -79,6 +85,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
accountPasswordCorrect: null,
// status of the key backup toggle switch
useKeyBackup: true,
passPhraseKeySelected: CREATESTORAGE_OPTION_KEY,
};
this._passphraseField = createRef();
@ -110,7 +118,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
);
const { force } = this.props;
const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_PASSPHRASE;
const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE;
this.setState({
phase,
@ -152,6 +160,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
if (this.state.phase === PHASE_MIGRATE) this._fetchBackupInfo();
}
_onKeyPassphraseChange = e => {
this.setState({
passPhraseKeySelected: e.target.value,
});
}
_collectRecoveryKeyNode = (n) => {
this._recoveryKeyNode = n;
}
@ -162,6 +176,24 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
});
}
_onChooseKeyPassphraseFormSubmit = async () => {
if (this.state.passPhraseKeySelected === CREATESTORAGE_OPTION_KEY) {
this._recoveryKey =
await MatrixClientPeg.get().createRecoveryKeyFromPassphrase();
this.setState({
copied: false,
downloaded: false,
phase: PHASE_SHOWKEY,
});
} else {
this.setState({
copied: false,
downloaded: false,
phase: PHASE_PASSPHRASE,
});
}
}
_onMigrateFormSubmit = (e) => {
e.preventDefault();
if (this.state.backupSigStatus.usable) {
@ -427,6 +459,53 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
});
}
_renderPhaseChooseKeyPassphrase() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return <form onSubmit={this._onChooseKeyPassphraseFormSubmit}>
<p>{_t(
"Safeguard against losing access to encrypted messages & data by " +
"backing up encryption keys on your server.",
)}</p>
<div className="mx_CreateSecretStorageDialog_primaryContainer" role="radiogroup" onChange={this._onKeyPassphraseChange}>
<StyledRadioButton
key={CREATESTORAGE_OPTION_KEY}
value={CREATESTORAGE_OPTION_KEY}
name="keyPassphrase"
checked={this.state.passPhraseKeySelected === CREATESTORAGE_OPTION_KEY}
>
<div className="mx_CreateSecretStorageDialog_optionTitle">
<img className="mx_CreateSecretStorageDialog_optionIcon"
src={require("../../../../../res/img/feather-customised/secure-backup.svg")}
/>
{_t("Generate a Security Key")}
</div>
<div>{_t("Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.")}</div>
</StyledRadioButton>
<StyledRadioButton
key={CREATESTORAGE_OPTION_PASSPHRASE}
value={CREATESTORAGE_OPTION_PASSPHRASE}
name="keyPassphrase"
checked={this.state.passPhraseKeySelected === CREATESTORAGE_OPTION_PASSPHRASE}
>
<div className="mx_CreateSecretStorageDialog_optionTitle">
<img className="mx_CreateSecretStorageDialog_optionIcon"
src={require("../../../../../res/img/feather-customised/secure-phrase.svg")}
/>
{_t("Enter a Security Phrase")}
</div>
<div>{_t("Use a secret phrase only you know, and optionally save a Security Key to use for backup.")}</div>
</StyledRadioButton>
</div>
<DialogButtons
primaryButton={_t("Continue")}
onPrimaryButtonClick={this._onChooseKeyPassphraseFormSubmit}
onCancel={this._onCancel}
hasCancel={true}
/>
</form>;
}
_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.
@ -716,6 +795,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
_titleForPhase(phase) {
switch (phase) {
case PHASE_CHOOSE_KEY_PASSPHRASE:
return _t('Set up Secure backup');
case PHASE_MIGRATE:
return _t('Upgrade your encryption');
case PHASE_PASSPHRASE:
@ -760,6 +841,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
case PHASE_LOADERROR:
content = this._renderPhaseLoadError();
break;
case PHASE_CHOOSE_KEY_PASSPHRASE:
content = this._renderPhaseChooseKeyPassphrase();
break;
case PHASE_MIGRATE:
content = this._renderPhaseMigrate();
break;

View file

@ -42,7 +42,7 @@ export default class StyledRadioButton extends React.PureComponent<IProps, IStat
<input type='radio' disabled={disabled} {...otherProps} />
{/* Used to render the radio button circle */}
<div><div></div></div>
<span>{children}</span>
<div className="mx_RadioButton_content">{children}</div>
<div className="mx_RadioButton_spacer" />
</label>;
}

View file

@ -2171,6 +2171,11 @@
"Import": "Import",
"Confirm encryption setup": "Confirm encryption setup",
"Click the button below to confirm setting up encryption.": "Click the button below to confirm setting up encryption.",
"Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.": "Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.",
"Generate a Security Key": "Generate a Security Key",
"Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.": "Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.",
"Enter a Security Phrase": "Enter a Security Phrase",
"Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Use a secret phrase only you know, and optionally save a Security Key to use for backup.",
"Enter your account password to confirm the upgrade:": "Enter your account password to confirm the upgrade:",
"Restore your key backup to upgrade your encryption": "Restore your key backup to upgrade your encryption",
"Restore": "Restore",
@ -2200,6 +2205,7 @@
"Unable to query secret storage status": "Unable to query secret storage status",
"Retry": "Retry",
"You can now verify your other devices, and other users to keep your chats safe.": "You can now verify your other devices, and other users to keep your chats safe.",
"Set up Secure backup": "Set up Secure backup",
"Upgrade your encryption": "Upgrade your encryption",
"Confirm recovery passphrase": "Confirm recovery passphrase",
"Make a copy of your recovery key": "Make a copy of your recovery key",