diff --git a/api/user.go b/api/user.go
index 60162d8f18..c53a643c71 100644
--- a/api/user.go
+++ b/api/user.go
@@ -436,6 +436,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
password := props["password"]
mfaToken := props["token"]
deviceId := props["device_id"]
+ ldapOnly := props["ldap_only"] == "true"
if len(password) == 0 {
c.Err = model.NewLocAppError("login", "api.user.login.blank_pwd.app_error", nil, "")
@@ -460,7 +461,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
c.LogAudit("attempt")
- if user, err = getUserForLogin(loginId); err != nil {
+ if user, err = getUserForLogin(loginId, ldapOnly); err != nil {
c.LogAudit("failure")
c.Err = err
return
@@ -485,13 +486,13 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(user.ToJson()))
}
-func getUserForLogin(loginId string) (*model.User, *model.AppError) {
+func getUserForLogin(loginId string, onlyLdap bool) (*model.User, *model.AppError) {
ldapAvailable := *utils.Cfg.LdapSettings.Enable && einterfaces.GetLdapInterface() != nil
if result := <-Srv.Store.User().GetForLogin(
loginId,
- *utils.Cfg.EmailSettings.EnableSignInWithUsername,
- *utils.Cfg.EmailSettings.EnableSignInWithEmail,
+ *utils.Cfg.EmailSettings.EnableSignInWithUsername && !onlyLdap,
+ *utils.Cfg.EmailSettings.EnableSignInWithEmail && !onlyLdap,
ldapAvailable,
); result.Err != nil {
diff --git a/api/user_test.go b/api/user_test.go
index 1a3b36d4b3..9dd57dc209 100644
--- a/api/user_test.go
+++ b/api/user_test.go
@@ -204,6 +204,23 @@ func TestLogin(t *testing.T) {
}
}
+func TestLoginByLdap(t *testing.T) {
+ th := Setup()
+ Client := th.CreateClient()
+
+ team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+ rteam, _ := Client.CreateTeam(&team)
+
+ user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Username: "corey" + model.NewId(), Password: "pwd"}
+ ruser, _ := Client.CreateUser(&user, "")
+ LinkUserToTeam(ruser.Data.(*model.User), rteam.Data.(*model.Team))
+ store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
+
+ if _, err := Client.LoginByLdap(ruser.Data.(*model.User).Id, user.Password); err == nil {
+ t.Fatal("should've failed to log in with non-ldap user")
+ }
+}
+
func TestLoginWithDeviceId(t *testing.T) {
th := Setup().InitBasic()
Client := th.BasicClient
diff --git a/model/client.go b/model/client.go
index 1575df9e0b..152aaa7067 100644
--- a/model/client.go
+++ b/model/client.go
@@ -362,6 +362,14 @@ func (c *Client) Login(loginId string, password string) (*Result, *AppError) {
return c.login(m)
}
+func (c *Client) LoginByLdap(loginId string, password string) (*Result, *AppError) {
+ m := make(map[string]string)
+ m["login_id"] = loginId
+ m["password"] = password
+ m["ldap_only"] = "true"
+ return c.login(m)
+}
+
func (c *Client) LoginWithDevice(loginId string, password string, deviceId string) (*Result, *AppError) {
m := make(map[string]string)
m["login_id"] = loginId
diff --git a/webapp/client/client.jsx b/webapp/client/client.jsx
index 5d0dd07c91..c81c5a1d78 100644
--- a/webapp/client/client.jsx
+++ b/webapp/client/client.jsx
@@ -759,6 +759,12 @@ export default class Client {
this.track('api', 'api_users_login', '', 'id', id);
}
+ loginByLdap = (loginId, password, mfaToken, success, error) => {
+ this.doLogin({login_id: loginId, password, token: mfaToken, ldap_only: 'true'}, success, error);
+
+ this.track('api', 'api_users_login', '', 'login_id', loginId);
+ }
+
doLogin = (outgoingData, success, error) => {
var outer = this; // eslint-disable-line consistent-this
diff --git a/webapp/components/signup_user_complete.jsx b/webapp/components/signup_user_complete.jsx
index 6dd26f391b..5c06cefedf 100644
--- a/webapp/components/signup_user_complete.jsx
+++ b/webapp/components/signup_user_complete.jsx
@@ -1,6 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import FormError from 'components/form_error.jsx';
import LoadingScreen from 'components/loading_screen.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
@@ -19,11 +20,15 @@ import ReactDOM from 'react-dom';
import logoImage from 'images/logo.png';
-class SignupUserComplete extends React.Component {
+export default class SignupUserComplete extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
+ this.handleLdapSignup = this.handleLdapSignup.bind(this);
+
+ this.handleLdapIdChange = this.handleLdapIdChange.bind(this);
+ this.handleLdapPasswordChange = this.handleLdapPasswordChange.bind(this);
this.state = {
data: '',
@@ -35,9 +40,12 @@ class SignupUserComplete extends React.Component {
teamId: '',
openServer: false,
loading: true,
- inviteId: ''
+ inviteId: '',
+ ldapId: '',
+ ldapPassword: ''
};
}
+
componentWillMount() {
let data = this.props.location.query.d;
let hash = this.props.location.query.h;
@@ -148,6 +156,48 @@ class SignupUserComplete extends React.Component {
});
}
+ handleLdapSignup(e) {
+ e.preventDefault();
+
+ this.setState({ldapError: ''});
+
+ Client.webLoginByLdap(
+ this.state.ldapId,
+ this.state.ldapPassword,
+ null,
+ () => {
+ GlobalActions.emitInitialLoad(
+ () => {
+ browserHistory.push('/select_team');
+ }
+ );
+ },
+ (err) => {
+ if (err.id === 'ent.ldap.do_login.user_not_registered.app_error' || err.id === 'ent.ldap.do_login.user_filtered.app_error') {
+ this.setState({
+ ldapError: (
+
+