From 91647ed46f1eaeb30c6f71a466dfe38a3eaab420 Mon Sep 17 00:00:00 2001 From: Deluan Date: Mon, 4 May 2026 17:29:27 -0400 Subject: [PATCH 1/4] fix(scanner): skip library filter for empty user ID on fresh installs When no admin user exists (fresh DB), WithAdminUser falls back to model.User{ID: ""}. The empty ID bypassed neither the invalidUserId ("-1") check nor the IsAdmin check in applyLibraryFilter, causing Phase 3's GetTouchedAlbums to filter by user_id="" and find zero albums. The album refresh never ran, leaving multi-disc albums with incomplete folder_ids from Phase 1. Fix: treat empty user ID the same as invalidUserId in applyLibraryFilter, skipping the library filter entirely. This is more targeted than making the fallback user admin, which would affect other callers like Phase 4 playlist import. Signed-off-by: Deluan --- persistence/sql_base_repository.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/persistence/sql_base_repository.go b/persistence/sql_base_repository.go index fd263d37b..98aa66158 100644 --- a/persistence/sql_base_repository.go +++ b/persistence/sql_base_repository.go @@ -205,8 +205,8 @@ func libraryIdFilter(_ string, value any) Sqlizer { func (r sqlRepository) applyLibraryFilter(sq SelectBuilder, tableName ...string) SelectBuilder { user := loggedUser(r.ctx) - // If the user is an admin, or the user ID is invalid (e.g., when no user is logged in), skip the library filter - if user.IsAdmin || user.ID == invalidUserId { + // If the user is an admin, or the user ID is empty/invalid (e.g., when no user is logged in), skip the library filter + if user.IsAdmin || user.ID == "" || user.ID == invalidUserId { return sq } From fda536ff1766dbf6a9fa4a1c29bf5c7c4d45f6e3 Mon Sep 17 00:00:00 2001 From: Deluan Date: Mon, 4 May 2026 17:53:44 -0400 Subject: [PATCH 2/4] fix(playlists): prevent playlist import when no admin user exists Signed-off-by: Deluan --- scanner/phase_4_playlists.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scanner/phase_4_playlists.go b/scanner/phase_4_playlists.go index f726343f2..94349720c 100644 --- a/scanner/phase_4_playlists.go +++ b/scanner/phase_4_playlists.go @@ -50,7 +50,7 @@ func (p *phasePlaylists) produce(put func(entry *model.Folder)) error { return nil } u, _ := request.UserFrom(p.ctx) - if !u.IsAdmin { + if !u.IsAdmin && u.ID == "" { log.Warn(p.ctx, "Playlists will not be imported, as there are no admin users yet, "+ "Please create an admin user first, and then update the playlists for them to be imported") return nil From 5b01636d3300cc96a1cd3d4f9d7f425d0760a6f9 Mon Sep 17 00:00:00 2001 From: Deluan Date: Mon, 4 May 2026 17:54:42 -0400 Subject: [PATCH 3/4] Revert "fix(scanner): skip library filter for empty user ID on fresh installs" This reverts commit 91647ed46f1eaeb30c6f71a466dfe38a3eaab420. --- persistence/sql_base_repository.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/persistence/sql_base_repository.go b/persistence/sql_base_repository.go index 98aa66158..fd263d37b 100644 --- a/persistence/sql_base_repository.go +++ b/persistence/sql_base_repository.go @@ -205,8 +205,8 @@ func libraryIdFilter(_ string, value any) Sqlizer { func (r sqlRepository) applyLibraryFilter(sq SelectBuilder, tableName ...string) SelectBuilder { user := loggedUser(r.ctx) - // If the user is an admin, or the user ID is empty/invalid (e.g., when no user is logged in), skip the library filter - if user.IsAdmin || user.ID == "" || user.ID == invalidUserId { + // If the user is an admin, or the user ID is invalid (e.g., when no user is logged in), skip the library filter + if user.IsAdmin || user.ID == invalidUserId { return sq } From fec03d8780d98da7ae04fb4907bec56b4a4448af Mon Sep 17 00:00:00 2001 From: Deluan Date: Mon, 4 May 2026 17:58:26 -0400 Subject: [PATCH 4/4] fix(scanner): check user ID instead of IsAdmin for playlist import guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The condition `!u.IsAdmin && u.ID == ""` was wrong — with the synthetic admin fallback (IsAdmin: true, ID: ""), it evaluated to false and allowed playlist import with an empty OwnerID. The check should be just `u.ID == ""` to skip whenever there's no real user. --- scanner/phase_4_playlists.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scanner/phase_4_playlists.go b/scanner/phase_4_playlists.go index 94349720c..8e8b1ca7f 100644 --- a/scanner/phase_4_playlists.go +++ b/scanner/phase_4_playlists.go @@ -50,7 +50,7 @@ func (p *phasePlaylists) produce(put func(entry *model.Folder)) error { return nil } u, _ := request.UserFrom(p.ctx) - if !u.IsAdmin && u.ID == "" { + if u.ID == "" { log.Warn(p.ctx, "Playlists will not be imported, as there are no admin users yet, "+ "Please create an admin user first, and then update the playlists for them to be imported") return nil