From 463fd8c20b6e20d1cc669810c339770b9b1ede41 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Thu, 17 Mar 2016 15:46:16 -0400 Subject: Add the ability to switch from email to ldap and back --- api/user.go | 197 +++++++++++++++++++-- api/user_test.go | 145 +++++++++++++-- einterfaces/ldap.go | 1 + i18n/en.json | 14 +- i18n/es.json | 2 +- i18n/pt.json | 2 +- model/client.go | 26 ++- model/ldap.go | 8 + webapp/components/claim/claim.jsx | 88 +++++++++ webapp/components/claim/claim_account.jsx | 116 ------------ .../components/claim/components/email_to_ldap.jsx | 169 ++++++++++++++++++ .../components/claim/components/email_to_oauth.jsx | 139 +++++++++++++++ .../components/claim/components/ldap_to_email.jsx | 167 +++++++++++++++++ .../components/claim/components/oauth_to_email.jsx | 143 +++++++++++++++ webapp/components/claim/email_to_sso.jsx | 154 ---------------- webapp/components/claim/sso_to_email.jsx | 168 ------------------ .../user_settings/user_settings_security.jsx | 45 ++++- webapp/i18n/en.json | 55 ++++-- webapp/i18n/es.json | 30 ++-- webapp/i18n/pt.json | 30 ++-- webapp/root.jsx | 32 +++- webapp/utils/client.jsx | 50 +++++- webapp/utils/constants.jsx | 1 + 23 files changed, 1242 insertions(+), 540 deletions(-) create mode 100644 model/ldap.go create mode 100644 webapp/components/claim/claim.jsx delete mode 100644 webapp/components/claim/claim_account.jsx create mode 100644 webapp/components/claim/components/email_to_ldap.jsx create mode 100644 webapp/components/claim/components/email_to_oauth.jsx create mode 100644 webapp/components/claim/components/ldap_to_email.jsx create mode 100644 webapp/components/claim/components/oauth_to_email.jsx delete mode 100644 webapp/components/claim/email_to_sso.jsx delete mode 100644 webapp/components/claim/sso_to_email.jsx diff --git a/api/user.go b/api/user.go index aadf735d0..04bd673a8 100644 --- a/api/user.go +++ b/api/user.go @@ -51,8 +51,6 @@ func InitUser(r *mux.Router) { sr.Handle("/login_ldap", ApiAppHandler(loginLdap)).Methods("POST") sr.Handle("/revoke_session", ApiUserRequired(revokeSession)).Methods("POST") sr.Handle("/attach_device", ApiUserRequired(attachDeviceId)).Methods("POST") - sr.Handle("/switch_to_sso", ApiAppHandler(switchToSSO)).Methods("POST") - sr.Handle("/switch_to_email", ApiUserRequired(switchToEmail)).Methods("POST") sr.Handle("/verify_email", ApiAppHandler(verifyEmail)).Methods("POST") sr.Handle("/resend_verification", ApiAppHandler(resendVerification)).Methods("POST") @@ -67,6 +65,11 @@ func InitUser(r *mux.Router) { sr.Handle("/{id:[A-Za-z0-9]+}/sessions", ApiUserRequired(getSessions)).Methods("GET") sr.Handle("/{id:[A-Za-z0-9]+}/audits", ApiUserRequired(getAudits)).Methods("GET") sr.Handle("/{id:[A-Za-z0-9]+}/image", ApiUserRequired(getProfileImage)).Methods("GET") + + sr.Handle("/claim/email_to_oauth", ApiAppHandler(emailToOAuth)).Methods("POST") + sr.Handle("/claim/oauth_to_email", ApiUserRequired(oauthToEmail)).Methods("POST") + sr.Handle("/claim/email_to_ldap", ApiAppHandler(emailToLdap)).Methods("POST") + sr.Handle("/claim/ldap_to_email", ApiAppHandler(ldapToEmail)).Methods("POST") } func createUser(c *Context, w http.ResponseWriter, r *http.Request) { @@ -2047,30 +2050,30 @@ func IsUsernameTaken(name string, teamId string) bool { return false } -func switchToSSO(c *Context, w http.ResponseWriter, r *http.Request) { +func emailToOAuth(c *Context, w http.ResponseWriter, r *http.Request) { props := model.MapFromJson(r.Body) password := props["password"] if len(password) == 0 { - c.SetInvalidParam("switchToSSO", "password") + c.SetInvalidParam("emailToOAuth", "password") return } teamName := props["team_name"] if len(teamName) == 0 { - c.SetInvalidParam("switchToSSO", "team_name") + c.SetInvalidParam("emailToOAuth", "team_name") return } service := props["service"] if len(service) == 0 { - c.SetInvalidParam("switchToSSO", "service") + c.SetInvalidParam("emailToOAuth", "service") return } email := props["email"] if len(email) == 0 { - c.SetInvalidParam("switchToSSO", "email") + c.SetInvalidParam("emailToOAuth", "email") return } @@ -2162,24 +2165,24 @@ func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request, sendSignInChangeEmailAndForget(c, user.Email, team.DisplayName, c.GetSiteURL()+"/"+team.Name, c.GetSiteURL(), strings.Title(service)+" SSO") } -func switchToEmail(c *Context, w http.ResponseWriter, r *http.Request) { +func oauthToEmail(c *Context, w http.ResponseWriter, r *http.Request) { props := model.MapFromJson(r.Body) password := props["password"] if len(password) == 0 { - c.SetInvalidParam("switchToEmail", "password") + c.SetInvalidParam("oauthToEmail", "password") return } teamName := props["team_name"] if len(teamName) == 0 { - c.SetInvalidParam("switchToEmail", "team_name") + c.SetInvalidParam("oauthToEmail", "team_name") return } email := props["email"] if len(email) == 0 { - c.SetInvalidParam("switchToEmail", "email") + c.SetInvalidParam("oauthToEmail", "email") return } @@ -2205,7 +2208,7 @@ func switchToEmail(c *Context, w http.ResponseWriter, r *http.Request) { if user.Id != c.Session.UserId { c.LogAudit("fail - user ids didn't match") - c.Err = model.NewLocAppError("switchToEmail", "api.user.switch_to_email.context.app_error", nil, "") + c.Err = model.NewLocAppError("oauthToEmail", "api.user.oauth_to_email.context.app_error", nil, "") c.Err.StatusCode = http.StatusForbidden return } @@ -2230,6 +2233,176 @@ func switchToEmail(c *Context, w http.ResponseWriter, r *http.Request) { w.Write([]byte(model.MapToJson(m))) } +func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) { + props := model.MapFromJson(r.Body) + + email := props["email"] + if len(email) == 0 { + c.SetInvalidParam("emailToLdap", "email") + return + } + + emailPassword := props["email_password"] + if len(emailPassword) == 0 { + c.SetInvalidParam("emailToLdap", "email_password") + return + } + + teamName := props["team_name"] + if len(teamName) == 0 { + c.SetInvalidParam("emailToLdap", "team_name") + return + } + + ldapId := props["ldap_id"] + if len(ldapId) == 0 { + c.SetInvalidParam("emailToLdap", "ldap_id") + return + } + + ldapPassword := props["ldap_password"] + if len(ldapPassword) == 0 { + c.SetInvalidParam("emailToLdap", "ldap_password") + return + } + + c.LogAudit("attempt") + + var team *model.Team + if result := <-Srv.Store.Team().GetByName(teamName); result.Err != nil { + c.LogAudit("fail - couldn't get team") + c.Err = result.Err + return + } else { + team = result.Data.(*model.Team) + } + + var user *model.User + if result := <-Srv.Store.User().GetByEmail(team.Id, email); result.Err != nil { + c.LogAudit("fail - couldn't get user") + c.Err = result.Err + return + } else { + user = result.Data.(*model.User) + } + + if !checkUserLoginAttempts(c, user) || !checkUserPassword(c, user, emailPassword) { + c.LogAuditWithUserId(user.Id, "fail - invalid email password") + return + } + + RevokeAllSession(c, user.Id) + if c.Err != nil { + return + } + + ldapInterface := einterfaces.GetLdapInterface() + if ldapInterface == nil { + c.Err = model.NewLocAppError("emailToLdap", "api.user.email_to_ldap.not_available.app_error", nil, "") + c.Err.StatusCode = http.StatusNotImplemented + return + } + + if err := ldapInterface.DoSwitch(user.Id, ldapId, ldapPassword); err != nil { + c.LogAuditWithUserId(user.Id, "fail - ldap switch failed") + c.Err = err + return + } + + sendSignInChangeEmailAndForget(c, user.Email, team.DisplayName, c.GetSiteURL()+"/"+team.Name, c.GetSiteURL(), "LDAP") + + m := map[string]string{} + m["follow_link"] = c.GetTeamURL() + "/login?extra=signin_change" + + c.LogAudit("success") + w.Write([]byte(model.MapToJson(m))) +} + +func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) { + props := model.MapFromJson(r.Body) + + email := props["email"] + if len(email) == 0 { + c.SetInvalidParam("ldapToEmail", "email") + return + } + + emailPassword := props["email_password"] + if len(emailPassword) == 0 { + c.SetInvalidParam("ldapToEmail", "email_password") + return + } + + teamName := props["team_name"] + if len(teamName) == 0 { + c.SetInvalidParam("ldapToEmail", "team_name") + return + } + + ldapPassword := props["ldap_password"] + if len(ldapPassword) == 0 { + c.SetInvalidParam("ldapToEmail", "ldap_password") + return + } + + c.LogAudit("attempt") + + var team *model.Team + if result := <-Srv.Store.Team().GetByName(teamName); result.Err != nil { + c.LogAudit("fail - couldn't get team") + c.Err = result.Err + return + } else { + team = result.Data.(*model.Team) + } + + var user *model.User + if result := <-Srv.Store.User().GetByEmail(team.Id, email); result.Err != nil { + c.LogAudit("fail - couldn't get user") + c.Err = result.Err + return + } else { + user = result.Data.(*model.User) + } + + if user.AuthService != model.USER_AUTH_SERVICE_LDAP { + c.Err = model.NewLocAppError("ldapToEmail", "api.user.ldap_to_email.not_ldap_account.app_error", nil, "") + return + } + + ldapInterface := einterfaces.GetLdapInterface() + if ldapInterface == nil { + c.Err = model.NewLocAppError("ldapToEmail", "api.user.ldap_to_email.not_available.app_error", nil, "") + c.Err.StatusCode = http.StatusNotImplemented + return + } + + if err := ldapInterface.CheckPassword(user.AuthData, ldapPassword); err != nil { + c.LogAuditWithUserId(user.Id, "fail - ldap authentication failed") + c.Err = err + return + } + + if result := <-Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(emailPassword)); result.Err != nil { + c.LogAudit("fail - database issue") + c.Err = result.Err + return + } + + RevokeAllSession(c, user.Id) + if c.Err != nil { + return + } + + sendSignInChangeEmailAndForget(c, user.Email, team.DisplayName, c.GetSiteURL()+"/"+team.Name, c.GetSiteURL(), c.T("api.templates.signin_change_email.body.method_email")) + + m := map[string]string{} + m["follow_link"] = c.GetTeamURL() + "/login?extra=signin_change" + + c.LogAudit("success") + w.Write([]byte(model.MapToJson(m))) +} + func sendSignInChangeEmailAndForget(c *Context, email, teamDisplayName, teamURL, siteURL, method string) { go func() { diff --git a/api/user_test.go b/api/user_test.go index a175adb1b..86cda0390 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -1161,7 +1161,7 @@ func TestStatuses(t *testing.T) { } -func TestSwitchToSSO(t *testing.T) { +func TestEmailToOAuth(t *testing.T) { Setup() team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} @@ -1172,45 +1172,45 @@ func TestSwitchToSSO(t *testing.T) { store.Must(Srv.Store.User().VerifyEmail(ruser.Id)) m := map[string]string{} - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.EmailToOAuth(m); err == nil { t.Fatal("should have failed - empty data") } m["password"] = "pwd" - _, err := Client.SwitchToSSO(m) + _, err := Client.EmailToOAuth(m) if err == nil { t.Fatal("should have failed - missing team_name, service, email") } m["team_name"] = team.Name - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.EmailToOAuth(m); err == nil { t.Fatal("should have failed - missing service, email") } m["service"] = "someservice" - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.EmailToOAuth(m); err == nil { t.Fatal("should have failed - missing email") } m["team_name"] = "junk" - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.EmailToOAuth(m); err == nil { t.Fatal("should have failed - bad team name") } m["team_name"] = team.Name m["email"] = "junk" - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.EmailToOAuth(m); err == nil { t.Fatal("should have failed - bad email") } m["email"] = ruser.Email m["password"] = "junk" - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.EmailToOAuth(m); err == nil { t.Fatal("should have failed - bad password") } } -func TestSwitchToEmail(t *testing.T) { +func TestOAuthToEmail(t *testing.T) { Setup() team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN} @@ -1225,45 +1225,158 @@ func TestSwitchToEmail(t *testing.T) { store.Must(Srv.Store.User().VerifyEmail(ruser2.Id)) m := map[string]string{} - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.OAuthToEmail(m); err == nil { t.Fatal("should have failed - not logged in") } Client.LoginByEmail(team.Name, user.Email, user.Password) - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.OAuthToEmail(m); err == nil { t.Fatal("should have failed - empty data") } m["password"] = "pwd" - _, err := Client.SwitchToSSO(m) + _, err := Client.OAuthToEmail(m) if err == nil { t.Fatal("should have failed - missing team_name, service, email") } m["team_name"] = team.Name - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.OAuthToEmail(m); err == nil { t.Fatal("should have failed - missing email") } m["email"] = ruser.Email m["team_name"] = "junk" - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.OAuthToEmail(m); err == nil { t.Fatal("should have failed - bad team name") } m["team_name"] = team.Name m["email"] = "junk" - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.OAuthToEmail(m); err == nil { t.Fatal("should have failed - bad email") } m["email"] = ruser2.Email - if _, err := Client.SwitchToSSO(m); err == nil { + if _, err := Client.OAuthToEmail(m); err == nil { t.Fatal("should have failed - wrong user") } } +func TestLDAPToEmail(t *testing.T) { + Setup() + + 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{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} + ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User) + store.Must(Srv.Store.User().VerifyEmail(ruser.Id)) + + Client.LoginByEmail(team.Name, user.Email, user.Password) + + m := map[string]string{} + if _, err := Client.LDAPToEmail(m); err == nil { + t.Fatal("should have failed - empty data") + } + + m["email_password"] = "pwd" + _, err := Client.LDAPToEmail(m) + if err == nil { + t.Fatal("should have failed - missing team_name, ldap_password, email") + } + + m["team_name"] = team.Name + if _, err := Client.LDAPToEmail(m); err == nil { + t.Fatal("should have failed - missing email, ldap_password") + } + + m["ldap_password"] = "pwd" + if _, err := Client.LDAPToEmail(m); err == nil { + t.Fatal("should have failed - missing email") + } + + m["email"] = ruser.Email + m["team_name"] = "junk" + if _, err := Client.LDAPToEmail(m); err == nil { + t.Fatal("should have failed - bad team name") + } + + m["team_name"] = team.Name + m["email"] = "junk" + if _, err := Client.LDAPToEmail(m); err == nil { + t.Fatal("should have failed - bad email") + } + + m["email"] = user.Email + if _, err := Client.LDAPToEmail(m); err == nil { + t.Fatal("should have failed - user is not an LDAP user") + } +} + +func TestEmailToLDAP(t *testing.T) { + Setup() + + 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{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"} + ruser := Client.Must(Client.CreateUser(&user, "")).Data.(*model.User) + store.Must(Srv.Store.User().VerifyEmail(ruser.Id)) + + Client.LoginByEmail(team.Name, user.Email, user.Password) + + m := map[string]string{} + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - empty data") + } + + m["email_password"] = "pwd" + _, err := Client.EmailToLDAP(m) + if err == nil { + t.Fatal("should have failed - missing team_name, ldap_id, ldap_password, email") + } + + m["team_name"] = team.Name + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - missing email, ldap_password, ldap_id") + } + + m["ldap_id"] = "someid" + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - missing email, ldap_password") + } + + m["ldap_password"] = "pwd" + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - missing email") + } + + m["email"] = ruser.Email + m["team_name"] = "junk" + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - bad team name") + } + + m["team_name"] = team.Name + m["email"] = "junk" + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - bad email") + } + + m["email"] = user.Email + m["email_password"] = "junk" + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - bad password") + } + + m["email_password"] = "pwd" + if _, err := Client.EmailToLDAP(m); err == nil { + t.Fatal("should have failed - missing ldap bits or user") + } +} + func TestMeLoggedIn(t *testing.T) { Setup() diff --git a/einterfaces/ldap.go b/einterfaces/ldap.go index 1c5938322..583fa02c0 100644 --- a/einterfaces/ldap.go +++ b/einterfaces/ldap.go @@ -11,6 +11,7 @@ type LdapInterface interface { DoLogin(team *model.Team, id string, password string) (*model.User, *model.AppError) GetUser(id string) (*model.User, *model.AppError) CheckPassword(id string, password string) *model.AppError + DoSwitch(userId, ldapId, ldapPassword string) *model.AppError } var theLdapInterface LdapInterface diff --git a/i18n/en.json b/i18n/en.json index 3180e8dbc..6811d86e3 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1540,9 +1540,21 @@ "translation": "Failed to send welcome email successfully err=%v" }, { - "id": "api.user.switch_to_email.context.app_error", + "id": "api.user.oauth_to_email.context.app_error", "translation": "Update password failed because context user_id did not match provided user's id" }, + { + "id": "api.user.email_to_ldap.not_available.app_error", + "translation": "LDAP not available on this server" + }, + { + "id": "api.user.ldap_to_email.not_ldap_account.app_error", + "translation": "This user account does use LDAP" + }, + { + "id": "api.user.ldap_to_email.not_available.app_error", + "translation": "LDAP not available on this server" + }, { "id": "api.user.update_active.permissions.app_error", "translation": "You do not have the appropriate permissions" diff --git a/i18n/es.json b/i18n/es.json index 97471ee98..2c062dd00 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -1540,7 +1540,7 @@ "translation": "Falla al enviar el correo de bienvenida err=%v" }, { - "id": "api.user.switch_to_email.context.app_error", + "id": "api.user.oauth_to_email.context.app_error", "translation": "La actualización de la contraseña falló porque el user_id del contexto no coincide con el id de usuario provisto" }, { diff --git a/i18n/pt.json b/i18n/pt.json index 15bc42835..6bcf9e072 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -1540,7 +1540,7 @@ "translation": "Falha ao enviar com sucesso boas vindas por email err=%v" }, { - "id": "api.user.switch_to_email.context.app_error", + "id": "api.user.oauth_to_email.context.app_error", "translation": "Atualização de senha falhou devido ao contexto user_id não combinar com id de usuário fornecido" }, { diff --git a/model/client.go b/model/client.go index f5c8ad641..ee26ae64e 100644 --- a/model/client.go +++ b/model/client.go @@ -332,8 +332,8 @@ func (c *Client) GetSessions(id string) (*Result, *AppError) { } } -func (c *Client) SwitchToSSO(m map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/users/switch_to_sso", MapToJson(m)); err != nil { +func (c *Client) EmailToOAuth(m map[string]string) (*Result, *AppError) { + if r, err := c.DoApiPost("/users/claim/email_to_sso", MapToJson(m)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -341,8 +341,26 @@ func (c *Client) SwitchToSSO(m map[string]string) (*Result, *AppError) { } } -func (c *Client) SwitchToEmail(m map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/users/switch_to_email", MapToJson(m)); err != nil { +func (c *Client) OAuthToEmail(m map[string]string) (*Result, *AppError) { + if r, err := c.DoApiPost("/users/claim/oauth_to_email", MapToJson(m)); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + } +} + +func (c *Client) LDAPToEmail(m map[string]string) (*Result, *AppError) { + if r, err := c.DoApiPost("/users/claim/ldap_to_email", MapToJson(m)); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + } +} + +func (c *Client) EmailToLDAP(m map[string]string) (*Result, *AppError) { + if r, err := c.DoApiPost("/users/claim/ldap_to_email", MapToJson(m)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), diff --git a/model/ldap.go b/model/ldap.go new file mode 100644 index 000000000..5fde06a6e --- /dev/null +++ b/model/ldap.go @@ -0,0 +1,8 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +const ( + USER_AUTH_SERVICE_LDAP = "ldap" +) diff --git a/webapp/components/claim/claim.jsx b/webapp/components/claim/claim.jsx new file mode 100644 index 000000000..0254897f9 --- /dev/null +++ b/webapp/components/claim/claim.jsx @@ -0,0 +1,88 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import TeamStore from '../../stores/team_store.jsx'; + +import React from 'react'; +import {FormattedMessage} from 'react-intl'; + +import logoImage from 'images/logo.png'; + +export default class Claim extends React.Component { + constructor(props) { + super(props); + + this.onTeamChange = this.onTeamChange.bind(this); + this.updateStateFromStores = this.updateStateFromStores.bind(this); + + this.state = {}; + } + componentWillMount() { + this.setState({ + email: this.props.location.query.email, + newType: this.props.location.query.new_type, + oldType: this.props.location.query.old_type, + teamName: this.props.params.team, + teamDisplayName: '' + }); + this.updateStateFromStores(); + } + componentDidMount() { + TeamStore.addChangeListener(this.onTeamChange); + } + componentWillUnmount() { + TeamStore.removeChangeListener(this.onTeamChange); + } + updateStateFromStores() { + const team = TeamStore.getByName(this.state.teamName); + let displayName = ''; + if (team) { + displayName = team.display_name; + } + this.setState({ + teamDisplayName: displayName + }); + } + onTeamChange() { + this.updateStateFromStores(); + } + render() { + return ( +
+
+ + + + +
+
+
+ +
+ {React.cloneElement(this.props.children, { + teamName: this.state.teamName, + teamDisplayName: this.state.teamDisplayName, + currentType: this.state.oldType, + newType: this.state.newType, + email: this.state.email + })} +
+
+
+
+ ); + } +} + +Claim.defaultProps = { +}; +Claim.propTypes = { + params: React.PropTypes.object.isRequired, + location: React.PropTypes.object.isRequired, + children: React.PropTypes.node +}; diff --git a/webapp/components/claim/claim_account.jsx b/webapp/components/claim/claim_account.jsx deleted file mode 100644 index b6495e283..000000000 --- a/webapp/components/claim/claim_account.jsx +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import EmailToSSO from './email_to_sso.jsx'; -import SSOToEmail from './sso_to_email.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import {FormattedMessage} from 'react-intl'; - -import React from 'react'; -import logoImage from 'images/logo.png'; - -export default class ClaimAccount extends React.Component { - constructor(props) { - super(props); - - this.onTeamChange = this.onTeamChange.bind(this); - this.updateStateFromStores = this.updateStateFromStores.bind(this); - - this.state = {}; - } - componentWillMount() { - this.setState({ - email: this.props.location.query.email, - newType: this.props.location.query.new_type, - oldType: this.props.location.query.old_type, - teamName: this.props.params.team, - teamDisplayName: '' - }); - this.updateStateFromStores(); - } - componentDidMount() { - TeamStore.addChangeListener(this.onTeamChange); - } - componentWillUnmount() { - TeamStore.removeChangeListener(this.onTeamChange); - } - updateStateFromStores() { - const team = TeamStore.getByName(this.state.teamName); - let displayName = ''; - if (team) { - displayName = team.displayName; - } - this.setState({ - teamDisplayName: displayName - }); - } - onTeamChange() { - this.updateStateFromStores(); - } - render() { - if (this.state.teamDisplayName === '') { - return (
); - } - let content; - if (this.state.email === '') { - content = ( -

- -

- ); - } else if (this.state.oldType === '' && this.state.newType !== '') { - content = ( - - ); - } else { - content = ( - - ); - } - - return ( -
- -
-
- -
- {content} -
-
-
-
- ); - } -} - -ClaimAccount.defaultProps = { -}; -ClaimAccount.propTypes = { - params: React.PropTypes.object.isRequired, - location: React.PropTypes.object.isRequired -}; diff --git a/webapp/components/claim/components/email_to_ldap.jsx b/webapp/components/claim/components/email_to_ldap.jsx new file mode 100644 index 000000000..bb2a3f0ed --- /dev/null +++ b/webapp/components/claim/components/email_to_ldap.jsx @@ -0,0 +1,169 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import * as Utils from '../../../utils/utils.jsx'; +import * as Client from '../../../utils/client.jsx'; + +import React from 'react'; +import ReactDOM from 'react-dom'; +import {FormattedMessage} from 'react-intl'; + +export default class EmailToLDAP extends React.Component { + constructor(props) { + super(props); + + this.submit = this.submit.bind(this); + + this.state = {}; + } + submit(e) { + e.preventDefault(); + var state = {}; + + const password = ReactDOM.findDOMNode(this.refs.password).value.trim(); + if (!password) { + state.error = Utils.localizeMessage('claim.email_to_ldap.pwdError', 'Please enter your password.'); + this.setState(state); + return; + } + + const ldapId = ReactDOM.findDOMNode(this.refs.ldapid).value.trim(); + if (!ldapId) { + state.error = Utils.localizeMessage('claim.email_to_ldap.ldapIdError', 'Please enter your LDAP ID.'); + this.setState(state); + return; + } + + const ldapPassword = ReactDOM.findDOMNode(this.refs.ldappassword).value.trim(); + if (!ldapPassword) { + state.error = Utils.localizeMessage('claim.email_to_ldap.ldapPasswordError', 'Please enter your LDAP password.'); + this.setState(state); + return; + } + + state.error = null; + this.setState(state); + + var postData = {}; + postData.email_password = password; + postData.ldap_id = ldapId; + postData.ldap_password = ldapPassword; + postData.email = this.props.email; + postData.team_name = this.props.teamName; + + Client.emailToLDAP(postData, + (data) => { + if (data.follow_link) { + window.location.href = data.follow_link; + } + }, + (error) => { + this.setState({error}); + } + ); + } + render() { + var error = null; + if (this.state.error) { + error =
; + } + + var formClass = 'form-group'; + if (error) { + formClass += ' has-error'; + } + + return ( +
+

+ +

+
+

+ +

+

+ +

+

+ +

+
+ +
+

+ +

+
+ +
+
+ +
+ {error} + +
+
+ ); + } +} + +EmailToLDAP.defaultProps = { +}; +EmailToLDAP.propTypes = { + email: React.PropTypes.string, + teamName: React.PropTypes.string, + teamDisplayName: React.PropTypes.string +}; diff --git a/webapp/components/claim/components/email_to_oauth.jsx b/webapp/components/claim/components/email_to_oauth.jsx new file mode 100644 index 000000000..51549423d --- /dev/null +++ b/webapp/components/claim/components/email_to_oauth.jsx @@ -0,0 +1,139 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import * as Utils from '../../../utils/utils.jsx'; +import * as Client from '../../../utils/client.jsx'; + +import React from 'react'; +import ReactDOM from 'react-dom'; +import {FormattedMessage} from 'react-intl'; + +export default class EmailToOAuth extends React.Component { + constructor(props) { + super(props); + + this.submit = this.submit.bind(this); + + this.state = {}; + } + submit(e) { + e.preventDefault(); + var state = {}; + + var password = ReactDOM.findDOMNode(this.refs.password).value.trim(); + if (!password) { + state.error = Utils.localizeMessage('claim.email_to_oauth.pwdError', 'Please enter your password.'); + this.setState(state); + return; + } + + state.error = null; + this.setState(state); + + var postData = {}; + postData.password = password; + postData.email = this.props.email; + postData.team_name = this.props.teamName; + postData.service = this.props.newType; + + Client.emailToOAuth(postData, + (data) => { + if (data.follow_link) { + window.location.href = data.follow_link; + } + }, + (error) => { + this.setState({error}); + } + ); + } + render() { + var error = null; + if (this.state.error) { + error =
; + } + + var formClass = 'form-group'; + if (error) { + formClass += ' has-error'; + } + + const uiType = Utils.toTitleCase(this.props.newType) + ' SSO'; + + return ( +
+

+ +

+
+

+ +

+

+ +

+

+ +

+
+ +
+ {error} + +
+
+ ); + } +} + +EmailToOAuth.defaultProps = { +}; +EmailToOAuth.propTypes = { + newType: React.PropTypes.string, + email: React.PropTypes.string, + teamName: React.PropTypes.string, + teamDisplayName: React.PropTypes.string +}; diff --git a/webapp/components/claim/components/ldap_to_email.jsx b/webapp/components/claim/components/ldap_to_email.jsx new file mode 100644 index 000000000..d645819b5 --- /dev/null +++ b/webapp/components/claim/components/ldap_to_email.jsx @@ -0,0 +1,167 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import * as Utils from '../../../utils/utils.jsx'; +import * as Client from '../../../utils/client.jsx'; + +import React from 'react'; +import ReactDOM from 'react-dom'; +import {FormattedMessage} from 'react-intl'; + +export default class LDAPToEmail extends React.Component { + constructor(props) { + super(props); + + this.submit = this.submit.bind(this); + + this.state = {}; + } + submit(e) { + e.preventDefault(); + var state = {}; + + const password = ReactDOM.findDOMNode(this.refs.password).value.trim(); + if (!password) { + state.error = Utils.localizeMessage('claim.ldap_to_email.pwdError', 'Please enter your password.'); + this.setState(state); + return; + } + + const confirmPassword = ReactDOM.findDOMNode(this.refs.passwordconfirm).value.trim(); + if (!confirmPassword || password !== confirmPassword) { + state.error = Utils.localizeMessage('claim.ldap_to_email.pwdNotMatch', 'Passwords do not match.'); + this.setState(state); + return; + } + + const ldapPassword = ReactDOM.findDOMNode(this.refs.ldappassword).value.trim(); + if (!ldapPassword) { + state.error = Utils.localizeMessage('claim.ldap_to_email.ldapPasswordError', 'Please enter your LDAP password.'); + this.setState(state); + return; + } + + state.error = null; + this.setState(state); + + var postData = {}; + postData.email_password = password; + postData.ldap_password = ldapPassword; + postData.email = this.props.email; + postData.team_name = this.props.teamName; + + Client.ldapToEmail(postData, + (data) => { + if (data.follow_link) { + window.location.href = data.follow_link; + } + }, + (error) => { + this.setState({error}); + } + ); + } + render() { + var error = null; + if (this.state.error) { + error =
; + } + + var formClass = 'form-group'; + if (error) { + formClass += ' has-error'; + } + + return ( +
+

+ +

+
+

+ +

+

+ +

+

+ +

+
+ +
+

+ +

+
+ +
+
+ +
+ {error} + +
+
+ ); + } +} + +LDAPToEmail.defaultProps = { +}; +LDAPToEmail.propTypes = { + email: React.PropTypes.string, + teamName: React.PropTypes.string, + teamDisplayName: React.PropTypes.string +}; diff --git a/webapp/components/claim/components/oauth_to_email.jsx b/webapp/components/claim/components/oauth_to_email.jsx new file mode 100644 index 000000000..11246bea7 --- /dev/null +++ b/webapp/components/claim/components/oauth_to_email.jsx @@ -0,0 +1,143 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import * as Utils from '../../../utils/utils.jsx'; +import * as Client from '../../../utils/client.jsx'; + +import React from 'react'; +import ReactDOM from 'react-dom'; +import {FormattedMessage} from 'react-intl'; + +export default class OAuthToEmail extends React.Component { + constructor(props) { + super(props); + + this.submit = this.submit.bind(this); + + this.state = {}; + } + submit(e) { + e.preventDefault(); + const state = {}; + + const password = ReactDOM.findDOMNode(this.refs.password).value.trim(); + if (!password) { + state.error = Utils.localizeMessage('claim.oauth_to_email.enterPwd', 'Please enter a password.'); + this.setState(state); + return; + } + + const confirmPassword = ReactDOM.findDOMNode(this.refs.passwordconfirm).value.trim(); + if (!confirmPassword || password !== confirmPassword) { + state.error = Utils.localizeMessage('claim.oauth_to_email.pwdNotMatch', 'Password do not match.'); + this.setState(state); + return; + } + + state.error = null; + this.setState(state); + + var postData = {}; + postData.password = password; + postData.email = this.props.email; + postData.team_name = this.props.teamName; + + Client.oauthToEmail(postData, + (data) => { + if (data.follow_link) { + window.location.href = data.follow_link; + } + }, + (error) => { + this.setState({error}); + } + ); + } + render() { + var error = null; + if (this.state.error) { + error =
; + } + + var formClass = 'form-group'; + if (error) { + formClass += ' has-error'; + } + + const uiType = Utils.toTitleCase(this.props.currentType) + ' SSO'; + + return ( +
+

+ +

+
+

+ +

+

+ +

+
+ +
+
+ +
+ {error} + +
+
+ ); + } +} + +OAuthToEmail.defaultProps = { +}; +OAuthToEmail.propTypes = { + teamName: React.PropTypes.string, + teamDisplayName: React.PropTypes.string, + currentType: React.PropTypes.string, + email: React.PropTypes.string +}; diff --git a/webapp/components/claim/email_to_sso.jsx b/webapp/components/claim/email_to_sso.jsx deleted file mode 100644 index d09449247..000000000 --- a/webapp/components/claim/email_to_sso.jsx +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import ReactDOM from 'react-dom'; -import * as Utils from 'utils/utils.jsx'; -import * as Client from 'utils/client.jsx'; - -import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl'; - -const holders = defineMessages({ - pwdError: { - id: 'claim.email_to_sso.pwdError', - defaultMessage: 'Please enter your password.' - }, - pwd: { - id: 'claim.email_to_sso.pwd', - defaultMessage: 'Password' - } -}); - -import React from 'react'; - -class EmailToSSO extends React.Component { - constructor(props) { - super(props); - - this.submit = this.submit.bind(this); - - this.state = {}; - } - submit(e) { - e.preventDefault(); - var state = {}; - - var password = ReactDOM.findDOMNode(this.refs.password).value.trim(); - if (!password) { - state.error = this.props.intl.formatMessage(holders.pwdError); - this.setState(state); - return; - } - - state.error = null; - this.setState(state); - - var postData = {}; - postData.password = password; - postData.email = this.props.email; - postData.team_name = this.props.teamName; - postData.service = this.props.type; - - Client.switchToSSO(postData, - (data) => { - if (data.follow_link) { - window.location.href = data.follow_link; - } - }, - (error) => { - this.setState({error}); - } - ); - } - render() { - var error = null; - if (this.state.error) { - error =
; - } - - var formClass = 'form-group'; - if (error) { - formClass += ' has-error'; - } - - const uiType = Utils.toTitleCase(this.props.type) + ' SSO'; - - return ( -
-

- -

-
-

- -

-

- -

-

- -

-
- -
- {error} - -
-
- ); - } -} - -EmailToSSO.defaultProps = { -}; -EmailToSSO.propTypes = { - intl: intlShape.isRequired, - type: React.PropTypes.string.isRequired, - email: React.PropTypes.string.isRequired, - teamName: React.PropTypes.string.isRequired, - teamDisplayName: React.PropTypes.string.isRequired -}; - -export default injectIntl(EmailToSSO); diff --git a/webapp/components/claim/sso_to_email.jsx b/webapp/components/claim/sso_to_email.jsx deleted file mode 100644 index a41e09969..000000000 --- a/webapp/components/claim/sso_to_email.jsx +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import ReactDOM from 'react-dom'; -import * as Utils from 'utils/utils.jsx'; -import * as Client from 'utils/client.jsx'; - -import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl'; - -const holders = defineMessages({ - enterPwd: { - id: 'claim.sso_to_email.enterPwd', - defaultMessage: 'Please enter a password.' - }, - pwdNotMatch: { - id: 'claim.sso_to_email.pwdNotMatch', - defaultMessage: 'Password do not match.' - }, - newPwd: { - id: 'claim.sso_to_email.newPwd', - defaultMessage: 'New Password' - }, - confirm: { - id: 'claim.sso_to_email.confirm', - defaultMessage: 'Confirm Password' - } -}); - -import React from 'react'; - -class SSOToEmail extends React.Component { - constructor(props) { - super(props); - - this.submit = this.submit.bind(this); - - this.state = {}; - } - submit(e) { - const {formatMessage} = this.props.intl; - e.preventDefault(); - const state = {}; - - const password = ReactDOM.findDOMNode(this.refs.password).value.trim(); - if (!password) { - state.error = formatMessage(holders.enterPwd); - this.setState(state); - return; - } - - const confirmPassword = ReactDOM.findDOMNode(this.refs.passwordconfirm).value.trim(); - if (!confirmPassword || password !== confirmPassword) { - state.error = formatMessage(holders.pwdNotMatch); - this.setState(state); - return; - } - - state.error = null; - this.setState(state); - - var postData = {}; - postData.password = password; - postData.email = this.props.email; - postData.team_name = this.props.teamName; - - Client.switchToEmail(postData, - (data) => { - if (data.follow_link) { - window.location.href = data.follow_link; - } - }, - (error) => { - this.setState({error}); - } - ); - } - render() { - const {formatMessage} = this.props.intl; - var error = null; - if (this.state.error) { - error =
; - } - - var formClass = 'form-group'; - if (error) { - formClass += ' has-error'; - } - - const uiType = Utils.toTitleCase(this.props.currentType) + ' SSO'; - - return ( -
-

- -

-
-

- -

-

- -

-
- -
-
- -
- {error} - -
-
- ); - } -} - -SSOToEmail.defaultProps = { -}; -SSOToEmail.propTypes = { - intl: intlShape.isRequired, - currentType: React.PropTypes.string.isRequired, - email: React.PropTypes.string.isRequired, - teamName: React.PropTypes.string.isRequired, - teamDisplayName: React.PropTypes.string -}; - -export default injectIntl(SSOToEmail); diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security.jsx index e42de91ea..283d2c425 100644 --- a/webapp/components/user_settings/user_settings_security.jsx +++ b/webapp/components/user_settings/user_settings_security.jsx @@ -15,6 +15,7 @@ import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedTime, FormattedDate} from 'react-intl'; +import {Link} from 'react-router'; const holders = defineMessages({ currentPasswordError: { @@ -268,17 +269,24 @@ class SecurityTab extends React.Component { let emailOption; if (global.window.mm_config.EnableSignUpWithEmail === 'true' && user.auth_service !== '') { + let link; + if (user.auth_service === Constants.LDAP_SERVICE) { + link = '/' + teamName + '/claim/ldap_to_email?email=' + encodeURIComponent(user.email); + } else { + link = '/' + teamName + '/claim/oauth_to_email?email=' + encodeURIComponent(user.email) + '&old_type=' + user.auth_service; + } + emailOption = (
- - +
); @@ -288,15 +296,15 @@ class SecurityTab extends React.Component { if (global.window.mm_config.EnableSignUpWithGitLab === 'true' && user.auth_service === '') { gitlabOption = (
- - +
); @@ -306,15 +314,33 @@ class SecurityTab extends React.Component { if (global.window.mm_config.EnableSignUpWithGoogle === 'true' && user.auth_service === '') { googleOption = (
- - + +
+
+ ); + } + + let ldapOption; + if (global.window.mm_config.EnableLdap === 'true' && user.auth_service === '') { + ldapOption = ( +
+ +
); @@ -325,6 +351,7 @@ class SecurityTab extends React.Component { {emailOption} {gitlabOption}
+ {ldapOption} {googleOption}
); diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index d9411df07..34e938e69 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -633,21 +633,45 @@ "choose_auth_page.ldapCreate": "Create new team with LDAP Account", "choose_auth_page.noSignup": "No sign-up methods configured, please contact your system administrator.", "claim.account.noEmail": "No email specified", - "claim.email_to_sso.enterPwd": "Enter the password for your {team} {site} account", - "claim.email_to_sso.pwd": "Password", - "claim.email_to_sso.pwdError": "Please enter your password.", - "claim.email_to_sso.ssoNote": "You must already have a valid {type} account", - "claim.email_to_sso.ssoType": "Upon claiming your account, you will only be able to login with {type} SSO", - "claim.email_to_sso.switchTo": "Switch account to {uiType}", - "claim.email_to_sso.title": "Switch Email/Password Account to {uiType}", - "claim.sso_to_email.confirm": "Confirm Password", - "claim.sso_to_email.description": "Upon changing your account type, you will only be able to login with your email and password.", - "claim.sso_to_email.enterPwd": "Please enter a password.", - "claim.sso_to_email.newPwd": "New Password", - "claim.sso_to_email.pwdNotMatch": "Password do not match.", - "claim.sso_to_email.switchTo": "Switch {type} to email and password", - "claim.sso_to_email.title": "Switch {type} Account to Email", - "claim.sso_to_email_newPwd": "Enter a new password for your {team} {site} account", + "claim.email_to_oauth.enterPwd": "Enter the password for your {team} {site} account", + "claim.email_to_oauth.pwd": "Password", + "claim.email_to_oauth.pwdError": "Please enter your password.", + "claim.email_to_oauth.ssoNote": "You must already have a valid {type} account", + "claim.email_to_oauth.ssoType": "Upon claiming your account, you will only be able to login with {type} SSO", + "claim.email_to_oauth.switchTo": "Switch account to {uiType}", + "claim.email_to_oauth.title": "Switch Email/Password Account to {uiType}", + "claim.oauth_to_email.confirm": "Confirm Password", + "claim.oauth_to_email.description": "Upon changing your account type, you will only be able to login with your email and password.", + "claim.oauth_to_email.enterPwd": "Please enter a password.", + "claim.oauth_to_email.newPwd": "New Password", + "claim.oauth_to_email.pwdNotMatch": "Password do not match.", + "claim.oauth_to_email.switchTo": "Switch {type} to email and password", + "claim.oauth_to_email.title": "Switch {type} Account to Email", + "claim.oauth_to_email.newPwd": "Enter a new password for your {team} {site} account", + "claim.email_to_ldap.pwdError": "Please enter your password.", + "claim.email_to_ldap.ldapIdError": "Please enter your LDAP ID.", + "claim.email_to_ldap.ldapPasswordError": "Please enter your LDAP password.", + "claim.email_to_ldap.title": "Switch Email/Password Account to LDAP", + "claim.email_to_ldap.ssoType": "Upon claiming your account, you will only be able to login with LDAP", + "claim.email_to_ldap.ssoNote": "You must already have a valid LDAP account", + "claim.email_to_ldap.enterPwd": "Enter the password for your {team} {site} email account", + "claim.email_to_ldap.pwd": "Password", + "claim.email_to_ldap.enterLdapPwd": "Enter the ID and password for your LDAP account", + "claim.email_to_ldap.ldapId": "LDAP ID", + "claim.email_to_ldap.ldapPwd": "LDAP Password", + "claim.email_to_ldap.switchTo": "Switch account to LDAP", + "claim.ldap_to_email.pwdError": "Please enter your password.", + "claim.ldap_to_email.pwdNotMatch": "Passwords do not match.", + "claim.ldap_to_email.ldapPasswordError": "Please enter your LDAP password.", + "claim.ldap_to_email.title": "Switch LDAP Account to Email/Password", + "claim.ldap_to_email.ssoType": "Upon claiming your account, you will only be able to login with your email and password", + "claim.ldap_to_email.email": "You will use the email {email} to login", + "claim.ldap_to_email.enterLdapPwd": "Enter your LDAP password for your {team} {site} email account", + "claim.ldap_to_email.ldapPwd": "LDAP Password", + "claim.ldap_to_email.enterPwd": "Enter a new password for your email account", + "claim.ldap_to_email.pwd": "Password", + "claim.ldap_to_email.confirm": "Confirm Password", + "claim.ldap_to_email.switchTo": "Switch account to email/password", "confirm_modal.cancel": "Cancel", "create_comment.addComment": "Add a comment...", "create_comment.comment": "Add Comment", @@ -1335,6 +1359,7 @@ "user.settings.security.switchEmail": "Switch to using email and password", "user.settings.security.switchGitlab": "Switch to using GitLab SSO", "user.settings.security.switchGoogle": "Switch to using Google SSO", + "user.settings.security.switchLda": "Switch to using LDAP", "user.settings.security.title": "Security Settings", "user.settings.security.viewHistory": "View Access History", "user_list.notFound": "No users found :(", diff --git a/webapp/i18n/es.json b/webapp/i18n/es.json index 8852dd3c6..9c1665c4e 100644 --- a/webapp/i18n/es.json +++ b/webapp/i18n/es.json @@ -633,21 +633,21 @@ "choose_auth_page.ldapCreate": "Crea un nuevo equipo con tu cuenta de LDAP", "choose_auth_page.noSignup": "No hay métodos de inicio de sesión configurad, por favor contacte al administrador de sistemasos", "claim.account.noEmail": "No se especifico un correo electrónico.", - "claim.email_to_sso.enterPwd": "Ingresa la contraseña para tu cuenta para {team} {site}", - "claim.email_to_sso.pwd": "Contraseña", - "claim.email_to_sso.pwdError": "Por favor introduce tu contraseña.", - "claim.email_to_sso.ssoNote": "Debes tener una cuenta válida con {type}", - "claim.email_to_sso.ssoType": "Al reclamar tu cuenta, sólo podrás iniciar sesión con {type} SSO", - "claim.email_to_sso.switchTo": "Cambiar cuenta a {uiType}", - "claim.email_to_sso.title": "Cambiar Cuenta de Correo/Contraseña a {uiType}", - "claim.sso_to_email.confirm": "Confirmar Contraseña", - "claim.sso_to_email.description": "Al cambiar el tipo de cuenta, sólo podrás iniciar sesión con tu correo electrónico y contraseña.", - "claim.sso_to_email.enterPwd": "Por favor ingresa una contraseña.", - "claim.sso_to_email.newPwd": "Nueva Contraseña", - "claim.sso_to_email.pwdNotMatch": "Las contraseñas no coinciden.", - "claim.sso_to_email.switchTo": "Cambiar {type} a correo electrónico y contraseña", - "claim.sso_to_email.title": "Cambiar la cuenta de {type} a Correo Electrónico", - "claim.sso_to_email_newPwd": "Ingresa una nueva contraseña para tu cuenta de {team} {site}", + "claim.email_to_oauth.enterPwd": "Ingresa la contraseña para tu cuenta para {team} {site}", + "claim.email_to_oauth.pwd": "Contraseña", + "claim.email_to_oauth.pwdError": "Por favor introduce tu contraseña.", + "claim.email_to_oauth.ssoNote": "Debes tener una cuenta válida con {type}", + "claim.email_to_oauth.ssoType": "Al reclamar tu cuenta, sólo podrás iniciar sesión con {type} SSO", + "claim.email_to_oauth.switchTo": "Cambiar cuenta a {uiType}", + "claim.email_to_oauth.title": "Cambiar Cuenta de Correo/Contraseña a {uiType}", + "claim.oauth_to_email.confirm": "Confirmar Contraseña", + "claim.oauth_to_email.description": "Al cambiar el tipo de cuenta, sólo podrás iniciar sesión con tu correo electrónico y contraseña.", + "claim.oauth_to_email.enterPwd": "Por favor ingresa una contraseña.", + "claim.oauth_to_email.newPwd": "Nueva Contraseña", + "claim.oauth_to_email.pwdNotMatch": "Las contraseñas no coinciden.", + "claim.oauth_to_email.switchTo": "Cambiar {type} a correo electrónico y contraseña", + "claim.oauth_to_email.title": "Cambiar la cuenta de {type} a Correo Electrónico", + "claim.oauth_to_email.newPwd": "Ingresa una nueva contraseña para tu cuenta de {team} {site}", "confirm_modal.cancel": "Cancelar", "create_comment.addComment": "Agregar un comentario...", "create_comment.comment": "Agregar Comentario", diff --git a/webapp/i18n/pt.json b/webapp/i18n/pt.json index 41d3bbc1c..0b06b77af 100644 --- a/webapp/i18n/pt.json +++ b/webapp/i18n/pt.json @@ -639,21 +639,21 @@ "choose_auth_page.ldapCreate": "Criar uma nova equipe com uma conta LDAP", "choose_auth_page.noSignup": "Nenhum método de inscrição configurado, por favor contate seu administrador do sistema.", "claim.account.noEmail": "Nenhum email específicado", - "claim.email_to_sso.enterPwd": "Entre a senha para o sua conta {team} {site}", - "claim.email_to_sso.pwd": "Senha", - "claim.email_to_sso.pwdError": "Por favor digite a sua senha.", - "claim.email_to_sso.ssoNote": "Você precisa já ter uma conta {type} válida", - "claim.email_to_sso.ssoType": "Ao retirar a sua conta, você só vai ser capaz de logar com SSO {type}", - "claim.email_to_sso.switchTo": "Trocar a conta para {uiType}", - "claim.email_to_sso.title": "Trocar E-mail/Senha da Conta para {uiType}", - "claim.sso_to_email.confirm": "Confirmar senha", - "claim.sso_to_email.description": "Após a alteração do tipo de conta, você só vai ser capaz de logar com seu e-mail e senha.", - "claim.sso_to_email.enterPwd": "Por favor entre uma senha.", - "claim.sso_to_email.newPwd": "Nova Senha", - "claim.sso_to_email.pwdNotMatch": "As senha não correspondem.", - "claim.sso_to_email.switchTo": "Trocar {type} para email e senha", - "claim.sso_to_email.title": "Trocar Conta {type} para E-mail", - "claim.sso_to_email_newPwd": "Entre a nova senha para o sua conta {team} {site}", + "claim.email_to_oauth.enterPwd": "Entre a senha para o sua conta {team} {site}", + "claim.email_to_oauth.pwd": "Senha", + "claim.email_to_oauth.pwdError": "Por favor digite a sua senha.", + "claim.email_to_oauth.ssoNote": "Você precisa já ter uma conta {type} válida", + "claim.email_to_oauth.ssoType": "Ao retirar a sua conta, você só vai ser capaz de logar com SSO {type}", + "claim.email_to_oauth.switchTo": "Trocar a conta para {uiType}", + "claim.email_to_oauth.title": "Trocar E-mail/Senha da Conta para {uiType}", + "claim.oauth_to_email.confirm": "Confirmar senha", + "claim.oauth_to_email.description": "Após a alteração do tipo de conta, você só vai ser capaz de logar com seu e-mail e senha.", + "claim.oauth_to_email.enterPwd": "Por favor entre uma senha.", + "claim.oauth_to_email.newPwd": "Nova Senha", + "claim.oauth_to_email.pwdNotMatch": "As senha não correspondem.", + "claim.oauth_to_email.switchTo": "Trocar {type} para email e senha", + "claim.oauth_to_email.title": "Trocar Conta {type} para E-mail", + "claim.oauth_to_email.newPwd": "Entre a nova senha para o sua conta {team} {site}", "confirm_modal.cancel": "Cancelar", "create_comment.addComment": "Adicionar um comentário...", "create_comment.comment": "Adicionar Comentário", diff --git a/webapp/root.jsx b/webapp/root.jsx index 6ab5e80a0..bb5f506c1 100644 --- a/webapp/root.jsx +++ b/webapp/root.jsx @@ -35,7 +35,6 @@ import SignupUserComplete from 'components/signup_user_complete.jsx'; import ShouldVerifyEmail from 'components/should_verify_email.jsx'; import DoVerifyEmail from 'components/do_verify_email.jsx'; import AdminConsole from 'components/admin_console/admin_controller.jsx'; -import ClaimAccount from 'components/claim/claim_account.jsx'; import SignupTeamComplete from 'components/signup_team_complete/components/signup_team_complete.jsx'; import WelcomePage from 'components/signup_team_complete/components/team_signup_welcome_page.jsx'; @@ -46,6 +45,12 @@ import UsernamePage from 'components/signup_team_complete/components/team_signup import PasswordPage from 'components/signup_team_complete/components/team_signup_password_page.jsx'; import FinishedPage from 'components/signup_team_complete/components/team_signup_finished.jsx'; +import Claim from 'components/claim/claim.jsx'; +import EmailToOAuth from 'components/claim/components/email_to_oauth.jsx'; +import OAuthToEmail from 'components/claim/components/oauth_to_email.jsx'; +import LDAPToEmail from 'components/claim/components/ldap_to_email.jsx'; +import EmailToLDAP from 'components/claim/components/email_to_ldap.jsx'; + import {addLocaleData} from 'react-intl'; import enLocaleData from 'react-intl/locale-data/en'; import esLocaleData from 'react-intl/locale-data/es'; @@ -307,10 +312,6 @@ function renderRootComponent() { path='login' component={Login} /> - + + + + + + diff --git a/webapp/utils/client.jsx b/webapp/utils/client.jsx index e29cf71d3..d42767d31 100644 --- a/webapp/utils/client.jsx +++ b/webapp/utils/client.jsx @@ -256,38 +256,72 @@ export function resetPassword(data, success, error) { track('api', 'api_users_reset_password'); } -export function switchToSSO(data, success, error) { +export function emailToOAuth(data, success, error) { $.ajax({ - url: '/api/v1/users/switch_to_sso', + url: '/api/v1/users/claim/email_to_oauth', dataType: 'json', contentType: 'application/json', type: 'POST', data: JSON.stringify(data), success, error: function onError(xhr, status, err) { - var e = handleError('switchToSSO', xhr, status, err); + var e = handleError('emailToOAuth', xhr, status, err); error(e); } }); - track('api', 'api_users_switch_to_sso'); + track('api', 'api_users_email_to_oauth'); } -export function switchToEmail(data, success, error) { +export function oauthToEmail(data, success, error) { $.ajax({ - url: '/api/v1/users/switch_to_email', + url: '/api/v1/users/claim/oauth_to_email', dataType: 'json', contentType: 'application/json', type: 'POST', data: JSON.stringify(data), success, error: function onError(xhr, status, err) { - var e = handleError('switchToEmail', xhr, status, err); + var e = handleError('oauthToEmail', xhr, status, err); error(e); } }); - track('api', 'api_users_switch_to_email'); + track('api', 'api_users_oauth_to_email'); +} + +export function emailToLDAP(data, success, error) { + $.ajax({ + url: '/api/v1/users/claim/email_to_ldap', + dataType: 'json', + contentType: 'application/json', + type: 'POST', + data: JSON.stringify(data), + success, + error: function onError(xhr, status, err) { + var e = handleError('emailToLDAP', xhr, status, err); + error(e); + } + }); + + track('api', 'api_users_email_to_ldap'); +} + +export function ldapToEmail(data, success, error) { + $.ajax({ + url: '/api/v1/users/claim/ldap_to_email', + dataType: 'json', + contentType: 'application/json', + type: 'POST', + data: JSON.stringify(data), + success, + error: function onError(xhr, status, err) { + var e = handleError('ldapToEmail', xhr, status, err); + error(e); + } + }); + + track('api', 'api_users_ldap_to_email'); } export function logout(success, error) { diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index 859348c73..ae9fdc5fb 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -185,6 +185,7 @@ export default { OFFTOPIC_CHANNEL: 'off-topic', GITLAB_SERVICE: 'gitlab', GOOGLE_SERVICE: 'google', + LDAP_SERVICE: 'ldap', EMAIL_SERVICE: 'email', SIGNIN_CHANGE: 'signin_change', SIGNIN_VERIFIED: 'verified', -- cgit v1.2.3-1-g7c22 From 934c7c7a7c8423d71fdc7d1586b9c03aedcc5129 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Wed, 23 Mar 2016 15:59:43 -0400 Subject: Fix imports and change ldap function name --- api/user.go | 2 +- einterfaces/ldap.go | 2 +- webapp/components/claim/claim.jsx | 2 +- webapp/components/claim/components/email_to_ldap.jsx | 4 ++-- webapp/components/claim/components/email_to_oauth.jsx | 4 ++-- webapp/components/claim/components/ldap_to_email.jsx | 4 ++-- webapp/components/claim/components/oauth_to_email.jsx | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/api/user.go b/api/user.go index 04bd673a8..6803a946c 100644 --- a/api/user.go +++ b/api/user.go @@ -2303,7 +2303,7 @@ func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) { return } - if err := ldapInterface.DoSwitch(user.Id, ldapId, ldapPassword); err != nil { + if err := ldapInterface.SwitchToEmail(user.Id, ldapId, ldapPassword); err != nil { c.LogAuditWithUserId(user.Id, "fail - ldap switch failed") c.Err = err return diff --git a/einterfaces/ldap.go b/einterfaces/ldap.go index 583fa02c0..2977ab812 100644 --- a/einterfaces/ldap.go +++ b/einterfaces/ldap.go @@ -11,7 +11,7 @@ type LdapInterface interface { DoLogin(team *model.Team, id string, password string) (*model.User, *model.AppError) GetUser(id string) (*model.User, *model.AppError) CheckPassword(id string, password string) *model.AppError - DoSwitch(userId, ldapId, ldapPassword string) *model.AppError + SwitchToEmail(userId, ldapId, ldapPassword string) *model.AppError } var theLdapInterface LdapInterface diff --git a/webapp/components/claim/claim.jsx b/webapp/components/claim/claim.jsx index 0254897f9..464187c37 100644 --- a/webapp/components/claim/claim.jsx +++ b/webapp/components/claim/claim.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import TeamStore from '../../stores/team_store.jsx'; +import TeamStore from 'stores/team_store.jsx'; import React from 'react'; import {FormattedMessage} from 'react-intl'; diff --git a/webapp/components/claim/components/email_to_ldap.jsx b/webapp/components/claim/components/email_to_ldap.jsx index bb2a3f0ed..f3046fa74 100644 --- a/webapp/components/claim/components/email_to_ldap.jsx +++ b/webapp/components/claim/components/email_to_ldap.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import * as Utils from '../../../utils/utils.jsx'; -import * as Client from '../../../utils/client.jsx'; +import * as Utils from 'utils/utils.jsx'; +import * as Client from 'utils/client.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; diff --git a/webapp/components/claim/components/email_to_oauth.jsx b/webapp/components/claim/components/email_to_oauth.jsx index 51549423d..f3e370a4a 100644 --- a/webapp/components/claim/components/email_to_oauth.jsx +++ b/webapp/components/claim/components/email_to_oauth.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import * as Utils from '../../../utils/utils.jsx'; -import * as Client from '../../../utils/client.jsx'; +import * as Utils from 'utils/utils.jsx'; +import * as Client from 'utils/client.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; diff --git a/webapp/components/claim/components/ldap_to_email.jsx b/webapp/components/claim/components/ldap_to_email.jsx index d645819b5..b4ffd4944 100644 --- a/webapp/components/claim/components/ldap_to_email.jsx +++ b/webapp/components/claim/components/ldap_to_email.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import * as Utils from '../../../utils/utils.jsx'; -import * as Client from '../../../utils/client.jsx'; +import * as Utils from 'utils/utils.jsx'; +import * as Client from 'utils/client.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; diff --git a/webapp/components/claim/components/oauth_to_email.jsx b/webapp/components/claim/components/oauth_to_email.jsx index 11246bea7..476677aeb 100644 --- a/webapp/components/claim/components/oauth_to_email.jsx +++ b/webapp/components/claim/components/oauth_to_email.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import * as Utils from '../../../utils/utils.jsx'; -import * as Client from '../../../utils/client.jsx'; +import * as Utils from 'utils/utils.jsx'; +import * as Client from 'utils/client.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; -- cgit v1.2.3-1-g7c22