fix(caldav): eliminate nested db session in CalDAV auth

checkUserCaldavTokens called user.GetCaldavTokens which creates its own
db.NewSession(), while the caller (BasicAuth) already holds an open
session. With SQLite this caused a deadlock because the second session
blocks on the write lock held by the first session in the same goroutine.

Add GetCaldavTokensWithSession that accepts an existing session and use
it from checkUserCaldavTokens.
This commit is contained in:
kolaente
2026-03-02 21:52:50 +01:00
parent 530973c475
commit 39acdac531
2 changed files with 13 additions and 2 deletions

View File

@@ -61,7 +61,7 @@ func checkUserCaldavTokens(s *xorm.Session, login *user.Login) (*user.User, erro
log.Warningf("Error while retrieving users from database: %v", err)
return nil, err
}
tokens, err := user.GetCaldavTokens(usr)
tokens, err := user.GetCaldavTokensWithSession(s, usr)
if err != nil {
log.Errorf("Error while getting tokens for caldav auth: %v", err)
return nil, err

View File

@@ -16,7 +16,11 @@
package user
import "code.vikunja.io/api/pkg/db"
import (
"code.vikunja.io/api/pkg/db"
"xorm.io/xorm"
)
func GenerateNewCaldavToken(u *User) (token *Token, err error) {
s := db.NewSession()
@@ -42,6 +46,13 @@ func GetCaldavTokens(u *User) (tokens []*Token, err error) {
return getTokensForKind(s, u, TokenCaldavAuth)
}
// GetCaldavTokensWithSession is like GetCaldavTokens but uses an existing
// database session instead of creating a new one. This avoids nested sessions
// which cause deadlocks with SQLite's single-writer model.
func GetCaldavTokensWithSession(s *xorm.Session, u *User) (tokens []*Token, err error) {
return getTokensForKind(s, u, TokenCaldavAuth)
}
func DeleteCaldavTokenByID(u *User, id int64) error {
s := db.NewSession()
defer s.Close()