mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-27 19:38:57 +01:00
feat: add library access validation to selectedMusicFolderIds
Enhanced the selectedMusicFolderIds function to validate musicFolderId parameters against the user's accessible libraries. Invalid library IDs (those the user doesn't have access to) are now silently filtered out, improving security by preventing users from accessing libraries they don't have permission for. Changes include: - Added validation logic to check musicFolderId parameters against user's accessible libraries - Added slices package import for efficient validation - Enhanced function documentation to clarify validation behavior - Added comprehensive test cases covering validation scenarios - Maintains backward compatibility with existing behavior
This commit is contained in:
parent
c5b7857fef
commit
bbc6d0722c
2 changed files with 33 additions and 3 deletions
|
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
|
@ -485,6 +486,7 @@ func getUserAccessibleLibraries(ctx context.Context) []model.Library {
|
|||
// selectedMusicFolderIds retrieves the music folder IDs from the request parameters.
|
||||
// If no IDs are provided, it returns all libraries the user has access to (based on the user found in the context).
|
||||
// If the parameter is required and not present, it returns an error.
|
||||
// Invalid library IDs (those the user doesn't have access to) are silently filtered out.
|
||||
func selectedMusicFolderIds(r *http.Request, required bool) ([]int, error) {
|
||||
p := req.Params(r)
|
||||
musicFolderIds, err := p.Ints("musicFolderId")
|
||||
|
|
@ -494,11 +496,21 @@ func selectedMusicFolderIds(r *http.Request, required bool) ([]int, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Get user's accessible libraries for validation
|
||||
libraries := getUserAccessibleLibraries(r.Context())
|
||||
accessibleLibraryIds := slice.Map(libraries, func(lib model.Library) int { return lib.ID })
|
||||
|
||||
if len(musicFolderIds) > 0 {
|
||||
return musicFolderIds, nil
|
||||
// Validate and filter out invalid library IDs
|
||||
validIds := make([]int, 0, len(musicFolderIds))
|
||||
for _, id := range musicFolderIds {
|
||||
if slices.Contains(accessibleLibraryIds, id) {
|
||||
validIds = append(validIds, id)
|
||||
}
|
||||
}
|
||||
return validIds, nil
|
||||
}
|
||||
|
||||
// If no musicFolderId is provided, return all libraries the user has access to.
|
||||
libraries := getUserAccessibleLibraries(r.Context())
|
||||
return slice.Map(libraries, func(lib model.Library) int { return lib.ID }), nil
|
||||
return accessibleLibraryIds, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,6 +203,24 @@ var _ = Describe("helpers", func() {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(ids).To(Equal([]int{2})) // Only valid ID is returned
|
||||
})
|
||||
|
||||
It("should filter out library IDs the user doesn't have access to", func() {
|
||||
r := httptest.NewRequest("GET", "/test?musicFolderId=1&musicFolderId=5&musicFolderId=2&musicFolderId=99", nil)
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
ids, err := selectedMusicFolderIds(r, false)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(ids).To(Equal([]int{1, 2})) // Only accessible libraries (1, 2) are returned, 5 and 99 are filtered out
|
||||
})
|
||||
|
||||
It("should return empty slice when user has no access to any of the requested libraries", func() {
|
||||
r := httptest.NewRequest("GET", "/test?musicFolderId=99&musicFolderId=100", nil)
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
ids, err := selectedMusicFolderIds(r, false)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(ids).To(Equal([]int{})) // No accessible libraries in the request
|
||||
})
|
||||
})
|
||||
|
||||
Context("when musicFolderId parameter is not provided", func() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue