When deleting a user via CLI (`vikunja user delete <id> -n`), the user
row was deleted first, then `notifications.Notify` was called. But
`Notify` calls `User.ShouldNotify()` which queries the database to check
the user's status — and since the row was already deleted within the same
transaction, it returned `ErrUserDoesNotExist`.
Move the notification call before the `DELETE` so the user row still
exists when `ShouldNotify` checks it.
Closesgo-vikunja/vikunja#2335
- user_export.go: Remove defer s.Close() from checkExportRequest since
it returns the session to callers. Callers now own the session
lifecycle with their own defer s.Close(). Close session on all error
paths within checkExportRequest.
- user_delete.go: Close the read session immediately after Find() before
the per-user deletion loop, avoiding a long-lived transaction holding
locks unnecessarily.
- user/delete.go: Remove double s.Close() in notifyUsersScheduledForDeletion
by closing immediately after Find() instead of using both defer and
explicit close.
- caldav_token.go: Return nil token on Commit() error to prevent callers
from using an unpersisted token.
Refactor functions that created their own sessions when called from
within existing transactions, which caused "database table is locked"
errors in SQLite's shared-cache mode.
Changes:
- Add files.CreateWithSession() to reuse caller's session
- Refactor DeleteBackgroundFileIfExists() to accept session parameter
- Add variadic session parameter to notifications.Notify() and
Notifiable.ShouldNotify() interface
- Update all Notify callers (~17 sites) to pass their session through
- Use files.CreateWithSession in SaveBackgroundFile and NewAttachment
- Fix test code to commit sessions before assertions
Since NewSession() now auto-begins a transaction, explicit Begin()
calls are redundant (xorm's Begin() is a no-op when already in a
transaction). Removing them reduces confusion.
Special case: user_delete.go's loop previously called Begin/Commit
per user on a shared session. Restructured to create a new session
per user deletion so each gets its own transaction.
Add defer s.Close() to sessions that were never closed:
- auth.GetAuthFromClaims inline session
- models.deleteUsers cron function
- notifications.notify database insert
This fixes a bug where the ownership of a project was not transferred when the user was deleted, leading to errors when viewing the project, as the owner user could not be found.
Resolves https://kolaente.dev/vikunja/vikunja/issues/2827