Add the ability to switch from email to ldap and back

Этот коммит содержится в:
JoramWilander
2016-03-17 15:46:16 -04:00
родитель 7af2e6f87a
Коммит 463fd8c20b
20 изменённых файлов: 933 добавлений и 231 удалений

Просмотреть файл

@@ -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() {

Просмотреть файл

@@ -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()