use forms to wrap password fields so Chrome doesn't go wild and prefill all the things
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
45735d5ae3
commit
cb0392b78d
3 changed files with 57 additions and 64 deletions
|
@ -295,31 +295,27 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPassPhraseNextClick = () => {
|
_onPassPhraseNextClick = async () => {
|
||||||
this.setState({phase: PHASE_PASSPHRASE_CONFIRM});
|
// If we're waiting for the timeout before updating the result at this point,
|
||||||
}
|
// skip ahead and do it now, otherwise we'll deny the attempt to proceed
|
||||||
|
// even if the user entered a valid passphrase
|
||||||
_onPassPhraseKeyPress = async (e) => {
|
if (this._setZxcvbnResultTimeout !== null) {
|
||||||
if (e.key === 'Enter') {
|
clearTimeout(this._setZxcvbnResultTimeout);
|
||||||
// If we're waiting for the timeout before updating the result at this point,
|
this._setZxcvbnResultTimeout = null;
|
||||||
// skip ahead and do it now, otherwise we'll deny the attempt to proceed
|
await new Promise((resolve) => {
|
||||||
// even if the user entered a valid passphrase
|
this.setState({
|
||||||
if (this._setZxcvbnResultTimeout !== null) {
|
zxcvbnResult: scorePassword(this.state.passPhrase),
|
||||||
clearTimeout(this._setZxcvbnResultTimeout);
|
}, resolve);
|
||||||
this._setZxcvbnResultTimeout = null;
|
});
|
||||||
await new Promise((resolve) => {
|
|
||||||
this.setState({
|
|
||||||
zxcvbnResult: scorePassword(this.state.passPhrase),
|
|
||||||
}, resolve);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (this._passPhraseIsValid()) {
|
|
||||||
this._onPassPhraseNextClick();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (this._passPhraseIsValid()) {
|
||||||
|
this.setState({phase: PHASE_PASSPHRASE_CONFIRM});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
_onPassPhraseConfirmNextClick = async () => {
|
_onPassPhraseConfirmNextClick = async () => {
|
||||||
|
if (this.state.passPhrase !== this.state.passPhraseConfirm) return;
|
||||||
|
|
||||||
const [keyInfo, encodedRecoveryKey] =
|
const [keyInfo, encodedRecoveryKey] =
|
||||||
await MatrixClientPeg.get().createRecoveryKeyFromPassphrase(this.state.passPhrase);
|
await MatrixClientPeg.get().createRecoveryKeyFromPassphrase(this.state.passPhrase);
|
||||||
this._keyInfo = keyInfo;
|
this._keyInfo = keyInfo;
|
||||||
|
@ -332,12 +328,6 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPassPhraseConfirmKeyPress = (e) => {
|
|
||||||
if (e.key === 'Enter' && this.state.passPhrase === this.state.passPhraseConfirm) {
|
|
||||||
this._onPassPhraseConfirmNextClick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onSetAgainClick = () => {
|
_onSetAgainClick = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
passPhrase: '',
|
passPhrase: '',
|
||||||
|
@ -407,7 +397,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
} else if (this.state.canUploadKeysWithPasswordOnly) {
|
} else if (this.state.canUploadKeysWithPasswordOnly) {
|
||||||
authPrompt = <div>
|
authPrompt = <div>
|
||||||
<div>{_t("Enter your account password to confirm the upgrade:")}</div>
|
<div>{_t("Enter your account password to confirm the upgrade:")}</div>
|
||||||
<div><Field type="password"
|
<div><Field
|
||||||
|
type="password"
|
||||||
id="mx_CreateSecretStorage_accountPassword"
|
id="mx_CreateSecretStorage_accountPassword"
|
||||||
label={_t("Password")}
|
label={_t("Password")}
|
||||||
value={this.state.accountPassword}
|
value={this.state.accountPassword}
|
||||||
|
@ -469,7 +460,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>
|
return <form>
|
||||||
<p>{_t(
|
<p>{_t(
|
||||||
"Set up encryption on this device to allow it to verify other devices, " +
|
"Set up encryption on this device to allow it to verify other devices, " +
|
||||||
"granting them access to encrypted messages and marking them as trusted for other users.",
|
"granting them access to encrypted messages and marking them as trusted for other users.",
|
||||||
|
@ -480,13 +471,14 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
)}</p>
|
)}</p>
|
||||||
|
|
||||||
<div className="mx_CreateSecretStorageDialog_passPhraseContainer">
|
<div className="mx_CreateSecretStorageDialog_passPhraseContainer">
|
||||||
<Field type="password"
|
<Field
|
||||||
|
type="password"
|
||||||
className="mx_CreateSecretStorageDialog_passPhraseField"
|
className="mx_CreateSecretStorageDialog_passPhraseField"
|
||||||
onChange={this._onPassPhraseChange}
|
onChange={this._onPassPhraseChange}
|
||||||
onKeyPress={this._onPassPhraseKeyPress}
|
|
||||||
value={this.state.passPhrase}
|
value={this.state.passPhrase}
|
||||||
label={_t("Enter a passphrase")}
|
label={_t("Enter a passphrase")}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
|
autoComplete="new-password"
|
||||||
/>
|
/>
|
||||||
<div className="mx_CreateSecretStorageDialog_passPhraseHelp">
|
<div className="mx_CreateSecretStorageDialog_passPhraseHelp">
|
||||||
{strengthMeter}
|
{strengthMeter}
|
||||||
|
@ -499,10 +491,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
onChange={this._onUseKeyBackupChange} value={this.state.useKeyBackup}
|
onChange={this._onUseKeyBackupChange} value={this.state.useKeyBackup}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DialogButtons primaryButton={_t('Continue')}
|
<DialogButtons
|
||||||
|
primaryButton={_t('Continue')}
|
||||||
onPrimaryButtonClick={this._onPassPhraseNextClick}
|
onPrimaryButtonClick={this._onPassPhraseNextClick}
|
||||||
hasCancel={false}
|
hasCancel={false}
|
||||||
disabled={!this._passPhraseIsValid()}
|
disabled={!this._passPhraseIsValid()}
|
||||||
|
primaryIsSubmit={true}
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
onClick={this._onSkipSetupClick}
|
onClick={this._onSkipSetupClick}
|
||||||
|
@ -516,7 +510,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
{_t("Set up with a recovery key")}
|
{_t("Set up with a recovery key")}
|
||||||
</AccessibleButton></p>
|
</AccessibleButton></p>
|
||||||
</details>
|
</details>
|
||||||
</div>;
|
</form>;
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderPhasePassPhraseConfirm() {
|
_renderPhasePassPhraseConfirm() {
|
||||||
|
@ -549,27 +543,30 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
return <div>
|
return <form>
|
||||||
<p>{_t(
|
<p>{_t(
|
||||||
"Enter your passphrase a second time to confirm it.",
|
"Enter your passphrase a second time to confirm it.",
|
||||||
)}</p>
|
)}</p>
|
||||||
<div className="mx_CreateSecretStorageDialog_passPhraseContainer">
|
<div className="mx_CreateSecretStorageDialog_passPhraseContainer">
|
||||||
<Field type="password"
|
<Field
|
||||||
|
type="password"
|
||||||
id="mx_CreateSecretStorageDialog_passPhraseField"
|
id="mx_CreateSecretStorageDialog_passPhraseField"
|
||||||
onChange={this._onPassPhraseConfirmChange}
|
onChange={this._onPassPhraseConfirmChange}
|
||||||
onKeyPress={this._onPassPhraseConfirmKeyPress}
|
|
||||||
value={this.state.passPhraseConfirm}
|
value={this.state.passPhraseConfirm}
|
||||||
className="mx_CreateSecretStorageDialog_passPhraseField"
|
className="mx_CreateSecretStorageDialog_passPhraseField"
|
||||||
label={_t("Confirm your passphrase")}
|
label={_t("Confirm your passphrase")}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
|
autoComplete="new-password"
|
||||||
/>
|
/>
|
||||||
<div className="mx_CreateSecretStorageDialog_passPhraseMatch">
|
<div className="mx_CreateSecretStorageDialog_passPhraseMatch">
|
||||||
{passPhraseMatch}
|
{passPhraseMatch}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DialogButtons primaryButton={_t('Continue')}
|
<DialogButtons
|
||||||
|
primaryButton={_t('Continue')}
|
||||||
onPrimaryButtonClick={this._onPassPhraseConfirmNextClick}
|
onPrimaryButtonClick={this._onPassPhraseConfirmNextClick}
|
||||||
hasCancel={false}
|
hasCancel={false}
|
||||||
|
primaryIsSubmit={true}
|
||||||
disabled={this.state.passPhrase !== this.state.passPhraseConfirm}
|
disabled={this.state.passPhrase !== this.state.passPhraseConfirm}
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
|
@ -577,7 +574,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
className="danger"
|
className="danger"
|
||||||
>{_t("Skip")}</button>
|
>{_t("Skip")}</button>
|
||||||
</DialogButtons>
|
</DialogButtons>
|
||||||
</div>;
|
</form>;
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderPhaseShowKey() {
|
_renderPhaseShowKey() {
|
||||||
|
|
|
@ -160,6 +160,7 @@ export default createReactClass({
|
||||||
onKeyDown={ this._onKeyDown }
|
onKeyDown={ this._onKeyDown }
|
||||||
onBlur={this._onBlur}
|
onBlur={this._onBlur}
|
||||||
placeholder={ placeholder }
|
placeholder={ placeholder }
|
||||||
|
autoComplete="off"
|
||||||
/>
|
/>
|
||||||
{ clearButton }
|
{ clearButton }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2018, 2019 New Vector Ltd
|
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");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -21,7 +21,6 @@ import * as sdk from '../../../../index';
|
||||||
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
|
||||||
|
|
||||||
import { _t } from '../../../../languageHandler';
|
import { _t } from '../../../../languageHandler';
|
||||||
import { Key } from "../../../../Keyboard";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Access Secure Secret Storage by requesting the user's passphrase.
|
* Access Secure Secret Storage by requesting the user's passphrase.
|
||||||
|
@ -69,6 +68,8 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPassPhraseNext = async () => {
|
_onPassPhraseNext = async () => {
|
||||||
|
if (this.state.passPhrase.length <= 0) return;
|
||||||
|
|
||||||
this.setState({ keyMatches: null });
|
this.setState({ keyMatches: null });
|
||||||
const input = { passphrase: this.state.passPhrase };
|
const input = { passphrase: this.state.passPhrase };
|
||||||
const keyMatches = await this.props.checkPrivateKey(input);
|
const keyMatches = await this.props.checkPrivateKey(input);
|
||||||
|
@ -80,6 +81,8 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRecoveryKeyNext = async () => {
|
_onRecoveryKeyNext = async () => {
|
||||||
|
if (!this.state.recoveryKeyValid) return;
|
||||||
|
|
||||||
this.setState({ keyMatches: null });
|
this.setState({ keyMatches: null });
|
||||||
const input = { recoveryKey: this.state.recoveryKey };
|
const input = { recoveryKey: this.state.recoveryKey };
|
||||||
const keyMatches = await this.props.checkPrivateKey(input);
|
const keyMatches = await this.props.checkPrivateKey(input);
|
||||||
|
@ -97,18 +100,6 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPassPhraseKeyPress = (e) => {
|
|
||||||
if (e.key === Key.ENTER && this.state.passPhrase.length > 0) {
|
|
||||||
this._onPassPhraseNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onRecoveryKeyKeyPress = (e) => {
|
|
||||||
if (e.key === Key.ENTER && this.state.recoveryKeyValid) {
|
|
||||||
this._onRecoveryKeyNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
|
|
||||||
|
@ -135,7 +126,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
|
||||||
)}
|
)}
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
keyStatus = <div className="mx_AccessSecretStorageDialog_keyStatus"></div>;
|
keyStatus = <div className="mx_AccessSecretStorageDialog_keyStatus" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
content = <div>
|
content = <div>
|
||||||
|
@ -149,23 +140,26 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
|
||||||
"identity for verifying other devices by entering your passphrase.",
|
"identity for verifying other devices by entering your passphrase.",
|
||||||
)}</p>
|
)}</p>
|
||||||
|
|
||||||
<div className="mx_AccessSecretStorageDialog_primaryContainer">
|
<form className="mx_AccessSecretStorageDialog_primaryContainer">
|
||||||
<input type="password"
|
<input
|
||||||
|
type="password"
|
||||||
className="mx_AccessSecretStorageDialog_passPhraseInput"
|
className="mx_AccessSecretStorageDialog_passPhraseInput"
|
||||||
onChange={this._onPassPhraseChange}
|
onChange={this._onPassPhraseChange}
|
||||||
onKeyPress={this._onPassPhraseKeyPress}
|
|
||||||
value={this.state.passPhrase}
|
value={this.state.passPhrase}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
|
autoComplete="new-password"
|
||||||
/>
|
/>
|
||||||
{keyStatus}
|
{keyStatus}
|
||||||
<DialogButtons primaryButton={_t('Next')}
|
<DialogButtons
|
||||||
|
primaryButton={_t('Next')}
|
||||||
onPrimaryButtonClick={this._onPassPhraseNext}
|
onPrimaryButtonClick={this._onPassPhraseNext}
|
||||||
hasCancel={true}
|
hasCancel={true}
|
||||||
onCancel={this._onCancel}
|
onCancel={this._onCancel}
|
||||||
focus={false}
|
focus={false}
|
||||||
|
primaryIsSubmit={true}
|
||||||
primaryDisabled={this.state.passPhrase.length === 0}
|
primaryDisabled={this.state.passPhrase.length === 0}
|
||||||
/>
|
/>
|
||||||
</div>
|
</form>
|
||||||
{_t(
|
{_t(
|
||||||
"If you've forgotten your passphrase you can "+
|
"If you've forgotten your passphrase you can "+
|
||||||
"<button1>use your recovery key</button1> or " +
|
"<button1>use your recovery key</button1> or " +
|
||||||
|
@ -192,7 +186,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
|
||||||
|
|
||||||
let keyStatus;
|
let keyStatus;
|
||||||
if (this.state.recoveryKey.length === 0) {
|
if (this.state.recoveryKey.length === 0) {
|
||||||
keyStatus = <div className="mx_AccessSecretStorageDialog_keyStatus"></div>;
|
keyStatus = <div className="mx_AccessSecretStorageDialog_keyStatus" />;
|
||||||
} else if (this.state.recoveryKeyValid) {
|
} else if (this.state.recoveryKeyValid) {
|
||||||
keyStatus = <div className="mx_AccessSecretStorageDialog_keyStatus">
|
keyStatus = <div className="mx_AccessSecretStorageDialog_keyStatus">
|
||||||
{"\uD83D\uDC4D "}{_t("This looks like a valid recovery key!")}
|
{"\uD83D\uDC4D "}{_t("This looks like a valid recovery key!")}
|
||||||
|
@ -221,22 +215,23 @@ export default class AccessSecretStorageDialog extends React.PureComponent {
|
||||||
"identity for verifying other devices by entering your recovery key.",
|
"identity for verifying other devices by entering your recovery key.",
|
||||||
)}</p>
|
)}</p>
|
||||||
|
|
||||||
<div className="mx_AccessSecretStorageDialog_primaryContainer">
|
<form className="mx_AccessSecretStorageDialog_primaryContainer">
|
||||||
<input className="mx_AccessSecretStorageDialog_recoveryKeyInput"
|
<input className="mx_AccessSecretStorageDialog_recoveryKeyInput"
|
||||||
onChange={this._onRecoveryKeyChange}
|
onChange={this._onRecoveryKeyChange}
|
||||||
onKeyPress={this._onRecoveryKeyKeyPress}
|
|
||||||
value={this.state.recoveryKey}
|
value={this.state.recoveryKey}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
/>
|
/>
|
||||||
{keyStatus}
|
{keyStatus}
|
||||||
<DialogButtons primaryButton={_t('Next')}
|
<DialogButtons
|
||||||
|
primaryButton={_t('Next')}
|
||||||
onPrimaryButtonClick={this._onRecoveryKeyNext}
|
onPrimaryButtonClick={this._onRecoveryKeyNext}
|
||||||
hasCancel={true}
|
hasCancel={true}
|
||||||
onCancel={this._onCancel}
|
onCancel={this._onCancel}
|
||||||
focus={false}
|
focus={false}
|
||||||
|
primaryIsSubmit={true}
|
||||||
primaryDisabled={!this.state.recoveryKeyValid}
|
primaryDisabled={!this.state.recoveryKeyValid}
|
||||||
/>
|
/>
|
||||||
</div>
|
</form>
|
||||||
{_t(
|
{_t(
|
||||||
"If you've forgotten your recovery key you can "+
|
"If you've forgotten your recovery key you can "+
|
||||||
"<button>set up new recovery options</button>."
|
"<button>set up new recovery options</button>."
|
||||||
|
|
Loading…
Reference in a new issue