mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-19 12:56:10 +02:00
fix(session): address review feedback
- Use shared flex-divided-list/items-with-main classes in session templates so they pick up consistent styling instead of relying on non-existent flex-list/flex-item-* classes. - Add CountUserSessionsByUserID helper and use it in admin user view so we don't materialize the full session list just to compute total/active counts. - Bound the VirtualSessionProvider tombstone map by self-expiring entries via time.AfterFunc, so map size no longer depends on the session GC interval. Co-Authored-By: GitHub Copilot (Claude Opus 4.7) <copilot@github.com>
This commit is contained in:
1 parent
093061d3ba
commit
3e2fe1fed4
5 files changed
+51
-46
No files matched your search
+16
-20
@@ -17,6 +17,11 @@ import (
|
||||
postgres "gitea.com/go-chi/session/postgres"
|
||||
)
|
||||
|
||||
// tombstoneTTL is how long a destroyed session ID is remembered so that
|
||||
// concurrent requests releasing after destruction cannot recreate the session
|
||||
// or be re-authenticated.
|
||||
const tombstoneTTL = 10 * time.Minute
|
||||
|
||||
// VirtualSessionProvider represents a shadowed session provider implementation.
|
||||
// It wraps a real session provider and adds "tombstone" tracking for destroyed
|
||||
// sessions so that concurrent requests (e.g. EventSource) cannot accidentally
|
||||
@@ -30,6 +35,8 @@ type VirtualSessionProvider struct {
|
||||
// a FileStore reference may call Release() and recreate the file.
|
||||
// By tracking destroyed IDs, Read() returns an inert VirtualStore
|
||||
// that prevents re-authentication and avoids recreating the file.
|
||||
// Entries self-expire after tombstoneTTL via time.AfterFunc so the map
|
||||
// stays bounded regardless of session GC interval.
|
||||
destroyedSIDs sync.Map // sid -> time.Time
|
||||
}
|
||||
|
||||
@@ -100,6 +107,10 @@ func (o *VirtualSessionProvider) Destroy(sid string) error {
|
||||
o.lock.Lock()
|
||||
defer o.lock.Unlock()
|
||||
o.destroyedSIDs.Store(sid, time.Now())
|
||||
// Self-expire the tombstone so the map stays bounded between session GCs.
|
||||
time.AfterFunc(tombstoneTTL, func() {
|
||||
o.destroyedSIDs.Delete(sid)
|
||||
})
|
||||
return o.provider.Destroy(sid)
|
||||
}
|
||||
|
||||
@@ -124,28 +135,13 @@ func (o *VirtualSessionProvider) GC() {
|
||||
|
||||
o.provider.GC()
|
||||
|
||||
// Clean up tombstone entries and re-destroy any files that may have
|
||||
// been recreated by concurrent requests releasing after destruction.
|
||||
cutoff := time.Now().Add(-10 * time.Minute)
|
||||
var stale []string
|
||||
var active []string
|
||||
o.destroyedSIDs.Range(func(key, value any) bool {
|
||||
sid := key.(string)
|
||||
if value.(time.Time).Before(cutoff) {
|
||||
stale = append(stale, sid)
|
||||
} else {
|
||||
active = append(active, sid)
|
||||
}
|
||||
// Re-destroy any sessions that may have been recreated by concurrent
|
||||
// requests releasing after destruction. Tombstones themselves expire
|
||||
// via time.AfterFunc in Destroy() so no manual cleanup is needed here.
|
||||
o.destroyedSIDs.Range(func(key, _ any) bool {
|
||||
_ = o.provider.Destroy(key.(string))
|
||||
return true
|
||||
})
|
||||
for _, sid := range stale {
|
||||
o.destroyedSIDs.Delete(sid)
|
||||
}
|
||||
if len(active) > 0 {
|
||||
for _, sid := range active {
|
||||
_ = o.provider.Destroy(sid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
Reference in new issue
Block a user