From af2c54c8f0635a9adffcdf9467a32cfa0f410230 Mon Sep 17 00:00:00 2001 From: zZebrahz Date: Sat, 30 May 2026 19:21:25 -0700 Subject: [PATCH] fix(auth): revoke sessions on library scope nil changes --- internal/api/handlers/admin.go | 9 +++++++-- internal/api/handlers/admin_test.go | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/internal/api/handlers/admin.go b/internal/api/handlers/admin.go index c40eed30..e1ccb92f 100644 --- a/internal/api/handlers/admin.go +++ b/internal/api/handlers/admin.go @@ -792,8 +792,13 @@ func updateRequiresSessionRevocation(current *models.User, input models.UpdateUs if input.Enabled != nil && *input.Enabled != current.Enabled { return true } - if input.LibraryIDs != nil && !slices.Equal(*input.LibraryIDs, current.LibraryIDs) { - return true + if input.LibraryIDs != nil { + if (*input.LibraryIDs == nil) != (current.LibraryIDs == nil) { + return true + } + if *input.LibraryIDs != nil && !slices.Equal(*input.LibraryIDs, current.LibraryIDs) { + return true + } } if input.Permissions != nil && !slices.Equal(*input.Permissions, current.Permissions) { return true diff --git a/internal/api/handlers/admin_test.go b/internal/api/handlers/admin_test.go index d3bd8d64..423e0f09 100644 --- a/internal/api/handlers/admin_test.go +++ b/internal/api/handlers/admin_test.go @@ -13,6 +13,8 @@ func TestUpdateRequiresSessionRevocation(t *testing.T) { disabled := false libraryIDs := []int{1, 2} sameLibraryIDs := []int{1} + emptyLibraryIDs := []int{} + var allLibraryIDs []int maxPlaybackQuality := "1080p" sameMaxPlaybackQuality := "original" password := "new-password" @@ -74,6 +76,11 @@ func TestUpdateRequiresSessionRevocation(t *testing.T) { in: models.UpdateUserInput{LibraryIDs: &sameLibraryIDs}, want: false, }, + { + name: "library ids nil differs from restricted", + in: models.UpdateUserInput{LibraryIDs: &allLibraryIDs}, + want: true, + }, { name: "max playback quality", in: models.UpdateUserInput{MaxPlaybackQuality: &maxPlaybackQuality}, @@ -108,4 +115,18 @@ func TestUpdateRequiresSessionRevocation(t *testing.T) { } }) } + + unrestrictedCurrent := *current + unrestrictedCurrent.LibraryIDs = nil + t.Run("library ids empty differs from nil", func(t *testing.T) { + if got := updateRequiresSessionRevocation(&unrestrictedCurrent, models.UpdateUserInput{LibraryIDs: &emptyLibraryIDs}); !got { + t.Fatalf("updateRequiresSessionRevocation() = %v, want true", got) + } + }) + + t.Run("library ids nil unchanged", func(t *testing.T) { + if got := updateRequiresSessionRevocation(&unrestrictedCurrent, models.UpdateUserInput{LibraryIDs: &allLibraryIDs}); got { + t.Fatalf("updateRequiresSessionRevocation() = %v, want false", got) + } + }) }