From 56f709571184b1949b9bbf584eda259e3c4e04b5 Mon Sep 17 00:00:00 2001 From: Anbraten <6918444+anbraten@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:47:57 +0200 Subject: [PATCH 01/42] login with selected forge --- server/api/login.go | 44 +++++++++++++++++------ server/services/manager.go | 21 +++++------ web/src/assets/locales/en.json | 2 +- web/src/compositions/useAuthentication.ts | 4 +-- web/src/views/Login.vue | 38 ++++++++++++++++++-- 5 files changed, 82 insertions(+), 27 deletions(-) diff --git a/server/api/login.go b/server/api/login.go index 349861ce11e..fc3c228b250 100644 --- a/server/api/login.go +++ b/server/api/login.go @@ -17,7 +17,9 @@ package api import ( "encoding/base32" "errors" + "fmt" "net/http" + "strconv" "time" "github.com/gin-gonic/gin" @@ -33,22 +35,42 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/shared/token" ) +func getForgeID(c *gin.Context) int64 { + _forgeID := c.Query("forge_id") + if _forgeID == "" { + _forgeID, _ = c.Cookie("forge_id") + } + if _forgeID == "" { + return 1 + } + forgeID, err := strconv.ParseInt(_forgeID, 10, 64) + if err != nil { + return 1 + } + return forgeID +} + func HandleLogin(c *gin.Context) { + forgeID := getForgeID(c) + if err := c.Request.FormValue("error"); err != "" { - c.Redirect(http.StatusSeeOther, server.Config.Server.RootPath+"/login/error?code="+err) + c.Redirect(http.StatusSeeOther, fmt.Sprintf("%s/login/error?code=%s&forge_id=%d", server.Config.Server.RootPath, err, forgeID)) } else { - c.Redirect(http.StatusSeeOther, server.Config.Server.RootPath+"/authorize") + c.Redirect(http.StatusSeeOther, fmt.Sprintf("%s/authorize?forge_id=%d", server.Config.Server.RootPath, forgeID)) } } func HandleAuth(c *gin.Context) { _store := store.FromContext(c) - _forge, err := server.Config.Services.Manager.ForgeMain() + forgeID := getForgeID(c) + + log.Debug().Msgf("trying to login with forge_id: %d", forgeID) + + _forge, err := server.Config.Services.Manager.ForgeByID(forgeID) if err != nil { _ = c.AbortWithError(http.StatusInternalServerError, err) return } - forgeID := int64(1) // TODO: replace with forge id when multiple forges are supported // when dealing with redirects, we may need to adjust the content type. I // cannot, however, remember why, so need to revisit this line. @@ -138,7 +160,7 @@ func HandleAuth(c *gin.Context) { ForgeID: u.ForgeID, } if err := _store.OrgCreate(org); err != nil { - log.Error().Err(err).Msgf("on user creation, could create org for user") + log.Error().Err(err).Msgf("on user creation, could not create org for user") } u.OrgID = org.ID } @@ -235,17 +257,16 @@ func GetLogout(c *gin.Context) { func GetLoginToken(c *gin.Context) { _store := store.FromContext(c) - _forge, err := server.Config.Services.Manager.ForgeMain() // TODO: get selected forge from auth request + in := &tokenPayload{} + err := c.Bind(in) if err != nil { - log.Error().Err(err).Msg("Cannot get main forge") - c.AbortWithStatus(http.StatusInternalServerError) + _ = c.AbortWithError(http.StatusBadRequest, err) return } - in := &tokenPayload{} - err = c.Bind(in) + _forge, err := server.Config.Services.Manager.ForgeByID(in.ForgeID) if err != nil { - _ = c.AbortWithError(http.StatusBadRequest, err) + _ = c.AbortWithError(http.StatusInternalServerError, err) return } @@ -279,4 +300,5 @@ type tokenPayload struct { Access string `json:"access_token,omitempty"` Refresh string `json:"refresh_token,omitempty"` Expires int64 `json:"expires_in,omitempty"` + ForgeID int64 `json:"forge_id,omitempty"` } diff --git a/server/services/manager.go b/server/services/manager.go index ff281c40a23..26859e58aca 100644 --- a/server/services/manager.go +++ b/server/services/manager.go @@ -46,6 +46,7 @@ type Manager interface { EnvironmentService() environment.Service ForgeFromRepo(repo *model.Repo) (forge.Forge, error) ForgeFromUser(user *model.User) (forge.Forge, error) + ForgeByID(forgeID int64) (forge.Forge, error) ForgeMain() (forge.Forge, error) } @@ -115,24 +116,20 @@ func (m *manager) EnvironmentService() environment.Service { } func (m *manager) ForgeFromRepo(repo *model.Repo) (forge.Forge, error) { - return m.getForgeByID(repo.ForgeID) + return m.ForgeByID(repo.ForgeID) } func (m *manager) ForgeFromUser(user *model.User) (forge.Forge, error) { - return m.getForgeByID(user.ForgeID) + return m.ForgeByID(user.ForgeID) } -func (m *manager) ForgeMain() (forge.Forge, error) { - return m.getForgeByID(1) // main forge is always 1 and is configured via environment variables -} - -func (m *manager) getForgeByID(id int64) (forge.Forge, error) { - item := m.forgeCache.Get(id) +func (m *manager) ForgeByID(forgeID int64) (forge.Forge, error) { + item := m.forgeCache.Get(forgeID) if item != nil && !item.IsExpired() { return item.Value(), nil } - forgeModel, err := m.store.ForgeGet(id) + forgeModel, err := m.store.ForgeGet(forgeID) if err != nil { return nil, err } @@ -142,7 +139,11 @@ func (m *manager) getForgeByID(id int64) (forge.Forge, error) { return nil, err } - m.forgeCache.Set(id, forge, forgeCacheTTL) + m.forgeCache.Set(forgeID, forge, forgeCacheTTL) return forge, nil } + +func (m *manager) ForgeMain() (forge.Forge, error) { + return m.ForgeByID(1) // main forge is always 1 and is configured via environment variables +} diff --git a/web/src/assets/locales/en.json b/web/src/assets/locales/en.json index 83e98c2d81d..008b6b9e4a4 100644 --- a/web/src/assets/locales/en.json +++ b/web/src/assets/locales/en.json @@ -1,6 +1,6 @@ { "cancel": "Cancel", - "login": "Login", + "login_with": "Login with {forge}", "welcome": "Welcome to Woodpecker", "repos": "Repos", "repositories": "Repositories", diff --git a/web/src/compositions/useAuthentication.ts b/web/src/compositions/useAuthentication.ts index 287942eed58..8ed98f42dae 100644 --- a/web/src/compositions/useAuthentication.ts +++ b/web/src/compositions/useAuthentication.ts @@ -7,11 +7,11 @@ export default () => user: useConfig().user, - authenticate(url?: string) { + authenticate(url?: string, forgeId?: number) { if (url) { const config = useUserConfig(); config.setUserConfig('redirectUrl', url); } - window.location.href = `${useConfig().rootPath}/login`; + window.location.href = `${useConfig().rootPath}/login?forge_id=${forgeId}`; }, }) as const; diff --git a/web/src/views/Login.vue b/web/src/views/Login.vue index d6fcec0b982..dbb8c8e5724 100644 --- a/web/src/views/Login.vue +++ b/web/src/views/Login.vue @@ -11,7 +11,11 @@