Added live validation

This commit is contained in:
Šimon Brandner 2020-11-21 20:10:38 +01:00
parent 447e87ceab
commit 7e786e67a8

View file

@ -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>