summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
authorJoramWilander <jwawilander@gmail.com>2016-03-17 15:46:16 -0400
committerJoramWilander <jwawilander@gmail.com>2016-03-23 15:59:58 -0400
commit463fd8c20b6e20d1cc669810c339770b9b1ede41 (patch)
tree3bf857301e0a24a1a7ccd7c5d15834829e3d22e7 /api
parent7af2e6f87a754312809aa044edd062930616401a (diff)
downloadchat-463fd8c20b6e20d1cc669810c339770b9b1ede41.tar.gz
chat-463fd8c20b6e20d1cc669810c339770b9b1ede41.tar.bz2
chat-463fd8c20b6e20d1cc669810c339770b9b1ede41.zip
Add the ability to switch from email to ldap and back
Diffstat (limited to 'api')
-rw-r--r--api/user.go197
-rw-r--r--api/user_test.go145
2 files changed, 314 insertions, 28 deletions
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()