diff options
Diffstat (limited to 'webapp/components/login/login_controller.jsx')
-rw-r--r-- | webapp/components/login/login_controller.jsx | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/webapp/components/login/login_controller.jsx b/webapp/components/login/login_controller.jsx new file mode 100644 index 000000000..c4a76f912 --- /dev/null +++ b/webapp/components/login/login_controller.jsx @@ -0,0 +1,453 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import LoginMfa from './components/login_mfa.jsx'; +import ErrorBar from 'components/error_bar.jsx'; +import FormError from 'components/form_error.jsx'; + +import * as GlobalActions from 'actions/global_actions.jsx'; +import UserStore from 'stores/user_store.jsx'; + +import Client from 'utils/web_client.jsx'; +import * as AsyncClient from 'utils/async_client.jsx'; +import * as TextFormatting from 'utils/text_formatting.jsx'; + +import * as Utils from 'utils/utils.jsx'; +import Constants from 'utils/constants.jsx'; + +import {FormattedMessage} from 'react-intl'; +import {browserHistory, Link} from 'react-router'; + +import React from 'react'; +import logoImage from 'images/logo.png'; + +export default class LoginController extends React.Component { + constructor(props) { + super(props); + + this.preSubmit = this.preSubmit.bind(this); + this.submit = this.submit.bind(this); + this.finishSignin = this.finishSignin.bind(this); + + this.handleLoginIdChange = this.handleLoginIdChange.bind(this); + this.handlePasswordChange = this.handlePasswordChange.bind(this); + + this.state = { + loginId: '', // the browser will set a default for this + password: '', + showMfa: false + }; + } + + componentDidMount() { + document.title = global.window.mm_config.SiteName; + + if (UserStore.getCurrentUser()) { + browserHistory.push('/select_team'); + } + + AsyncClient.checkVersion(); + } + + preSubmit(e) { + e.preventDefault(); + + const loginId = this.state.loginId.trim(); + const password = this.state.password; + + if (global.window.mm_config.EnableMultifactorAuthentication === 'true') { + Client.checkMfa( + loginId, + (data) => { + if (data.mfa_required === 'true') { + this.setState({showMfa: true}); + } else { + this.submit(loginId, password, ''); + } + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } else { + this.submit(loginId, password, ''); + } + } + + submit(loginId, password, token) { + Client.webLogin( + loginId, + password, + token, + () => { + this.setState({serverError: null}); + this.finishSignin(); + }, + (err) => { + if (err.id === 'api.user.login.not_verified.app_error') { + browserHistory.push('/should_verify_email?&email=' + encodeURIComponent(loginId)); + return; + } else if (err.id === 'store.sql_user.get_for_login.app_error' || + err.id === 'ent.ldap.do_login.user_not_registered.app_error') { + this.setState({ + showMfa: false, + serverError: ( + <FormattedMessage + id='login.userNotFound' + defaultMessage="We couldn't find an account matching your login credentials." + /> + ) + }); + } else if (err.id === 'api.user.check_user_password.invalid.app_error' || err.id === 'ent.ldap.do_login.invalid_password.app_error') { + this.setState({ + showMfa: false, + serverError: ( + <FormattedMessage + id='login.invalidPassword' + defaultMessage='Your password is incorrect.' + /> + ) + }); + } else { + this.setState({showMfa: false, serverError: err.message}); + } + } + ); + } + + finishSignin() { + GlobalActions.emitInitialLoad( + () => { + browserHistory.push('/select_team'); + } + ); + } + + handleLoginIdChange(e) { + this.setState({ + loginId: e.target.value + }); + } + + handlePasswordChange(e) { + this.setState({ + password: e.target.value + }); + } + + createCustomLogin() { + if (global.window.mm_license.IsLicensed === 'true' && + global.window.mm_license.CustomBrand === 'true' && + global.window.mm_config.EnableCustomBrand === 'true') { + const text = global.window.mm_config.CustomBrandText || ''; + + return ( + <div> + <img + src={Client.getAdminRoute() + '/get_brand_image'} + /> + <p dangerouslySetInnerHTML={{__html: TextFormatting.formatText(text)}}/> + </div> + ); + } + + return null; + } + + createLoginPlaceholder(emailSigninEnabled, usernameSigninEnabled, ldapEnabled) { + const loginPlaceholders = []; + if (emailSigninEnabled) { + loginPlaceholders.push(Utils.localizeMessage('login.email', 'Email')); + } + + if (usernameSigninEnabled) { + loginPlaceholders.push(Utils.localizeMessage('login.username', 'Username')); + } + + if (ldapEnabled) { + if (global.window.mm_config.LdapLoginFieldName) { + loginPlaceholders.push(global.window.mm_config.LdapLoginFieldName); + } else { + loginPlaceholders.push(Utils.localizeMessage('login.ldap_username', 'LDAP Username')); + } + } + + if (loginPlaceholders.length >= 2) { + return loginPlaceholders.slice(0, loginPlaceholders.length - 1).join(', ') + + Utils.localizeMessage('login.placeholderOr', ' or ') + + loginPlaceholders[loginPlaceholders.length - 1]; + } else if (loginPlaceholders.length === 1) { + return loginPlaceholders[0]; + } + + return ''; + } + + createLoginOptions() { + const extraParam = Utils.getUrlParameter('extra'); + let extraBox = ''; + if (extraParam) { + if (extraParam === Constants.SIGNIN_CHANGE) { + extraBox = ( + <div className='alert alert-success'> + <i className='fa fa-check'/> + <FormattedMessage + id='login.changed' + defaultMessage=' Sign-in method changed successfully' + /> + </div> + ); + } else if (extraParam === Constants.SIGNIN_VERIFIED) { + extraBox = ( + <div className='alert alert-success'> + <i className='fa fa-check'/> + <FormattedMessage + id='login.verified' + defaultMessage=' Email Verified' + /> + </div> + ); + } else if (extraParam === Constants.SESSION_EXPIRED) { + extraBox = ( + <div className='alert alert-warning'> + <i className='fa fa-exclamation-triangle'/> + <FormattedMessage + id='login.session_expired' + defaultMessage=' Your session has expired. Please login again.' + /> + </div> + ); + } else if (extraParam === Constants.PASSWORD_CHANGE) { + extraBox = ( + <div className='alert alert-success'> + <i className='fa fa-check'/> + <FormattedMessage + id='login.passwordChanged' + defaultMessage=' Password updated successfully' + /> + </div> + ); + } + } + + const loginControls = []; + + const ldapEnabled = global.window.mm_config.EnableLdap === 'true'; + const gitlabSigninEnabled = global.window.mm_config.EnableSignUpWithGitLab === 'true'; + const googleSigninEnabled = global.window.mm_config.EnableSignUpWithGoogle === 'true'; + const usernameSigninEnabled = global.window.mm_config.EnableSignInWithUsername === 'true'; + const emailSigninEnabled = global.window.mm_config.EnableSignInWithEmail === 'true'; + + if (emailSigninEnabled || usernameSigninEnabled || ldapEnabled) { + let errorClass = ''; + if (this.state.serverError) { + errorClass = ' has-error'; + } + + loginControls.push( + <form + key='loginBoxes' + onSubmit={this.preSubmit} + > + <div className='signup__email-container'> + <FormError error={this.state.serverError}/> + <div className={'form-group' + errorClass}> + <input + className='form-control' + name='loginId' + value={this.state.loginId} + onChange={this.handleLoginIdChange} + placeholder={this.createLoginPlaceholder(emailSigninEnabled, usernameSigninEnabled, ldapEnabled)} + spellCheck='false' + autoCapitalize='off' + /> + </div> + <div className={'form-group' + errorClass}> + <input + type='password' + className='form-control' + name='password' + value={this.state.password} + onChange={this.handlePasswordChange} + placeholder={Utils.localizeMessage('login.password', 'Password')} + spellCheck='false' + /> + </div> + <div className='form-group'> + <button + type='submit' + className='btn btn-primary' + disabled={!this.state.loginId || !this.state.password} + > + <FormattedMessage + id='login.signIn' + defaultMessage='Sign in' + /> + </button> + </div> + </div> + </form> + ); + } + + if (global.window.mm_config.EnableOpenServer === 'true') { + loginControls.push( + <div + className='form-group' + key='signup' + > + <span> + <FormattedMessage + id='login.noAccount' + defaultMessage="Don't have an account? " + /> + <Link + to={'/signup_user_complete'} + className='signup-team-login' + > + <FormattedMessage + id='login.create' + defaultMessage='Create one now' + /> + </Link> + </span> + </div> + ); + } + + if (usernameSigninEnabled || emailSigninEnabled) { + loginControls.push( + <div + key='forgotPassword' + className='form-group' + > + <Link to={'/reset_password'}> + <FormattedMessage + id='login.forgot' + defaultMessage='I forgot my password' + /> + </Link> + </div> + ); + } + + if ((emailSigninEnabled || usernameSigninEnabled || ldapEnabled) && (gitlabSigninEnabled || googleSigninEnabled)) { + loginControls.push( + <div + key='divider' + className='or__container' + > + <FormattedMessage + id='login.or' + defaultMessage='or' + /> + </div> + ); + + loginControls.push( + <h5 key='oauthHeader'> + <FormattedMessage + id='login.signInWith' + defaultMessage='Sign in with:' + /> + </h5> + ); + } + + if (gitlabSigninEnabled) { + loginControls.push( + <a + className='btn btn-custom-login gitlab' + key='gitlab' + href={Client.getOAuthRoute() + '/gitlab/login'} + > + <span className='icon'/> + <span> + <FormattedMessage + id='login.gitlab' + defaultMessage='GitLab' + /> + </span> + </a> + ); + } + + if (googleSigninEnabled) { + loginControls.push( + <Link + className='btn btn-custom-login google' + key='google' + to={Client.getOAuthRoute() + '/google/login'} + > + <span className='icon'/> + <span> + <FormattedMessage + id='login.google' + defaultMessage='Google Apps' + /> + </span> + </Link> + ); + } + + return ( + <div> + {extraBox} + {loginControls} + </div> + ); + } + + render() { + let content; + let customContent; + let customClass; + if (this.state.showMfa) { + content = ( + <LoginMfa + loginId={this.state.loginId} + password={this.state.password} + submit={this.submit} + /> + ); + } else { + content = this.createLoginOptions(); + customContent = this.createCustomLogin(); + if (customContent) { + customClass = 'branded'; + } + } + + return ( + <div> + <ErrorBar/> + <div className='col-sm-12'> + <div className={'signup-team__container ' + customClass}> + <div className='signup__markdown'> + {customContent} + </div> + <img + className='signup-team-logo' + src={logoImage} + /> + <div className='signup__content'> + <h1>{global.window.mm_config.SiteName}</h1> + <h4 className='color--light'> + <FormattedMessage + id='web.root.singup_info' + /> + </h4> + {content} + </div> + </div> + </div> + </div> + ); + } +} + +LoginController.defaultProps = { +}; +LoginController.propTypes = { + params: React.PropTypes.object.isRequired +}; |