You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
4.7 KiB
TypeScript
184 lines
4.7 KiB
TypeScript
5 years ago
|
import React from 'react';
|
||
|
|
||
|
import { SessionModal } from './SessionModal';
|
||
|
import { SessionButton, SessionButtonType, SessionButtonColor } from './SessionButton';
|
||
|
|
||
|
export enum PasswordAction {
|
||
|
Set = 'set',
|
||
|
Change = 'change',
|
||
|
Remove = 'remove'
|
||
|
}
|
||
|
|
||
|
interface Props {
|
||
|
action: PasswordAction;
|
||
|
onOk: any;
|
||
|
onClose: any;
|
||
|
}
|
||
|
|
||
|
interface State {
|
||
|
error: string | null;
|
||
|
}
|
||
|
|
||
|
export class SessionPasswordModal extends React.Component<Props, State> {
|
||
|
constructor(props: any) {
|
||
|
super(props);
|
||
|
|
||
|
this.state = {
|
||
|
error: null,
|
||
|
}
|
||
|
|
||
|
this.showError = this.showError.bind(this);
|
||
|
|
||
|
this.setPassword = this.setPassword.bind(this);
|
||
|
this.closeDialog = this.closeDialog.bind(this);
|
||
|
this.onEnter = this.onEnter.bind(this);
|
||
|
}
|
||
|
|
||
|
public render() {
|
||
|
const { action, onOk } = this.props;
|
||
|
const placeholders = this.props.action === PasswordAction.Change
|
||
|
? [window.i18n('typeInOldPassword'), window.i18n('enterPassword')]
|
||
|
: [window.i18n('enterPassword'), window.i18n('confirmPassword')]
|
||
|
|
||
|
const confirmButtonColor = this.props.action === PasswordAction.Remove
|
||
|
? SessionButtonColor.Danger
|
||
|
: SessionButtonColor.Primary
|
||
|
|
||
|
return (
|
||
|
<SessionModal
|
||
|
title={window.i18n(`${action}Password`)}
|
||
|
onOk={() => null}
|
||
|
onClose={this.closeDialog}
|
||
|
>
|
||
|
<div className="spacer-sm"></div>
|
||
|
|
||
|
<div className="session-modal__input-group">
|
||
|
<input
|
||
|
type="password"
|
||
|
id="password-modal-input"
|
||
|
placeholder={placeholders[0]}
|
||
|
/>
|
||
|
{ action !== PasswordAction.Remove && (
|
||
|
<input
|
||
|
type="password"
|
||
|
id="password-modal-input-confirm"
|
||
|
placeholder={placeholders[1]}
|
||
|
/>
|
||
|
)}
|
||
|
</div>
|
||
|
|
||
|
<div className="spacer-sm" />
|
||
|
{this.showError()}
|
||
|
|
||
|
<div className="session-modal__button-group">
|
||
|
<SessionButton
|
||
|
text={window.i18n('ok')}
|
||
|
buttonColor={confirmButtonColor}
|
||
|
onClick={() => this.setPassword(onOk)}
|
||
|
/>
|
||
|
|
||
|
<SessionButton text={window.i18n('cancel')} onClick={this.closeDialog} />
|
||
|
</div>
|
||
|
|
||
|
</SessionModal>
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
private async setPassword(onSuccess: any) {
|
||
|
const enteredPassword = String($('#password-modal-input').val());
|
||
|
const enteredPasswordConfirm = String($('#password-modal-input-confirm').val());
|
||
|
|
||
|
// Check passwords enntered
|
||
|
if ((enteredPassword.length === 0) ||
|
||
|
((this.props.action === PasswordAction.Change) &&
|
||
|
(enteredPasswordConfirm.length === 0))){
|
||
|
this.setState({
|
||
|
error: window.i18n('noGivenPassword'),
|
||
|
});
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Passwords match or remove password successful
|
||
|
const newPassword = this.props.action === PasswordAction.Remove
|
||
|
? null
|
||
|
: enteredPasswordConfirm;
|
||
|
const oldPassword = this.props.action === PasswordAction.Set
|
||
|
? null
|
||
|
: enteredPassword;
|
||
|
|
||
|
|
||
|
// Check if password match, when setting, changing or removing
|
||
|
const valid = this.props.action !== PasswordAction.Set
|
||
|
? !! await this.validatePasswordHash(oldPassword)
|
||
|
: (enteredPassword === enteredPasswordConfirm);
|
||
|
|
||
|
if (!valid){
|
||
|
this.setState({
|
||
|
error: window.i18n(`${this.props.action}PasswordInvalid`),
|
||
|
});
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
await window.setPassword(newPassword, oldPassword);
|
||
|
|
||
|
|
||
|
const toastParams = {
|
||
|
title: window.i18n(`${this.props.action}PasswordTitle`),
|
||
|
description: window.i18n(`${this.props.action}PasswordToastDescription`),
|
||
|
type: this.props.action !== PasswordAction.Remove ? 'success' : 'warning',
|
||
|
icon: this.props.action !== PasswordAction.Remove ? 'lock' : undefined,
|
||
|
}
|
||
|
|
||
|
window.pushToast({
|
||
|
id: "set-password-success-toast",
|
||
|
...toastParams
|
||
|
});
|
||
|
|
||
|
onSuccess(this.props.action);
|
||
|
this.closeDialog();
|
||
|
|
||
|
}
|
||
|
|
||
|
public async validatePasswordHash(password: string | null) {
|
||
|
// Check if the password matches the hash we have stored
|
||
|
const hash = await window.Signal.Data.getPasswordHash();
|
||
|
if (hash && !window.passwordUtil.matchesHash(password, hash)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private showError() {
|
||
|
const message = this.state.error;
|
||
|
|
||
|
return (
|
||
|
<>
|
||
|
{message && (
|
||
|
<>
|
||
|
<div className="session-label warning">{message}</div>
|
||
|
<div className="spacer-lg" />
|
||
|
</>
|
||
|
)}
|
||
|
</>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
private onEnter(event: any) {
|
||
|
if (event.key === 'Enter') {
|
||
|
//if ($('#server-url').is(':focus')) {
|
||
|
//this.showView('connecting');
|
||
|
//}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private closeDialog() {
|
||
|
window.removeEventListener('keyup', this.onEnter);
|
||
|
this.props.onClose && this.props.onClose();
|
||
|
}
|
||
|
|
||
|
}
|