import React from 'react'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import {Link} from 'react-router'; import classNames from 'classnames'; import Flux from '../lib/flux'; import BaseAuthForm from './BaseAuthForm'; import ConfirmModal from './ConfirmModal'; import SaveButton from './common/SaveButton'; import AuthenticationActionCreators from '../actions/AuthenticationActionCreators'; import ModalActionCreators from '../actions/ModalActionCreators'; import AuthenticationStore from '../stores/AuthenticationStore'; import querystring from 'querystring'; import i18n from '../i18n'; import RouterUtils from '../utils/RouterUtils'; import {ActionTypes, ChannelTypes, Endpoints, Routes, LoginStates} from '../Constants'; import {isSafeRedirect} from '../utils/RedirectUtils'; import HTTPUtils from '../utils/HTTPUtils'; import Dispatcher from '../Dispatcher'; const CODE_REF = 'code'; const Login = React.createClass({ mixins: [PureRenderMixin, Flux.StoreListenerMixin(AuthenticationStore)], getStateFromStores() { return { loginStatus: AuthenticationStore.getLoginStatus(), mfaTicket: AuthenticationStore.getMFATicket(), errors: AuthenticationStore.getErrors(), authenticated: AuthenticationStore.isAuthenticated(), }; }, componentDidMount() { AuthenticationActionCreators.fingerprint('Login'); this.loginOrSSO(); }, componentDidUpdate() { this.loginOrSSO(); }, loginOrSSO() { if (this.state.authenticated) { // We should double-check that the user's token is *valid* before forwarding them to their destination HTTPUtils.get({ url: Endpoints.ME, }).then( () => { const {query} = this.props.location; if (query['redirect_to'] && isSafeRedirect(query['redirect_to'])) { window.location = query['redirect_to']; } else if (query['service'] == null) { RouterUtils.transitionTo(Routes.ME); } else { const prefix = location.protocol + process.env.API_ENDPOINT + Endpoints.SSO; window.location = `${prefix}?token=${AuthenticationStore.getToken()}&${querystring.stringify(query)}`; } }, () => { Dispatcher.dispatch({type: ActionTypes.LOGOUT}); } ); } }, handleSubmit(e) { e.preventDefault(); AuthenticationActionCreators.login(this.refs.email.value, this.refs.password.value); }, handleTokenSubmit(e) { e.preventDefault(); this.setState({loggingInViaMFA: true}); AuthenticationActionCreators.loginMFA(this.refs[CODE_REF].value, this.state.mfaTicket); }, handleForgotPassword() { const email = this.refs.email.value; AuthenticationActionCreators.forgotPassword(email, () => { ModalActionCreators.push(props => { return (

{i18n.Messages.EMAIL_VERIFICATION_INSTRUCTIONS_BODY.format({email})}

); }); }); }, render() { const {errors, loginStatus} = this.state; const hasError = field => errors[field] != null; const renderError = field => { if (hasError(field)) { return ({errors[field]}); } else { return null; } }; let header; let registerLink; const invite = this.props.invite; if (invite != null) { const channelName = invite.channel.type === ChannelTypes.GUILD_TEXT ? `#${invite.channel.name}` : invite.channel.name; const serverName = invite.guild.name; header = (

{i18n.Messages.LOGIN_TITLE}

{i18n.Messages.INSTANT_INVITE_RESOLVED_BODY.format({channelName, serverName})}

); registerLink = { pathname: Routes.INVITE(invite.code), query: { mode: 'register', }, }; } else { header =

{i18n.Messages.LOGIN_TITLE}

; registerLink = { pathname: Routes.REGISTER, query: this.props.location.query, }; } if (this.state.mfaTicket || this.state.loggingInViaMFA) { return ( {header}

{i18n.Messages.TWO_FA_ENTER_TOKEN_BODY}

{i18n.Messages.LOGIN}
); } return ( {header}
{i18n.Messages.LOGIN}
); }, }); export default Login; // WEBPACK FOOTER // // ./discord_app/components/Login.js