107 lines
3.2 KiB
JavaScript
107 lines
3.2 KiB
JavaScript
|
import React from 'react';
|
||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||
|
import classNames from 'classnames';
|
||
|
import Flux from '../lib/flux';
|
||
|
import BaseAuthForm from './BaseAuthForm';
|
||
|
import SaveButton from './common/SaveButton';
|
||
|
import AuthenticationActionCreators from '../actions/AuthenticationActionCreators';
|
||
|
import AuthenticationStore from '../stores/AuthenticationStore';
|
||
|
import i18n from '../i18n';
|
||
|
import {LoginStates} from '../Constants';
|
||
|
|
||
|
const CODE_REF = 'code';
|
||
|
|
||
|
const ResetPassword = React.createClass({
|
||
|
mixins: [PureRenderMixin, Flux.StoreListenerMixin(AuthenticationStore)],
|
||
|
|
||
|
getIniitialState() {
|
||
|
return {
|
||
|
password: '',
|
||
|
};
|
||
|
},
|
||
|
|
||
|
getStateFromStores() {
|
||
|
return {
|
||
|
loginStatus: AuthenticationStore.getLoginStatus(),
|
||
|
mfaTicket: AuthenticationStore.getMFATicket(),
|
||
|
errors: AuthenticationStore.getErrors(),
|
||
|
};
|
||
|
},
|
||
|
|
||
|
handleSubmit(e) {
|
||
|
e.preventDefault();
|
||
|
const password = this.refs.password.value;
|
||
|
this.setState({password});
|
||
|
AuthenticationActionCreators.resetPassword(this.props.location.query['token'], password);
|
||
|
},
|
||
|
|
||
|
handleTokenSubmit(e) {
|
||
|
e.preventDefault();
|
||
|
const code = this.refs[CODE_REF].value;
|
||
|
AuthenticationActionCreators.resetPasswordMFA(
|
||
|
code,
|
||
|
this.state.mfaTicket,
|
||
|
this.state.password,
|
||
|
this.props.location.query['token']
|
||
|
);
|
||
|
},
|
||
|
|
||
|
render() {
|
||
|
const {errors, loginStatus} = this.state;
|
||
|
|
||
|
const hasError = field => errors[field] != null;
|
||
|
|
||
|
const renderError = field => {
|
||
|
if (hasError(field)) {
|
||
|
return <span className="error">({errors[field]})</span>;
|
||
|
} else {
|
||
|
return null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (this.state.mfaTicket) {
|
||
|
return (
|
||
|
<BaseAuthForm onSubmit={this.handleTokenSubmit}>
|
||
|
<div className={classNames({'control-group': true, error: hasError(CODE_REF)})}>
|
||
|
<label htmlFor="mfa-code">{i18n.Messages.TWO_FA_ENTER_TOKEN_LABEL} {renderError(CODE_REF)}</label>
|
||
|
<input
|
||
|
id="mfa-code"
|
||
|
key={CODE_REF}
|
||
|
ref={CODE_REF}
|
||
|
type="text"
|
||
|
autoComplete="off"
|
||
|
spellCheck="false"
|
||
|
maxLength={10}
|
||
|
autoFocus
|
||
|
defaultValue=""
|
||
|
/>
|
||
|
<p className="token-tip">{i18n.Messages.TWO_FA_ENTER_TOKEN_BODY}</p>
|
||
|
</div>
|
||
|
<SaveButton className="btn btn-primary" disabled={loginStatus === LoginStates.LOGGING_IN_MFA}>
|
||
|
{i18n.Messages.LOGIN}
|
||
|
</SaveButton>
|
||
|
</BaseAuthForm>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<BaseAuthForm onSubmit={this.handleSubmit}>
|
||
|
<h1>{i18n.Messages.RESET_PASSWORD_TITLE}</h1>
|
||
|
<div className={classNames({'control-group': true, error: hasError('password')})}>
|
||
|
<label htmlFor="forgot-password">{i18n.Messages.FORM_LABEL_NEW_PASSWORD} {renderError('password')}</label>
|
||
|
<input id="forgot-password" ref="password" type="password" autoFocus />
|
||
|
</div>
|
||
|
<SaveButton className="btn btn-primary" disabled={loginStatus === LoginStates.LOGGING_IN}>
|
||
|
{i18n.Messages.CHANGE_PASSWORD}
|
||
|
</SaveButton>
|
||
|
</BaseAuthForm>
|
||
|
);
|
||
|
},
|
||
|
});
|
||
|
|
||
|
export default ResetPassword;
|
||
|
|
||
|
|
||
|
|
||
|
// WEBPACK FOOTER //
|
||
|
// ./discord_app/components/ResetPassword.js
|