refactor SessionPasswordModal to handle errors on length

pull/1294/head
Audric Ackermann 5 years ago
parent a6fa3386c1
commit 89579ebd35
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -22,6 +22,10 @@ const validatePassword = (phrase, i18n) => {
} }
const trimmed = phrase.trim(); const trimmed = phrase.trim();
if (trimmed.length === 0) {
return i18n ? i18n('noGivenPassword') : ERRORS.LENGTH;
}
if (trimmed.length < 6 || trimmed.length > 50) { if (trimmed.length < 6 || trimmed.length > 50) {
return i18n ? i18n('passwordLengthError') : ERRORS.LENGTH; return i18n ? i18n('passwordLengthError') : ERRORS.LENGTH;
} }

@ -62,7 +62,7 @@
return this; return this;
}, },
onSubmit(groupName, avatar) { onSubmit(groupName, avatar) {
if(groupName !== this.groupName || avatar !== this.avatarPath) { if (groupName !== this.groupName || avatar !== this.avatarPath) {
window.MediumGroups.initiateGroupUpdate( window.MediumGroups.initiateGroupUpdate(
this.groupId, this.groupId,
groupName, groupName,

@ -17,17 +17,20 @@ interface Props {
interface State { interface State {
error: string | null; error: string | null;
currentPasswordEntered: string | null;
currentPasswordConfirmEntered: string | null;
} }
export class SessionPasswordModal extends React.Component<Props, State> { export class SessionPasswordModal extends React.Component<Props, State> {
private readonly passwordInput: React.RefObject<HTMLInputElement>; private passportInput: HTMLInputElement | null = null;
private readonly passwordInputConfirm: React.RefObject<HTMLInputElement>;
constructor(props: any) { constructor(props: any) {
super(props); super(props);
this.state = { this.state = {
error: null, error: null,
currentPasswordEntered: null,
currentPasswordConfirmEntered: null,
}; };
this.showError = this.showError.bind(this); this.showError = this.showError.bind(this);
@ -35,32 +38,28 @@ export class SessionPasswordModal extends React.Component<Props, State> {
this.setPassword = this.setPassword.bind(this); this.setPassword = this.setPassword.bind(this);
this.closeDialog = this.closeDialog.bind(this); this.closeDialog = this.closeDialog.bind(this);
this.onKeyUp = this.onKeyUp.bind(this); this.onPasswordInput = this.onPasswordInput.bind(this);
this.onPaste = this.onPaste.bind(this); this.onPasswordConfirmInput = this.onPasswordConfirmInput.bind(this);
this.passwordInput = React.createRef(); this.onPaste = this.onPaste.bind(this);
this.passwordInputConfirm = React.createRef();
} }
public componentDidMount() { public componentDidMount() {
setTimeout(() => { setTimeout(() => {
if (!this.passwordInput.current) { // tslint:disable-next-line: no-unused-expression
return; this.passportInput && this.passportInput.focus();
} }, 1);
this.passwordInput.current.focus();
}, 100);
} }
public render() { public render() {
const { action, onOk } = this.props; const { action, onOk } = this.props;
const placeholders = const placeholders =
this.props.action === PasswordAction.Change action === PasswordAction.Change
? [window.i18n('typeInOldPassword'), window.i18n('enterPassword')] ? [window.i18n('typeInOldPassword'), window.i18n('enterPassword')]
: [window.i18n('enterPassword'), window.i18n('confirmPassword')]; : [window.i18n('enterPassword'), window.i18n('confirmPassword')];
const confirmButtonColor = const confirmButtonColor =
this.props.action === PasswordAction.Remove action === PasswordAction.Remove
? SessionButtonColor.Danger ? SessionButtonColor.Danger
: SessionButtonColor.Primary; : SessionButtonColor.Primary;
@ -76,9 +75,11 @@ export class SessionPasswordModal extends React.Component<Props, State> {
<input <input
type="password" type="password"
id="password-modal-input" id="password-modal-input"
ref={this.passwordInput} ref={input => {
this.passportInput = input;
}}
placeholder={placeholders[0]} placeholder={placeholders[0]}
onKeyUp={this.onKeyUp} onKeyUp={this.onPasswordInput}
maxLength={window.CONSTANTS.MAX_PASSWORD_LENGTH} maxLength={window.CONSTANTS.MAX_PASSWORD_LENGTH}
onPaste={this.onPaste} onPaste={this.onPaste}
/> />
@ -86,9 +87,8 @@ export class SessionPasswordModal extends React.Component<Props, State> {
<input <input
type="password" type="password"
id="password-modal-input-confirm" id="password-modal-input-confirm"
ref={this.passwordInputConfirm}
placeholder={placeholders[1]} placeholder={placeholders[1]}
onKeyUp={this.onKeyUp} onKeyUp={this.onPasswordConfirmInput}
maxLength={window.CONSTANTS.MAX_PASSWORD_LENGTH} maxLength={window.CONSTANTS.MAX_PASSWORD_LENGTH}
onPaste={this.onPaste} onPaste={this.onPaste}
/> />
@ -139,61 +139,60 @@ export class SessionPasswordModal extends React.Component<Props, State> {
); );
} }
// tslint:disable-next-line: cyclomatic-complexity
private async setPassword(onSuccess?: any) { private async setPassword(onSuccess?: any) {
// Only initial input required for PasswordAction.Remove const { action } = this.props;
if ( const {
!this.passwordInput.current || currentPasswordEntered,
(!this.passwordInputConfirm.current && currentPasswordConfirmEntered,
this.props.action !== PasswordAction.Remove) } = this.state;
) { const { Set, Remove, Change } = PasswordAction;
return;
}
// Trim leading / trailing whitespace for UX // Trim leading / trailing whitespace for UX
const enteredPassword = String(this.passwordInput.current.value).trim(); const enteredPassword = (currentPasswordEntered || '').trim();
const enteredPasswordConfirm = const enteredPasswordConfirm = (currentPasswordConfirmEntered || '').trim();
(this.passwordInputConfirm.current &&
String(this.passwordInputConfirm.current.value).trim()) ||
'';
if (
enteredPassword.length === 0 ||
(enteredPasswordConfirm.length === 0 &&
this.props.action !== PasswordAction.Remove)
) {
return;
}
// Check passwords entered // if user did not fill the first password field, we can't do anything
if ( const errorFirstInput = window.passwordUtil.validatePassword(
enteredPassword.length === 0 || enteredPassword,
(this.props.action === PasswordAction.Change && window.i18n
enteredPasswordConfirm.length === 0) );
) { if (errorFirstInput !== null) {
this.setState({ this.setState({
error: window.i18n('noGivenPassword'), error: errorFirstInput,
}); });
return; return;
} }
// if action is Set or Change, we need a valid ConfirmPassword
if (action === Set || action === Change) {
const errorSecondInput = window.passwordUtil.validatePassword(
enteredPasswordConfirm,
window.i18n
);
if (errorSecondInput !== null) {
this.setState({
error: errorSecondInput,
});
return;
}
}
// Passwords match or remove password successful // Passwords match or remove password successful
const newPassword = const newPassword = action === Remove ? null : enteredPasswordConfirm;
this.props.action === PasswordAction.Remove const oldPassword = action === Set ? null : enteredPassword;
? null
: enteredPasswordConfirm;
const oldPassword =
this.props.action === PasswordAction.Set ? null : enteredPassword;
// Check if password match, when setting, changing or removing // Check if password match, when setting, changing or removing
const valid = let valid;
this.props.action !== PasswordAction.Set if (action === Set) {
? Boolean(await this.validatePasswordHash(oldPassword)) valid = enteredPassword === enteredPasswordConfirm;
: enteredPassword === enteredPasswordConfirm; } else {
valid = Boolean(await this.validatePasswordHash(oldPassword));
}
if (!valid) { if (!valid) {
this.setState({ this.setState({
error: window.i18n(`${this.props.action}PasswordInvalid`), error: window.i18n(`${action}PasswordInvalid`),
}); });
return; return;
@ -202,10 +201,10 @@ export class SessionPasswordModal extends React.Component<Props, State> {
await window.setPassword(newPassword, oldPassword); await window.setPassword(newPassword, oldPassword);
const toastParams = { const toastParams = {
title: window.i18n(`${this.props.action}PasswordTitle`), title: window.i18n(`${action}PasswordTitle`),
description: window.i18n(`${this.props.action}PasswordToastDescription`), description: window.i18n(`${action}PasswordToastDescription`),
type: this.props.action !== PasswordAction.Remove ? 'success' : 'warning', type: action !== Remove ? 'success' : 'warning',
icon: this.props.action !== PasswordAction.Remove ? 'lock' : undefined, icon: action !== Remove ? 'lock' : undefined,
}; };
window.pushToast({ window.pushToast({
@ -244,13 +243,17 @@ export class SessionPasswordModal extends React.Component<Props, State> {
return false; return false;
} }
private async onKeyUp(event: any) { private async onPasswordInput(event: any) {
const { onOk } = this.props;
if (event.key === 'Enter') { if (event.key === 'Enter') {
await this.setPassword(onOk); return this.setPassword(this.props.onOk);
} }
this.setState({ currentPasswordEntered: event.target.value });
}
event.preventDefault(); private async onPasswordConfirmInput(event: any) {
if (event.key === 'Enter') {
return this.setPassword(this.props.onOk);
}
this.setState({ currentPasswordConfirmEntered: event.target.value });
} }
} }

@ -8,9 +8,7 @@ import * as Lodash from 'lodash';
import * as libsession from '../session'; import * as libsession from '../session';
import { handleSessionRequestMessage } from './sessionHandling'; import { handleSessionRequestMessage } from './sessionHandling';
import { handlePairingAuthorisationMessage } from './multidevice'; import { handlePairingAuthorisationMessage } from './multidevice';
import { import { MediumGroupRequestKeysMessage } from '../session/messages/outgoing';
MediumGroupRequestKeysMessage,
} from '../session/messages/outgoing';
import { MultiDeviceProtocol, SessionProtocol } from '../session/protocols'; import { MultiDeviceProtocol, SessionProtocol } from '../session/protocols';
import { PubKey } from '../session/types'; import { PubKey } from '../session/types';

Loading…
Cancel
Save