mirror of
https://github.com/go-gitea/gitea.git
synced 2025-10-03 15:26:29 +00:00

the middleware that creates the session provider just panics if on creation the config is wrong. this is not catched and so you just get an cryptic stacktrace with no point where to look at (as user). ## Before ``` 2025/09/16 03:56:37 ...xer/stats/indexer.go:87:populateRepoIndexer() [I] Done (re)populating the repo stats indexer with existing repositories 2025/09/16 03:56:37 modules/ssh/ssh.go:387:Listen() [I] Adding SSH host key: /var/lib/gitea/data/ssh/gitea.rsa 2025/09/16 03:56:37 modules/ssh/init.go:26:Init() [I] SSH server started on :1234. Cipher list ([chacha20-poly1305@openssh.com aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com]), key exchange algorithms ([curve25519-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group14-sha256 diffie-hellman-group14-sha1]), MACs ([hmac-sha2-256-etm@openssh.com hmac-sha2-256 hmac-sha1]) 2025/09/16 03:56:37 ...s/graceful/server.go:50:NewServer() [I] Starting new SSH server: tcp::1234 on PID: 83337 2025/09/16 03:56:38 cmd/web.go:231:func1() [F] PANIC: dial tcp 127.0.0.1:6379: connect: connection refused gitea.com/go-chi/session@v0.0.0-20240316035857-16768d98ec96/session.go:239 (0x1cdb908) code.gitea.io/gitea/routers/common/middleware.go:108 (0x2547f5a) code.gitea.io/gitea/routers/web/web.go:270 (0x278b8e9) code.gitea.io/gitea/routers/init.go:185 (0x2850d89) code.gitea.io/gitea/cmd/web.go:211 (0x295c5ad) code.gitea.io/gitea/cmd/web.go:262 (0x295cacb) code.gitea.io/gitea/cmd/main.go:111 (0x2953422) github.com/urfave/cli/v2@v2.27.2/command.go:276 (0x1cc3dfd) github.com/urfave/cli/v2@v2.27.2/command.go:269 (0x1cc4084) github.com/urfave/cli/v2@v2.27.2/app.go:333 (0x1cc086a) github.com/urfave/cli/v2@v2.27.2/app.go:307 (0x2953f18) code.gitea.io/gitea/cmd/main.go:172 (0x2953efc) code.gitea.io/gitea/main.go:46 (0x2998498) runtime/proc.go:283 (0x4471ca) runtime/asm_amd64.s:1700 (0x484a20) ``` ## After ``` 2025/09/22 22:52:35 .../templates/htmlrenderer.go:118:initHTMLRenderer() [D] Creating static HTML Renderer 2025/09/22 22:52:35 routers/web/web.go:273:Routes() [F] common.Sessioner failed: failed to create session middleware: dial tcp 127.0.0.1:6379: connect: connection refused ``` --------- Signed-off-by: 6543 <6543@obermui.de>
177 lines
3.8 KiB
Go
177 lines
3.8 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package session
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
|
|
"code.gitea.io/gitea/models/auth"
|
|
"code.gitea.io/gitea/modules/timeutil"
|
|
|
|
"gitea.com/go-chi/session"
|
|
)
|
|
|
|
// DBStore represents a session store implementation based on the DB.
|
|
type DBStore struct {
|
|
sid string
|
|
lock sync.RWMutex
|
|
data map[any]any
|
|
}
|
|
|
|
func dbContext() context.Context {
|
|
return context.Background()
|
|
}
|
|
|
|
// NewDBStore creates and returns a DB session store.
|
|
func NewDBStore(sid string, kv map[any]any) *DBStore {
|
|
return &DBStore{
|
|
sid: sid,
|
|
data: kv,
|
|
}
|
|
}
|
|
|
|
// Set sets value to given key in session.
|
|
func (s *DBStore) Set(key, val any) error {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
|
|
s.data[key] = val
|
|
return nil
|
|
}
|
|
|
|
// Get gets value by given key in session.
|
|
func (s *DBStore) Get(key any) any {
|
|
s.lock.RLock()
|
|
defer s.lock.RUnlock()
|
|
|
|
return s.data[key]
|
|
}
|
|
|
|
// Delete delete a key from session.
|
|
func (s *DBStore) Delete(key any) error {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
|
|
delete(s.data, key)
|
|
return nil
|
|
}
|
|
|
|
// ID returns current session ID.
|
|
func (s *DBStore) ID() string {
|
|
return s.sid
|
|
}
|
|
|
|
// Release releases resource and save data to provider.
|
|
func (s *DBStore) Release() error {
|
|
// Skip encoding if the data is empty
|
|
if len(s.data) == 0 {
|
|
return nil
|
|
}
|
|
|
|
data, err := session.EncodeGob(s.data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return auth.UpdateSession(dbContext(), s.sid, data)
|
|
}
|
|
|
|
// Flush deletes all session data.
|
|
func (s *DBStore) Flush() error {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
|
|
s.data = make(map[any]any)
|
|
return nil
|
|
}
|
|
|
|
// DBProvider represents a DB session provider implementation.
|
|
type DBProvider struct {
|
|
maxLifetime int64
|
|
}
|
|
|
|
// Init initializes DB session provider.
|
|
// connStr: username:password@protocol(address)/dbname?param=value
|
|
func (p *DBProvider) Init(maxLifetime int64, connStr string) error {
|
|
p.maxLifetime = maxLifetime
|
|
return nil
|
|
}
|
|
|
|
// Read returns raw session store by session ID.
|
|
func (p *DBProvider) Read(sid string) (session.RawStore, error) {
|
|
s, err := auth.ReadSession(dbContext(), sid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var kv map[any]any
|
|
if len(s.Data) == 0 || s.Expiry.Add(p.maxLifetime) <= timeutil.TimeStampNow() {
|
|
kv = make(map[any]any)
|
|
} else {
|
|
kv, err = session.DecodeGob(s.Data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return NewDBStore(sid, kv), nil
|
|
}
|
|
|
|
// Exist returns true if session with given ID exists.
|
|
func (p *DBProvider) Exist(sid string) (bool, error) {
|
|
has, err := auth.ExistSession(dbContext(), sid)
|
|
if err != nil {
|
|
return false, fmt.Errorf("session/DB: error checking existence: %w", err)
|
|
}
|
|
return has, nil
|
|
}
|
|
|
|
// Destroy deletes a session by session ID.
|
|
func (p *DBProvider) Destroy(sid string) error {
|
|
return auth.DestroySession(dbContext(), sid)
|
|
}
|
|
|
|
// Regenerate regenerates a session store from old session ID to new one.
|
|
func (p *DBProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) {
|
|
s, err := auth.RegenerateSession(dbContext(), oldsid, sid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var kv map[any]any
|
|
if len(s.Data) == 0 || s.Expiry.Add(p.maxLifetime) <= timeutil.TimeStampNow() {
|
|
kv = make(map[any]any)
|
|
} else {
|
|
kv, err = session.DecodeGob(s.Data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return NewDBStore(sid, kv), nil
|
|
}
|
|
|
|
// Count counts and returns number of sessions.
|
|
func (p *DBProvider) Count() (int, error) {
|
|
total, err := auth.CountSessions(dbContext())
|
|
if err != nil {
|
|
return 0, fmt.Errorf("session/DB: error counting records: %w", err)
|
|
}
|
|
return int(total), nil
|
|
}
|
|
|
|
// GC calls GC to clean expired sessions.
|
|
func (p *DBProvider) GC() {
|
|
if err := auth.CleanupSessions(dbContext(), p.maxLifetime); err != nil {
|
|
log.Printf("session/DB: error garbage collecting: %v", err)
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
session.Register("db", &DBProvider{})
|
|
}
|