From f9a3a4b3949dddecae413b97904c895b2cd887bf Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Wed, 30 Mar 2016 12:49:29 -0400 Subject: Add MFA functionality --- webapp/components/login/login.jsx | 419 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 webapp/components/login/login.jsx (limited to 'webapp/components/login/login.jsx') diff --git a/webapp/components/login/login.jsx b/webapp/components/login/login.jsx new file mode 100644 index 000000000..7b370a939 --- /dev/null +++ b/webapp/components/login/login.jsx @@ -0,0 +1,419 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import LoginEmail from './components/login_email.jsx'; +import LoginUsername from './components/login_username.jsx'; +import LoginLdap from './components/login_ldap.jsx'; +import LoginMfa from './components/login_mfa.jsx'; + +import TeamStore from 'stores/team_store.jsx'; +import UserStore from 'stores/user_store.jsx'; + +import * as Client from 'utils/client.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'; + +export default class Login extends React.Component { + constructor(props) { + super(props); + + this.getStateFromStores = this.getStateFromStores.bind(this); + this.onTeamChange = this.onTeamChange.bind(this); + this.preSubmit = this.preSubmit.bind(this); + this.submit = this.submit.bind(this); + + this.state = this.getStateFromStores(); + } + componentDidMount() { + TeamStore.addChangeListener(this.onTeamChange); + Client.getMeLoggedIn((data) => { + if (data && data.logged_in !== 'false') { + browserHistory.push('/' + this.props.params.team + '/channels/town-square'); + } else { + this.setState({doneCheckLogin: true}); //eslint-disable-line react/no-did-mount-set-state + } + }); + } + componentWillUnmount() { + TeamStore.removeChangeListener(this.onTeamChange); + } + getStateFromStores() { + return { + currentTeam: TeamStore.getByName(this.props.params.team), + doneCheckLogin: false + }; + } + onTeamChange() { + this.setState(this.getStateFromStores()); + } + preSubmit(method, loginId, password) { + if (global.window.mm_config.EnableMultifactorAuthentication !== 'true') { + this.submit(method, loginId, password, ''); + return; + } + + Client.checkMfa(method, this.state.currentTeam.name, loginId, + (data) => { + if (data.mfa_required === 'true') { + this.setState({showMfa: true, method, loginId, password}); + } else { + this.submit(method, loginId, password, ''); + } + }, + (err) => { + if (method === Constants.EMAIL_SERVICE) { + this.setState({serverEmailError: err.message}); + } else if (method === Constants.USERNAME_SERVICE) { + this.setState({serverUsernameError: err.message}); + } else if (method === Constants.LDAP_SERVICE) { + this.setState({serverLdapError: err.message}); + } + } + ); + } + submit(method, loginId, password, token) { + this.setState({showMfa: false, serverEmailError: null, serverUsernameError: null, serverLdapError: null}); + + const team = this.state.currentTeam.name; + + if (method === Constants.EMAIL_SERVICE) { + Client.loginByEmail(team, loginId, password, token, + () => { + UserStore.setLastEmail(loginId); + browserHistory.push('/' + team + '/channels/town-square'); + }, + (err) => { + if (err.id === 'api.user.login.not_verified.app_error') { + browserHistory.push('/verify_email?teamname=' + encodeURIComponent(name) + '&email=' + encodeURIComponent(loginId)); + return; + } + this.setState({serverEmailError: err.message}); + } + ); + } else if (method === Constants.USERNAME_SERVICE) { + Client.loginByUsername(team, loginId, password, token, + () => { + UserStore.setLastUsername(loginId); + + const redirect = Utils.getUrlParameter('redirect'); + if (redirect) { + browserHistory.push(decodeURIComponent(redirect)); + } else { + browserHistory.push('/' + team + '/channels/town-square'); + } + }, + (err) => { + if (err.id === 'api.user.login.not_verified.app_error') { + this.setState({serverUsernameError: Utils.localizeMessage('login_username.verifyEmailError', 'Please verify your email address. Check your inbox for an email.')}); + } else if (err.id === 'store.sql_user.get_by_username.app_error') { + this.setState({serverUsernameError: Utils.localizeMessage('login_username.userNotFoundError', 'We couldn\'t find an existing account matching your username for this team.')}); + } else { + this.setState({serverUsernameError: err.message}); + } + } + ); + } else if (method === Constants.LDAP_SERVICE) { + Client.loginByLdap(team, loginId, password, token, + () => { + const redirect = Utils.getUrlParameter('redirect'); + if (redirect) { + browserHistory.push(decodeURIComponent(redirect)); + } else { + browserHistory.push('/' + team + '/channels/town-square'); + } + }, + (err) => { + this.setState({serverLdapError: err.message}); + } + ); + } + } + createLoginOptions(currentTeam) { + const extraParam = Utils.getUrlParameter('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 = ( +
+ + +
+ ); + } + } + + const teamName = currentTeam.name; + 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'; + + const oauthLogins = []; + if (gitlabSigninEnabled) { + oauthLogins.push( + + + + + + + ); + } + + if (googleSigninEnabled) { + oauthLogins.push( + + + + + + + ); + } + + let emailLogin; + if (emailSigninEnabled) { + emailLogin = ( + + ); + + if (oauthLogins.length > 0) { + emailLogin = ( +
+
+ +
+ {emailLogin} +
+ ); + } + } + + let usernameLogin; + if (usernameSigninEnabled) { + usernameLogin = ( + + ); + + if (emailSigninEnabled || oauthLogins.length > 0) { + usernameLogin = ( +
+
+ +
+ {usernameLogin} +
+ ); + } + } + + let ldapLogin; + if (ldapEnabled) { + ldapLogin = ( + + ); + + if (emailSigninEnabled || usernameSigninEnabled || oauthLogins.length > 0) { + ldapLogin = ( +
+
+ +
+ {ldapLogin} +
+ ); + } + } + + let userSignUp; + if (currentTeam.allow_open_invite) { + userSignUp = ( +
+ + + + + + +
+ ); + } + + let forgotPassword; + if (usernameSigninEnabled || emailSigninEnabled) { + forgotPassword = ( +
+ + + +
+ ); + } + + let teamSignUp; + if (global.window.mm_config.EnableTeamCreation === 'true' && !Utils.isMobileApp()) { + teamSignUp = ( +
+ + + +
+ ); + } + + return ( +
+ {extraBox} + {oauthLogins} + {emailLogin} + {usernameLogin} + {ldapLogin} + {userSignUp} + {forgotPassword} + {teamSignUp} +
+ ); + } + render() { + const currentTeam = this.state.currentTeam; + if (currentTeam == null || !this.state.doneCheckLogin) { + return
; + } + + let content; + if (this.state.showMfa) { + content = ( + + ); + } else { + content = this.createLoginOptions(currentTeam); + } + + return ( +
+
+ + + + +
+
+
+
+ +
+

{currentTeam.display_name}

+

+ +

+ {content} +
+
+
+ ); + } +} + +Login.defaultProps = { +}; +Login.propTypes = { + params: React.PropTypes.object.isRequired +}; -- cgit v1.2.3-1-g7c22