From b1e85dca7973fb33ad5df464ae88e1b78c8ee94b Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sat, 16 May 2026 19:30:54 -0400 Subject: [PATCH] fix(auth): hand over library and media item ownership on admin deletion When an admin was deleted, the ON DELETE SET NULL foreign key would set created_by_admin_id to NULL on all their libraries. This caused the scanner to fail to find an admin ID for broadcasting scan-complete WebSocket messages. - On admin deletion, reassign all libraries and media items to the next admin - Prevents created_by_admin_id from ever being NULL on active libraries - Uses new ReassignLibraries and ReassignMediaItems DB queries --- internal/handlers/auth.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/handlers/auth.go b/internal/handlers/auth.go index 64c28fc..e847377 100644 --- a/internal/handlers/auth.go +++ b/internal/handlers/auth.go @@ -903,6 +903,22 @@ func (h *AuthHandler) DeleteUser(c *echo.Context) error { return c.JSON(http.StatusBadRequest, map[string]string{"error": "cannot delete the last admin account"}) } + // If deleting an admin, reassign their libraries and media items to another admin + // before deletion to prevent ON DELETE SET NULL from orphaning ownership + if targetUserRole == "admin" { + successor, err := h.db.GetFirstAdminExclude(c.Request().Context(), targetUserUUID) + if err == nil { + _ = h.db.ReassignLibraries(c.Request().Context(), database.ReassignLibrariesParams{ + CreatedByAdminID: targetUserUUID, + CreatedByAdminID_2: successor.ID, + }) + _ = h.db.ReassignMediaItems(c.Request().Context(), database.ReassignMediaItemsParams{ + AddedByAdminID: targetUserUUID, + AddedByAdminID_2: successor.ID, + }) + } + } + // Delete user (this will cascade to delete all related data) err = h.db.DeleteUser(c.Request().Context(), targetUserUUID) if err != nil {