// A password reset form. import React from 'react'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import PhoneEdit from '../widgets/phone-edit.jsx'; import VisiblePassword from '../widgets/visible-password.jsx'; import HashNavigation from '../lib/navigation.js'; const messages = defineMessages({ password_reset_email_sent: { id: 'password_reset_email_sent', defaultMessage: 'An email with security code has been sent.', description: 'Notification that the email with password reset instructions has been sent' }, password_reset_sms_sent: { id: 'password_reset_sms_sent', defaultMessage: 'A text message with security code has been sent.', description: 'Notification that the SMS with password reset instructions has been sent' } }); class PasswordResetView extends React.PureComponent { constructor(props) { super(props); this.state = { tel: '', email: '', password: '', sent: false, haveCode: false, code: '' }; this.handleSubmit = this.handleSubmit.bind(this); this.handleEmailChange = this.handleEmailChange.bind(this); this.handlePasswordChange = this.handlePasswordChange.bind(this); this.handleCodeChange = this.handleCodeChange.bind(this); this.handleShowCodeField = this.handleShowCodeField.bind(this); // Connection will trigger change by changing the this.props.serverVersion. props.tinode.connect() .catch(err => { this.props.onError(err.message, 'err'); }); } componentDidMount() { const parsed = HashNavigation.parseUrlHash(window.location.hash); const newState = { token: parsed.params.token, scheme: parsed.params.scheme, code: parsed.params.code || '' } this.savedCred = parsed.params.cred; if (this.props.reqCredMethod && parsed.params.cred) { newState[this.props.reqCredMethod] = this.savedCred; } this.setState(newState); } componentDidUpdate(prevProps, prevState) { if (prevProps.reqCredMethod != this.props.reqCredMethod && this.props.reqCredMethod) { this.setState({[this.props.reqCredMethod]: this.savedCred || ''}); } } handleSubmit(e) { e.preventDefault(); if (this.state.token) { // Reset using token. this.props.onReset(this.state.password.trim(), { scheme: 'token', secret: this.state.token }); } else if (this.state.code && this.props.reqCredMethod) { // Reset using security code. // The secret is structured as ::, "123456:email:alice@example.com". const cred = this.props.reqCredMethod == 'email' ? this.state.email.trim() : this.state.tel.trim(); this.props.onReset(this.state.password.trim(), { scheme: 'code', secret: btoa(`${this.state.code}:${this.props.reqCredMethod}:${cred}`) }); } else { // Send email or SMS with the secret code. const email = this.state.email.trim(); const tel = this.state.tel.trim(); this.setState({email: email, tel: tel}); this.props.onRequest(this.props.reqCredMethod, email || tel) .then(_ => { this.setState({sent: true}); const msg = this.props.reqCredMethod == 'email' ? messages.password_reset_email_sent : this.props.reqCredMethod == 'tel' ? messages.password_reset_sms_sent : null; if (msg) { this.props.onError(this.props.intl.formatMessage(msg), 'info'); } }); } } handleEmailChange(e) { this.setState({email: e.target.value}); } handlePasswordChange(e) { this.setState({password: e.target.value}); } handleCodeChange(e) { this.setState({code: e.target.value.replace(/[^\d]/g, '')}); } handleShowCodeField(e) { e.preventDefault(); this.setState({haveCode: true}); } render() { const showCredentialInput = !((this.state.token || (this.state.code && this.props.reqCredMethod)) && this.state.scheme); const showPasswordInput = !showCredentialInput || this.state.haveCode || this.state.sent; const passwordInput = (<> { (placeholder) => } ); const emailInput = (<> {this.state.haveCode ? null : } { (placeholder) => } ); const phoneInput = (<> {this.state.haveCode ? null :
}
this.setState({tel: number})} />
); const codeInput = (<>
{ (numbers_only) => }
); const credentialInput = this.props.reqCredMethod == 'email' ? emailInput : this.props.reqCredMethod == 'tel' ? phoneInput : null; return (
{!this.state.sent && showCredentialInput ? credentialInput : null} {this.state.haveCode || this.state.sent ? codeInput : null} {showPasswordInput ? passwordInput : null}
{this.state.haveCode || this.state.sent || this.state.token || this.state.code ? null : }
); } } export default injectIntl(PasswordResetView);