|
|
|
@ -24,6 +24,7 @@ interface State {
|
|
|
|
|
error: string | null;
|
|
|
|
|
currentPasswordEntered: string | null;
|
|
|
|
|
currentPasswordConfirmEntered: string | null;
|
|
|
|
|
currentPasswordRetypeEntered: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
@ -36,6 +37,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
error: null,
|
|
|
|
|
currentPasswordEntered: null,
|
|
|
|
|
currentPasswordConfirmEntered: null,
|
|
|
|
|
currentPasswordRetypeEntered: null,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.showError = this.showError.bind(this);
|
|
|
|
@ -45,6 +47,7 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
|
|
|
|
|
this.onPasswordInput = this.onPasswordInput.bind(this);
|
|
|
|
|
this.onPasswordConfirmInput = this.onPasswordConfirmInput.bind(this);
|
|
|
|
|
this.onPasswordRetypeInput = this.onPasswordRetypeInput.bind(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public componentDidMount() {
|
|
|
|
@ -58,7 +61,11 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
const { action, onOk } = this.props;
|
|
|
|
|
const placeholders =
|
|
|
|
|
action === PasswordAction.Change
|
|
|
|
|
? [window.i18n('typeInOldPassword'), window.i18n('enterPassword')]
|
|
|
|
|
? [
|
|
|
|
|
window.i18n('typeInOldPassword'),
|
|
|
|
|
window.i18n('enterPassword'),
|
|
|
|
|
window.i18n('confirmPassword'),
|
|
|
|
|
]
|
|
|
|
|
: [window.i18n('enterPassword'), window.i18n('confirmPassword')];
|
|
|
|
|
|
|
|
|
|
const confirmButtonColor =
|
|
|
|
@ -90,6 +97,14 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
onKeyUp={this.onPasswordConfirmInput}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
{action === PasswordAction.Change && (
|
|
|
|
|
<input
|
|
|
|
|
type="password"
|
|
|
|
|
id="password-modal-input-reconfirm"
|
|
|
|
|
placeholder={placeholders[2]}
|
|
|
|
|
onKeyUp={this.onPasswordRetypeInput}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="spacer-sm" />
|
|
|
|
@ -174,13 +189,28 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
this.closeDialog();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleActionChange(oldPassword: string, newPassword: string) {
|
|
|
|
|
private async handleActionChange(
|
|
|
|
|
oldPassword: string,
|
|
|
|
|
newPassword: string,
|
|
|
|
|
newConfirmedPassword: string
|
|
|
|
|
) {
|
|
|
|
|
// We don't validate oldPassword on change: this is validate on the validatePasswordHash below
|
|
|
|
|
// we only validate the newPassword here
|
|
|
|
|
if (!this.validatePassword(newPassword)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const isValidWithStoredInDB = Boolean(await this.validatePasswordHash(oldPassword));
|
|
|
|
|
|
|
|
|
|
// Check the retyped password matches the new password
|
|
|
|
|
if (newPassword !== newConfirmedPassword) {
|
|
|
|
|
this.setState({
|
|
|
|
|
error: window.i18n('passwordsDoNotMatch'),
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isValidWithStoredInDB = Boolean(
|
|
|
|
|
await this.validatePasswordHash(oldPassword)
|
|
|
|
|
);
|
|
|
|
|
if (!isValidWithStoredInDB) {
|
|
|
|
|
this.setState({
|
|
|
|
|
error: window.i18n('changePasswordInvalid'),
|
|
|
|
@ -224,12 +254,17 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
// tslint:disable-next-line: cyclomatic-complexity
|
|
|
|
|
private async setPassword() {
|
|
|
|
|
const { action } = this.props;
|
|
|
|
|
const { currentPasswordEntered, currentPasswordConfirmEntered } = this.state;
|
|
|
|
|
const {
|
|
|
|
|
currentPasswordEntered,
|
|
|
|
|
currentPasswordConfirmEntered,
|
|
|
|
|
currentPasswordRetypeEntered,
|
|
|
|
|
} = this.state;
|
|
|
|
|
const { Set, Remove, Change } = PasswordAction;
|
|
|
|
|
|
|
|
|
|
// Trim leading / trailing whitespace for UX
|
|
|
|
|
const firstPasswordEntered = (currentPasswordEntered || '').trim();
|
|
|
|
|
const secondPasswordEntered = (currentPasswordConfirmEntered || '').trim();
|
|
|
|
|
const thirdPasswordEntered = (currentPasswordRetypeEntered || '').trim();
|
|
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
|
case Set: {
|
|
|
|
@ -237,7 +272,11 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case Change: {
|
|
|
|
|
await this.handleActionChange(firstPasswordEntered, secondPasswordEntered);
|
|
|
|
|
await this.handleActionChange(
|
|
|
|
|
firstPasswordEntered,
|
|
|
|
|
secondPasswordEntered,
|
|
|
|
|
thirdPasswordEntered
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
case Remove: {
|
|
|
|
@ -272,6 +311,15 @@ class SessionPasswordModalInner extends React.Component<Props, State> {
|
|
|
|
|
|
|
|
|
|
this.setState({ currentPasswordConfirmEntered });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async onPasswordRetypeInput(event: any) {
|
|
|
|
|
if (event.key === 'Enter') {
|
|
|
|
|
return this.setPassword();
|
|
|
|
|
}
|
|
|
|
|
const currentPasswordRetypeEntered = event.target.value;
|
|
|
|
|
|
|
|
|
|
this.setState({ currentPasswordRetypeEntered });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const SessionPasswordModal = withTheme(SessionPasswordModalInner);
|
|
|
|
|