From 39acdac531feadc77bb3aa9a064eb6d639a964e2 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 2 Mar 2026 21:52:50 +0100 Subject: [PATCH] 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. --- pkg/routes/caldav/auth.go | 2 +- pkg/user/caldav_token.go | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/routes/caldav/auth.go b/pkg/routes/caldav/auth.go index 3af6b6790..ce9c3fdeb 100644 --- a/pkg/routes/caldav/auth.go +++ b/pkg/routes/caldav/auth.go @@ -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 diff --git a/pkg/user/caldav_token.go b/pkg/user/caldav_token.go index 438136525..d407b27a2 100644 --- a/pkg/user/caldav_token.go +++ b/pkg/user/caldav_token.go @@ -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()