From dfc6db737411bd4ad68a803be5182f06055a1769 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Mon, 10 Apr 2017 08:19:49 -0400 Subject: Refactor switching login type code into app layer and add v4 endpoint (#6000) * Refactor switching login type code into app layer and add v4 endpoint * Fix unit test --- api4/context.go | 3 +- api4/user.go | 38 +++++++++++++++++++++++ api4/user_test.go | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 131 insertions(+), 3 deletions(-) (limited to 'api4') diff --git a/api4/context.go b/api4/context.go index 9c27ec9c1..cd1137508 100644 --- a/api4/context.go +++ b/api4/context.go @@ -242,8 +242,7 @@ func (c *Context) IsSystemAdmin() bool { func (c *Context) SessionRequired() { if len(c.Session.UserId) == 0 { - c.Err = model.NewLocAppError("", "api.context.session_expired.app_error", nil, "UserRequired") - c.Err.StatusCode = http.StatusUnauthorized + c.Err = model.NewAppError("", "api.context.session_expired.app_error", nil, "UserRequired", http.StatusUnauthorized) return } } diff --git a/api4/user.go b/api4/user.go index b30d066ab..5880370c6 100644 --- a/api4/user.go +++ b/api4/user.go @@ -43,6 +43,7 @@ func InitUser() { BaseRoutes.User.Handle("/mfa/generate", ApiSessionRequired(generateMfaSecret)).Methods("POST") BaseRoutes.Users.Handle("/login", ApiHandler(login)).Methods("POST") + BaseRoutes.Users.Handle("/login/switch", ApiHandler(switchAccountType)).Methods("POST") BaseRoutes.Users.Handle("/logout", ApiHandler(logout)).Methods("POST") BaseRoutes.UserByUsername.Handle("", ApiSessionRequired(getUserByUsername)).Methods("GET") @@ -981,3 +982,40 @@ func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) { ReturnStatusOK(w) } + +func switchAccountType(c *Context, w http.ResponseWriter, r *http.Request) { + switchRequest := model.SwitchRequestFromJson(r.Body) + if switchRequest == nil { + c.SetInvalidParam("switch_request") + return + } + + link := "" + var err *model.AppError + + if switchRequest.EmailToOAuth() { + link, err = app.SwitchEmailToOAuth(switchRequest.Email, switchRequest.Password, switchRequest.MfaCode, switchRequest.NewService) + } else if switchRequest.OAuthToEmail() { + c.SessionRequired() + if c.Err != nil { + return + } + + link, err = app.SwitchOAuthToEmail(switchRequest.Email, switchRequest.NewPassword, c.Session.UserId) + } else if switchRequest.EmailToLdap() { + link, err = app.SwitchEmailToLdap(switchRequest.Email, switchRequest.Password, switchRequest.MfaCode, switchRequest.LdapId, switchRequest.NewPassword) + } else if switchRequest.LdapToEmail() { + link, err = app.SwitchLdapToEmail(switchRequest.Password, switchRequest.MfaCode, switchRequest.Email, switchRequest.NewPassword) + } else { + c.SetInvalidParam("switch_request") + return + } + + if err != nil { + c.Err = err + return + } + + c.LogAudit("success") + w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link}))) +} diff --git a/api4/user_test.go b/api4/user_test.go index b3e4edc3d..f904bd460 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -1297,7 +1297,7 @@ func TestUpdateUserPassword(t *testing.T) { // Should fail because account is locked out _, resp = Client.UpdateUserPassword(th.BasicUser.Id, th.BasicUser.Password, "newpwd") CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error") - CheckForbiddenStatus(t, resp) + CheckUnauthorizedStatus(t, resp) // System admin can update another user's password adminSetPassword := "pwdsetbyadmin" @@ -1651,3 +1651,94 @@ func TestSetProfileImage(t *testing.T) { t.Fatal(err) } } + +func TestSwitchAccount(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + + enableGitLab := utils.Cfg.GitLabSettings.Enable + defer func() { + utils.Cfg.GitLabSettings.Enable = enableGitLab + }() + utils.Cfg.GitLabSettings.Enable = true + + Client.Logout() + + sr := &model.SwitchRequest{ + CurrentService: model.USER_AUTH_SERVICE_EMAIL, + NewService: model.USER_AUTH_SERVICE_GITLAB, + Email: th.BasicUser.Email, + Password: th.BasicUser.Password, + } + + link, resp := Client.SwitchAccountType(sr) + CheckNoError(t, resp) + + if link == "" { + t.Fatal("bad link") + } + + th.LoginBasic() + + fakeAuthData := "1" + if result := <-app.Srv.Store.User().UpdateAuthData(th.BasicUser.Id, model.USER_AUTH_SERVICE_GITLAB, &fakeAuthData, th.BasicUser.Email, true); result.Err != nil { + t.Fatal(result.Err) + } + + sr = &model.SwitchRequest{ + CurrentService: model.USER_AUTH_SERVICE_GITLAB, + NewService: model.USER_AUTH_SERVICE_EMAIL, + Email: th.BasicUser.Email, + NewPassword: th.BasicUser.Password, + } + + link, resp = Client.SwitchAccountType(sr) + CheckNoError(t, resp) + + if link != "/login?extra=signin_change" { + t.Log(link) + t.Fatal("bad link") + } + + Client.Logout() + _, resp = Client.Login(th.BasicUser.Email, th.BasicUser.Password) + CheckNoError(t, resp) + Client.Logout() + + sr = &model.SwitchRequest{ + CurrentService: model.USER_AUTH_SERVICE_GITLAB, + NewService: model.SERVICE_GOOGLE, + } + + _, resp = Client.SwitchAccountType(sr) + CheckBadRequestStatus(t, resp) + + sr = &model.SwitchRequest{ + CurrentService: model.USER_AUTH_SERVICE_EMAIL, + NewService: model.USER_AUTH_SERVICE_GITLAB, + Password: th.BasicUser.Password, + } + + _, resp = Client.SwitchAccountType(sr) + CheckNotFoundStatus(t, resp) + + sr = &model.SwitchRequest{ + CurrentService: model.USER_AUTH_SERVICE_EMAIL, + NewService: model.USER_AUTH_SERVICE_GITLAB, + Email: th.BasicUser.Email, + } + + _, resp = Client.SwitchAccountType(sr) + CheckUnauthorizedStatus(t, resp) + + sr = &model.SwitchRequest{ + CurrentService: model.USER_AUTH_SERVICE_GITLAB, + NewService: model.USER_AUTH_SERVICE_EMAIL, + Email: th.BasicUser.Email, + NewPassword: th.BasicUser.Password, + } + + _, resp = Client.SwitchAccountType(sr) + CheckUnauthorizedStatus(t, resp) +} -- cgit v1.2.3-1-g7c22