refactor!: move go-chi/session into Gitea - #39504
Conversation
Every request wrote its own copy of the session back on release, so a request that only read the session reverted changes a concurrent request saved in the meantime, e.g. the WebAuthn registration state when the page's background polling overlapped it. Session stores now track changes and only refresh the expiry of unchanged sessions. The file store fix is in https://gitea.com/go-chi/session/pulls/14, pinned via replace until it is merged. Assisted-by: Claude Code:claude-opus-5-5
|
I was also working on the "session" package .... I believe it's not worth to make any patch to the chi-session package. Either, we fully rewrite it, or, we write our own and completely drop it. Gitea side already has a "virtual" wrapper for it, it really doesn't make sense to hack it more ....... Also, we only need to support a few providers, including: memory, redis, file, db. All other providers can be removed (breaking change, but worth) |
|
I'll move the session package first-party. Much better then having this single external dependency with only gitea as the only real consumer. |
|
All legacy chi-* packages have various problems and bugs, and are only used by Gitea. |
|
Ok, migrating all. |
These packages only exist for Gitea, and their bugs and the workarounds for them are simpler to fix in first-party code. Sessions are only written back when changed and the cookie is only set once a session holds data, so a read-only request can no longer revert a concurrent change or bring back a logged-out session. Captcha answers are consumed atomically by the cache, and OpenID registration stops after a failed captcha. The removed mysql, postgres, couchbase and memcache session providers fail at startup with a hint to use db or redis. Assisted-by: Claude Code:claude-opus-5-5
|
Move done, fixed numerous bugs while doing so. The change is flagged breaking because of the session provider removals. |
|
CI failure is unrelated and needs #39512. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Four critical and two moderate findings remain unresolved.
Review effort: Lite
Findings: 4
Open (6)
GetAndDelete is non-atomic, allowing CAPTCHA answer reuse · New Keys iteration races with concurrent cache mutations · New Unauthenticated reload IDs enable unbounded cache memory growth · New Shared session lock allows logout and save to race · New Negative session lifetime causes immediate expiration · New 64-bit parsing silently truncates narrower integer fields · New
What changed in this PR
This PR moves Gitea-specific binding, cache, CAPTCHA, and session implementations into internal modules while updating related behavior, configuration, and tests.
Changes:
- Adds internal binding, cache, CAPTCHA, and session implementations.
- Updates CAPTCHA reload/single-use behavior and session persistence.
- Removes obsolete providers and dependencies.
| File | Reviewed changes / final status |
|---|---|
web_src/js/features/captcha.ts |
Adds CAPTCHA reload handling. |
tests/integration/signup_test.go |
Updates signup CAPTCHA coverage. |
tests/integration/session_test.go |
Updates session persistence coverage. |
tests/integration/repo_test.go |
Updates authenticated repository coverage. |
tests/integration/create_no_session_test.go |
Tests session cookie creation. |
templates/user/auth/signin_inner.tmpl |
Adjusts CAPTCHA display for linked accounts. |
templates/user/auth/captcha.tmpl |
Adds image CAPTCHA and reload controls. |
templates/admin/config.tmpl |
Displays cache configuration. |
services/forms/user_form.go |
Updates binding rules. |
services/forms/repo_form.go |
Updates repository form validation. |
services/forms/org.go |
Updates organization validation. |
services/forms/admin.go |
Updates administrative validation. |
services/contexttest/context_tests.go |
Updates session test setup. |
services/context/context_test.go |
Removes obsolete cookie tests. |
services/context/context_cookie.go |
Removes obsolete session cookie helper. |
services/context/captcha.go |
Uses internal CAPTCHA verification. |
services/context/base.go |
Removes redirect cookie workaround. |
services/context/base_test.go |
Removes obsolete redirect tests. |
services/auth/source/oauth2/store.go |
Uses the internal session store. |
services/auth/auth.go |
Updates session regeneration. |
routers/web/web.go |
Registers the internal CAPTCHA handler. |
routers/web/auth/openid.go |
Stops registration after failed CAPTCHA. |
routers/web/auth/linkaccount.go |
Updates CAPTCHA verification flow. |
routers/web/auth/auth.go |
Integrates internal CAPTCHA and sessions. |
routers/web/auth/auth_test.go |
Tests OpenID CAPTCHA rejection. |
routers/web/admin/config.go |
Removes virtual session configuration. |
routers/common/middleware.go |
Initializes internal sessions. |
routers/common/maintenancemode.go |
Updates CAPTCHA path documentation. |
options/locale/locale_en-US.json |
Adds CAPTCHA accessibility strings. |
modules/web/middleware/binding.go |
Switches to internal binding. |
modules/web/binding/binding.go |
Adds internal request binding; moderate width-validation issue remains. |
modules/web/binding/binding_test.go |
Tests internal binding behavior. |
modules/validation/binding.go |
Registers internal validation rules. |
modules/validation/binding_test.go |
Tests binding rule registration. |
modules/structs/user.go |
Updates optional URL validation. |
modules/structs/repo.go |
Updates repository name validation. |
modules/structs/org_team.go |
Updates team visibility validation. |
modules/structs/form.go |
Uses internal binding types. |
modules/structs/admin_user.go |
Updates optional URL validation. |
modules/setting/session.go |
Updates session configuration; negative lifetime handling issue remains. |
modules/setting/session_test.go |
Tests session lifetime defaults. |
modules/setting/cache.go |
Updates cache TTL conversion. |
modules/setting/cache_test.go |
Tests cache TTL behavior. |
modules/session/virtual.go |
Removes the virtual provider. |
modules/session/store.go |
Implements session store lifecycle. |
modules/session/session.go |
Adds internal session middleware. |
modules/session/session_test.go |
Tests session backends and concurrency. |
modules/session/redis.go |
Implements Redis sessions. |
modules/session/mem.go |
Implements memory sessions. |
modules/session/main_test.go |
Initializes session tests. |
modules/session/file.go |
Implements file sessions; concurrent logout resurrection issue remains. |
modules/session/db.go |
Implements database sessions. |
modules/imagecaptcha/imagecaptcha.go |
Implements CAPTCHA storage/serving; unbounded arbitrary refresh issue remains. |
modules/imagecaptcha/imagecaptcha_test.go |
Tests CAPTCHA lifecycle and rendering. |
modules/imagecaptcha/image.go |
Implements CAPTCHA image generation. |
modules/git/last_commit_cache.go |
Honors disabled cache TTLs. |
modules/cache/string_cache.go |
Adds the cache abstraction. |
modules/cache/cache.go |
Handles disabled item caching. |
modules/cache/cache_twoqueue.go |
Implements two-queue caching; concurrent key iteration race remains. |
modules/cache/cache_test.go |
Tests cache adapters and expiration. |
modules/cache/cache_redis.go |
Implements Redis caching. |
modules/cache/cache_memory.go |
Implements memory caching. |
modules/cache/cache_memcache.go |
Implements memcache caching; non-atomic CAPTCHA consumption issue remains. |
models/auth/session.go |
Updates session persistence APIs. |
go.sum |
Removes obsolete dependency checksums. |
go.mod |
Replaces external packages and adds memcache dependency. |
custom/conf/app.example.ini |
Updates cache and session documentation. |
cmd/dump.go |
Updates file-session dump handling. |
assets/go-licenses.json |
Updates dependency licenses. |
.golangci.yml |
Removes obsolete dependency restrictions. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Can we migrate the packages one by one? It is difficult to review the mixed changes ....... |
|
Yeah I will split into 1 PR per package I guess after this review round is done. |
Every session backend now refreshes the expiry when a session is loaded, so a request outliving the session, like a websocket, can no longer revive a DB session that expired in the meantime. JSON request bodies are decoded as a stream again instead of being buffered whole. Integer form fields are parsed at their own width, so out-of-range values are rejected instead of wrapping, and a negative SESSION_LIFE_TIME falls back to the default like GC_INTERVAL_TIME. Assisted-by: Claude Code:claude-opus-5-5
Binding, cache and captcha move into Gitea in their own pull requests, so this one only replaces go-chi/session. Assisted-by: Claude Code:claude-opus-5-5
A websocket opened by reverse proxy or SSPI sign-in only released its session when the connection closed, so the next request signed in again under a new ID and a later logout missed the open connection. Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
|
Split done, this PR now has the session module removal. |
The `gitea.com/go-chi/binding` package only exists for Gitea, so it moves into `modules/web/binding` to fix its bugs directly. Split out of #39504. - GET and HEAD always bind the query - JSON `null` slice elements and nested `TrimSpace` fields bind correctly - Integer fields reject out-of-range values instead of wrapping - An empty JSON body binds nothing and an unknown binding rule is an error Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: bircni <bircni@icloud.com>
|
Maybe also a good chance to rename |
|
Sure, call it out as a breaking change. |
Renamed to "gitea_session" and "gitea_remember" 3015299 |
* origin/main: fix(git): tolerate concurrent repacks in go-git storage (go-gitea#39536) [skip ci] Updated translations via Crowdin chore(lint): apply the main eslint config to vue files (go-gitea#39545) fix(markup): use installed math fonts for MathML in Chromium (go-gitea#39491) refactor: only update sync status columns when syncing push mirror (go-gitea#39517) refactor!: move go-chi/session into Gitea (go-gitea#39504) refactor: move go-chi/cache into Gitea (go-gitea#39530) refactor: move go-chi/captcha into Gitea (go-gitea#39529) refactor: move go-chi/binding into Gitea (go-gitea#39528) fix: use READ COMMITTED transactions on MySQL and MariaDB (go-gitea#39506) fix(git): avoid unnecessary timers during language stats (go-gitea#39531) perf(git): speed up activity top authors and subdirectory listings (go-gitea#39526) Assisted-by: Claude Code:claude-opus-5-5 # Conflicts: # go.sum # modules/git/repo_base_gogit.go



The
gitea.com/go-chi/sessionpackage only exists for Gitea, so it moves intomodules/sessionto fix its bugs directly. Fixes the flake in https://github.com/go-gitea/gitea/actions/runs/36726154500/job/109923538400.mysql,postgres,couchbaseandmemcachesession providers are removed, usefile,dborredisinsteadgitea_sessionandgitea_remember, if you'd like to use the old names, setCOOKIE_NAMEandCOOKIE_REMEMBER_NAMEin app.ini