diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go index 04e410543d2ce..da6bef207ad7c 100644 --- a/routers/web/auth/auth.go +++ b/routers/web/auth/auth.go @@ -123,9 +123,21 @@ func resetLocale(ctx *context.Context, u *user_model.User) error { return nil } +func RedirectAfterLogin(ctx *context.Context) { + redirectTo := ctx.FormString("redirect_to") + if redirectTo == "" { + redirectTo = ctx.GetSiteCookie("redirect_to") + } + middleware.DeleteRedirectToCookie(ctx.Resp) + nextRedirectTo := setting.AppSubURL + string(setting.LandingPageURL) + if setting.LandingPageURL == setting.LandingPageLogin { + nextRedirectTo = setting.AppSubURL + "/" // do not cycle-redirect to the login page + } + ctx.RedirectToFirst(redirectTo, nextRedirectTo) +} + func CheckAutoLogin(ctx *context.Context) bool { - // Check auto-login - isSucceed, err := autoSignIn(ctx) + isSucceed, err := autoSignIn(ctx) // try to auto-login if err != nil { if errors.Is(err, auth_service.ErrAuthTokenInvalidHash) { ctx.Flash.Error(ctx.Tr("auth.remember_me.compromised"), true) @@ -138,17 +150,10 @@ func CheckAutoLogin(ctx *context.Context) bool { redirectTo := ctx.FormString("redirect_to") if len(redirectTo) > 0 { middleware.SetRedirectToCookie(ctx.Resp, redirectTo) - } else { - redirectTo = ctx.GetSiteCookie("redirect_to") } if isSucceed { - middleware.DeleteRedirectToCookie(ctx.Resp) - nextRedirectTo := setting.AppSubURL + string(setting.LandingPageURL) - if setting.LandingPageURL == setting.LandingPageLogin { - nextRedirectTo = setting.AppSubURL + "/" // do not cycle-redirect to the login page - } - ctx.RedirectToFirst(redirectTo, nextRedirectTo) + RedirectAfterLogin(ctx) return true } @@ -163,6 +168,11 @@ func SignIn(ctx *context.Context) { return } + if ctx.IsSigned { + RedirectAfterLogin(ctx) + return + } + oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, optional.Some(true)) if err != nil { ctx.ServerError("UserSignIn", err) diff --git a/routers/web/auth/auth_test.go b/routers/web/auth/auth_test.go new file mode 100644 index 0000000000000..c4e583c7e5183 --- /dev/null +++ b/routers/web/auth/auth_test.go @@ -0,0 +1,38 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package auth + +import ( + "net/http" + "net/url" + "testing" + + "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/services/contexttest" + + "github.com/stretchr/testify/assert" +) + +func TestUserLogin(t *testing.T) { + ctx, resp := contexttest.MockContext(t, "/user/login") + ctx.IsSigned = true + SignIn(ctx) + assert.Equal(t, "/", test.RedirectURL(resp)) + + ctx, resp = contexttest.MockContext(t, "/user/login?redirect_to=/other") + ctx.IsSigned = true + SignIn(ctx) + assert.Equal(t, "/other", test.RedirectURL(resp)) + + ctx, resp = contexttest.MockContext(t, "/user/login") + ctx.Req.AddCookie(&http.Cookie{Name: "redirect_to", Value: "/other-cookie"}) + ctx.IsSigned = true + SignIn(ctx) + assert.Equal(t, "/other-cookie", test.RedirectURL(resp)) + + ctx, resp = contexttest.MockContext(t, "/user/login?redirect_to="+url.QueryEscape("https://example.com")) + ctx.IsSigned = true + SignIn(ctx) + assert.Equal(t, "/", test.RedirectURL(resp)) +} diff --git a/services/contexttest/context_tests.go b/services/contexttest/context_tests.go index 431017a30dcb6..d3e6de7efe4f9 100644 --- a/services/contexttest/context_tests.go +++ b/services/contexttest/context_tests.go @@ -7,6 +7,7 @@ package contexttest import ( gocontext "context" "io" + "maps" "net/http" "net/http/httptest" "net/url" @@ -36,7 +37,7 @@ func mockRequest(t *testing.T, reqPath string) *http.Request { } requestURL, err := url.Parse(path) assert.NoError(t, err) - req := &http.Request{Method: method, URL: requestURL, Form: url.Values{}} + req := &http.Request{Method: method, URL: requestURL, Form: maps.Clone(requestURL.Query()), Header: http.Header{}} req = req.WithContext(middleware.WithContextData(req.Context())) return req }