Added live validation
This commit is contained in:
parent
447e87ceab
commit
7e786e67a8
1 changed files with 50 additions and 4 deletions
|
@ -21,9 +21,16 @@ import PropTypes from 'prop-types';
|
||||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
import Spinner from '../elements/Spinner';
|
import Spinner from '../elements/Spinner';
|
||||||
|
import withValidation from '../elements/Validation';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import * as sdk from "../../../index";
|
import * as sdk from "../../../index";
|
||||||
import Modal from "../../../Modal";
|
import Modal from "../../../Modal";
|
||||||
|
import PassphraseField from "../auth/PassphraseField";
|
||||||
|
|
||||||
|
const FIELD_NEW_PASSWORD = 'field_new_password';
|
||||||
|
const FIELD_NEW_PASSWORD_CONFIRM = 'field_new_password_confirm';
|
||||||
|
|
||||||
|
const PASSWORD_MIN_SCORE = 3; // safely unguessable: moderate protection from offline slow-hash scenario.
|
||||||
|
|
||||||
export default class ChangePassword extends React.Component {
|
export default class ChangePassword extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -63,6 +70,7 @@ export default class ChangePassword extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
fieldValid: {},
|
||||||
phase: ChangePassword.Phases.Edit,
|
phase: ChangePassword.Phases.Edit,
|
||||||
oldPassword: "",
|
oldPassword: "",
|
||||||
newPassword: "",
|
newPassword: "",
|
||||||
|
@ -168,6 +176,14 @@ export default class ChangePassword extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
markFieldValid(fieldID, valid) {
|
||||||
|
const { fieldValid } = this.state;
|
||||||
|
fieldValid[fieldID] = valid;
|
||||||
|
this.setState({
|
||||||
|
fieldValid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onChangeOldPassword = (ev) => {
|
onChangeOldPassword = (ev) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
oldPassword: ev.target.value,
|
oldPassword: ev.target.value,
|
||||||
|
@ -180,12 +196,39 @@ export default class ChangePassword extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onNewPasswordValidate = result => {
|
||||||
|
this.markFieldValid(FIELD_NEW_PASSWORD, result.valid);
|
||||||
|
};
|
||||||
|
|
||||||
onChangeNewPasswordConfirm = (ev) => {
|
onChangeNewPasswordConfirm = (ev) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
newPasswordConfirm: ev.target.value,
|
newPasswordConfirm: ev.target.value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onNewPasswordConfirmValidate = async fieldState => {
|
||||||
|
const result = await this.validatePasswordConfirmRules(fieldState);
|
||||||
|
this.markFieldValid(FIELD_NEW_PASSWORD_CONFIRM, result.valid);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
validatePasswordConfirmRules = withValidation({
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
key: "required",
|
||||||
|
test: ({ value, allowEmpty }) => allowEmpty || !!value,
|
||||||
|
invalid: () => _t("Confirm password"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "match",
|
||||||
|
test({ value }) {
|
||||||
|
return !value || value === this.state.newPassword;
|
||||||
|
},
|
||||||
|
invalid: () => _t("Passwords don't match"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
onClickChange = (ev) => {
|
onClickChange = (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const oldPassword = this.state.oldPassword;
|
const oldPassword = this.state.oldPassword;
|
||||||
|
@ -202,8 +245,6 @@ export default class ChangePassword extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// TODO: Live validation on `new pw == confirm pw`
|
|
||||||
|
|
||||||
const rowClassName = this.props.rowClassName;
|
const rowClassName = this.props.rowClassName;
|
||||||
const buttonClassName = this.props.buttonClassName;
|
const buttonClassName = this.props.buttonClassName;
|
||||||
|
|
||||||
|
@ -220,21 +261,26 @@ export default class ChangePassword extends React.Component {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={rowClassName}>
|
<div className={rowClassName}>
|
||||||
<Field
|
<PassphraseField
|
||||||
|
fieldRef={field => this[FIELD_NEW_PASSWORD] = field}
|
||||||
type="password"
|
type="password"
|
||||||
label={_t('New Password')}
|
label='New Password'
|
||||||
|
minScore={PASSWORD_MIN_SCORE}
|
||||||
value={this.state.newPassword}
|
value={this.state.newPassword}
|
||||||
autoFocus={this.props.autoFocusNewPasswordInput}
|
autoFocus={this.props.autoFocusNewPasswordInput}
|
||||||
onChange={this.onChangeNewPassword}
|
onChange={this.onChangeNewPassword}
|
||||||
|
onValidate={this.onNewPasswordValidate}
|
||||||
autoComplete="new-password"
|
autoComplete="new-password"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={rowClassName}>
|
<div className={rowClassName}>
|
||||||
<Field
|
<Field
|
||||||
|
ref={field => this[FIELD_NEW_PASSWORD_CONFIRM] = field}
|
||||||
type="password"
|
type="password"
|
||||||
label={_t("Confirm password")}
|
label={_t("Confirm password")}
|
||||||
value={this.state.newPasswordConfirm}
|
value={this.state.newPasswordConfirm}
|
||||||
onChange={this.onChangeNewPasswordConfirm}
|
onChange={this.onChangeNewPasswordConfirm}
|
||||||
|
onValidate={this.onNewPasswordConfirmValidate}
|
||||||
autoComplete="new-password"
|
autoComplete="new-password"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue