// 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 {addUserToTeamFromInvite} from 'actions/team_actions.jsx'; import {checkMfa, webLogin} from 'actions/user_actions.jsx'; import BrowserStore from 'stores/browser_store.jsx'; import UserStore from 'stores/user_store.jsx'; import Client from 'client/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/es6'; import React from 'react'; import logoImage from 'images/logo.png'; export default class LoginController extends React.Component { static get propTypes() { return { location: React.PropTypes.object.isRequired, params: React.PropTypes.object.isRequired }; } 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); let loginId = ''; if (this.props.location.query.extra === Constants.SIGNIN_VERIFIED && this.props.location.query.email) { loginId = this.props.location.query.email; } this.state = { ldapEnabled: global.window.mm_license.IsLicensed === 'true' && global.window.mm_config.EnableLdap === 'true', usernameSigninEnabled: global.window.mm_config.EnableSignInWithUsername === 'true', emailSigninEnabled: global.window.mm_config.EnableSignInWithEmail === 'true', samlEnabled: global.window.mm_license.IsLicensed === 'true' && global.window.mm_config.EnableSaml === 'true', loginId, password: '', showMfa: false, loading: false }; } componentDidMount() { document.title = global.window.mm_config.SiteName; BrowserStore.removeGlobalItem('team'); if (UserStore.getCurrentUser()) { GlobalActions.redirectUserToDefaultTeam(); } if (this.props.location.query.extra === Constants.SIGNIN_VERIFIED && this.props.location.query.email) { this.refs.password.focus(); } AsyncClient.checkVersion(); } preSubmit(e) { e.preventDefault(); // password managers don't always call onInput handlers for form fields so it's possible // for the state to get out of sync with what the user sees in the browser let loginId = this.refs.loginId.value; if (loginId !== this.state.loginId) { this.setState({loginId}); } const password = this.refs.password.value; if (password !== this.state.password) { this.setState({password}); } // don't trim the password since we support spaces in passwords loginId = loginId.trim(); if (!loginId) { // it's slightly weird to be constructing the message ID, but it's a bit nicer than triply nested if statements let msgId = 'login.no'; if (this.state.emailSigninEnabled) { msgId += 'Email'; } if (this.state.usernameSigninEnabled) { msgId += 'Username'; } if (this.state.ldapEnabled) { msgId += 'LdapUsername'; } this.setState({ serverError: ( ) }); return; } if (!password) { this.setState({ serverError: ( ) }); return; } checkMfa( loginId, (data) => { if (data && data.mfa_required === 'true') { this.setState({showMfa: true}); } else { this.submit(loginId, password, ''); } }, (err) => { this.setState({serverError: err.message}); } ); } submit(loginId, password, token) { this.setState({serverError: null, loading: true}); webLogin( loginId, password, token, () => { // check for query params brought over from signup_user_complete const hash = this.props.location.query.h; const data = this.props.location.query.d; const inviteId = this.props.location.query.id; if (inviteId || hash) { addUserToTeamFromInvite( data, hash, inviteId, (team) => { this.finishSignin(team); }, () => { // there's not really a good way to deal with this, so just let the user log in like normal this.finishSignin(); } ); return; } this.finishSignin(); }, (err) => { if (err.id === 'api.user.login.not_verified.app_error') { browserHistory.push('/should_verify_email?&email=' + encodeURIComponent(loginId)); } 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, loading: false, serverError: ( ) }); } 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, loading: false, serverError: ( ) }); } else { this.setState({showMfa: false, serverError: err.message, loading: false}); } } ); } finishSignin(team) { GlobalActions.emitInitialLoad( () => { const query = this.props.location.query; GlobalActions.loadDefaultLocale(); if (query.redirect_to) { browserHistory.push(query.redirect_to); } else if (team) { browserHistory.push(`/${team.name}`); } else { GlobalActions.redirectUserToDefaultTeam(); } } ); } 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 (

); } return null; } createLoginPlaceholder() { const ldapEnabled = this.state.ldapEnabled; const usernameSigninEnabled = this.state.usernameSigninEnabled; const emailSigninEnabled = this.state.emailSigninEnabled; 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.ldapUsername', 'AD/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 ''; } checkSignUpEnabled() { return global.window.mm_config.EnableSignUpWithEmail === 'true' || global.window.mm_config.EnableSignUpWithGitLab === 'true' || global.window.mm_config.EnableSignUpWithOffice365 === 'true' || global.window.mm_config.EnableSignUpWithGoogle === 'true' || global.window.mm_config.EnableLdap === 'true' || global.window.mm_config.EnableSaml === 'true'; } createLoginOptions() { const extraParam = this.props.location.query.extra; let extraBox = ''; if (extraParam) { if (extraParam === Constants.SIGNIN_CHANGE) { extraBox = (
); } else if (extraParam === Constants.SIGNIN_VERIFIED) { extraBox = (
); } else if (extraParam === Constants.SESSION_EXPIRED) { extraBox = (
); } else if (extraParam === Constants.PASSWORD_CHANGE) { extraBox = (
); } } const loginControls = []; const ldapEnabled = this.state.ldapEnabled; const gitlabSigninEnabled = global.window.mm_config.EnableSignUpWithGitLab === 'true'; const googleSigninEnabled = global.window.mm_config.EnableSignUpWithGoogle === 'true'; const office365SigninEnabled = global.window.mm_config.EnableSignUpWithOffice365 === 'true'; const samlSigninEnabled = this.state.samlEnabled; const usernameSigninEnabled = this.state.usernameSigninEnabled; const emailSigninEnabled = this.state.emailSigninEnabled; if (emailSigninEnabled || usernameSigninEnabled || ldapEnabled) { let errorClass = ''; if (this.state.serverError) { errorClass = ' has-error'; } let loginButton = (); if (this.state.loading) { loginButton = ( ); } loginControls.push(
); } if (global.window.mm_config.EnableOpenServer === 'true' && this.checkSignUpEnabled()) { loginControls.push(
); } if (usernameSigninEnabled || emailSigninEnabled) { loginControls.push(
); } if ((emailSigninEnabled || usernameSigninEnabled || ldapEnabled) && (gitlabSigninEnabled || googleSigninEnabled || samlSigninEnabled || office365SigninEnabled)) { loginControls.push(
); loginControls.push(
); } if (gitlabSigninEnabled) { loginControls.push( ); } if (googleSigninEnabled) { loginControls.push( ); } if (office365SigninEnabled) { loginControls.push( ); } if (samlSigninEnabled) { loginControls.push( {global.window.mm_config.SamlLoginButtonText} ); } if (loginControls.length === 0) { loginControls.push( } margin={true} /> ); } return (
{extraBox} {loginControls}
); } render() { let content; let customContent; let customClass; if (this.state.showMfa) { content = ( ); } else { content = this.createLoginOptions(); customContent = this.createCustomLogin(); if (customContent) { customClass = 'branded'; } } let description = null; if (global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.CustomBrand === 'true' && global.window.mm_config.EnableCustomBrand === 'true') { description = global.window.mm_config.CustomDescriptionText; } else { description = ( ); } return (
{customContent}

{global.window.mm_config.SiteName}

{description}

{content}
); } }