mirror of
https://github.com/navidrome/navidrome.git
synced 2026-11-04 09:18:39 +01:00
fix(artwork): enforce entity visibility on the Subsonic getCoverArt path
serveEntity reads persisted item_artwork by id, bypassing the library and private- playlist filters that the legacy entity-load applied. On the authenticated Subsonic path a user could fetch artwork for an inaccessible album or someone else's private playlist by guessing an id. getCoverArt now resolves the underlying entity through the request-scoped (filtered) repositories and serves the placeholder when it is not visible, so existence isn't leaked and the always-an-image invariant holds. The public share (JWT-authorized) and Jellyfin (admin) paths are intentionally untouched.
This commit is contained in:
parent
8d715ba2fa
commit
9dd306eb10
3 changed files with 66 additions and 0 deletions
|
|
@ -308,6 +308,10 @@ func (s *service) enqueue(ctx context.Context, artID model.ArtworkID, priority i
|
|||
}
|
||||
|
||||
func (s *service) placeholder(kind model.Kind) *Image {
|
||||
return placeholderImage(kind)
|
||||
}
|
||||
|
||||
func placeholderImage(kind model.Kind) *Image {
|
||||
path := consts.PlaceholderAlbumArt
|
||||
if kind == model.KindArtistArtwork {
|
||||
path = consts.PlaceholderArtistArt
|
||||
|
|
@ -316,6 +320,13 @@ func (s *service) placeholder(kind model.Kind) *Image {
|
|||
return &Image{ReadCloser: r, Placeholder: true}
|
||||
}
|
||||
|
||||
// PlaceholderFor returns the kind-appropriate placeholder for an artwork id, for callers that must
|
||||
// serve a placeholder without consulting persisted state (e.g. an access-control denial).
|
||||
func PlaceholderFor(id string) *Image {
|
||||
artID, _ := model.ParseArtworkID(id)
|
||||
return placeholderImage(artID.Kind)
|
||||
}
|
||||
|
||||
type coverArtIDGetter interface {
|
||||
CoverArtID() model.ArtworkID
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue