refactor!: move go-chi/session into Gitea (#39504)

The `gitea.com/go-chi/session` package only exists for Gitea, so it
moves into `modules/session` to fix its bugs directly. Fixes the flake
in
https://github.com/go-gitea/gitea/actions/runs/36726154500/job/109923538400.

- Sessions are only written back when changed, so a read-only request
can't revert a concurrent change or restore a logged-out session, like
https://github.com/go-macaron/session/commit/ae808a4a4660c802965c834299ab08f167effd12
- The session cookie is only set once a session holds data
- Every backend refreshes the expiry on load and file sessions are
written atomically
- Also fix  https://github.com/go-gitea/gitea/issues/36176

## ⚠️ BREAKING ⚠️

* the `mysql`, `postgres`, `couchbase` and `memcache` session providers
are removed, use `file`, `db` or `redis` instead
* login-related cookies are renamed to `gitea_session` and
`gitea_remember`, if you'd like to use the old names, set `COOKIE_NAME`
and `COOKIE_REMEMBER_NAME` in app.ini

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwindandwxiaoguang authored and GitHub committed 2026-10-02 21:08:14 +02:00
1 parent bea6fcaa84
commit cf89ecd887
34 files changed
+913 -981

No files matched your search

-16
View File
@@ -18,8 +18,6 @@ import (
"gitea.dev/modules/util"
"gitea.dev/services/context"
"gitea.dev/services/mailer"
"gitea.com/go-chi/session"
)
const (
@@ -93,20 +91,6 @@ func Config(ctx *context.Context) {
ctx.Data["CacheItemTTL"] = setting.CacheService.TTL
sessionCfg := setting.SessionConfig
if sessionCfg.Provider == "VirtualSession" {
var realSession session.Options
if err := json.Unmarshal([]byte(sessionCfg.ProviderConfig), &realSession); err != nil {
log.Error("Unable to unmarshall session config for virtual provider config: %s\nError: %v", sessionCfg.ProviderConfig, err)
}
sessionCfg.Provider = realSession.Provider
sessionCfg.ProviderConfig = realSession.ProviderConfig
sessionCfg.CookieName = realSession.CookieName
sessionCfg.CookiePath = realSession.CookiePath
sessionCfg.Gclifetime = realSession.Gclifetime
sessionCfg.Maxlifetime = realSession.Maxlifetime
sessionCfg.Secure = realSession.Secure
sessionCfg.Domain = realSession.Domain
}
sessionCfg.ProviderConfig = ""
ctx.Data["SessionConfig"] = sessionCfg
+4 -4
View File
@@ -444,7 +444,9 @@ func extractUserNameFromOAuth2(gothUser *goth.User) (string, error) {
// HandleSignOut resets the session and sets the cookies
func HandleSignOut(ctx *context.Context) {
_ = ctx.Session.Flush()
_ = ctx.Session.Destroy(ctx.Resp, ctx.Req)
if err := ctx.Session.Destroy(ctx.Resp, ctx.Req); err != nil {
log.Error("Unable to destroy session: %v", err)
}
ctx.DeleteSiteCookie(setting.CookieRememberName)
middleware.DeleteRedirectToCookie(ctx.Resp)
}
@@ -931,10 +933,8 @@ func ActivateEmail(ctx *context.Context) {
}
func regenerateSession(ctx *context.Context, updates map[string]any) error {
if _, err := session.RegenerateSession(ctx.Resp, ctx.Req); err != nil {
return fmt.Errorf("regenerate session: %w", err)
}
sess := ctx.Session
sess.Regenerate(ctx.Resp, ctx.Req)
sessID := sess.ID()
for k, v := range updates {
if err := sess.Set(k, v); err != nil {
-2
View File
@@ -49,8 +49,6 @@ import (
"gitea.dev/services/context"
"gitea.dev/services/forms"
_ "gitea.dev/modules/session" // to register all internal adapters
chi_middleware "github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"github.com/klauspost/compress/gzhttp"