navidrome/server/jellyfin/users.go
Deluan fbce1d3500 feat(jellyfin): full multi-library support with per-user access scoping
Replace the single hardcoded "music" UserView with one CollectionFolder
view per library the user can access, and scope every /Items browse
query (albums, songs, artists, /Latest) to those libraries via
server/filter's ApplyLibraryFilter/ApplyArtistLibraryFilter.

ParentId is now disambiguated: a numeric value the user has access to is
treated as a library scope (browsing a UserView), otherwise it falls
through as an entity id (artist/album), which safely matches nothing
rather than leaking another library's content. getItem now 404s when
fetching an album or song outside the user's accessible libraries;
artists are skipped (they can span multiple libraries) with a TODO.

Genres remain unscoped since they're global tags, not per-library
entities.
2026-07-05 15:53:02 -04:00

37 lines
1.2 KiB
Go

package jellyfin
import (
"net/http"
"strconv"
"github.com/navidrome/navidrome/model/request"
"github.com/navidrome/navidrome/server/jellyfin/dto"
)
// getUserViews returns one CollectionFolder view per library the current user can access,
// so Jellyfin clients browse each library as its own top-level view (instead of a single
// aggregate "music" view spanning every library).
func (api *Router) getUserViews(w http.ResponseWriter, r *http.Request) {
u, _ := request.UserFrom(r.Context())
views := make([]dto.BaseItemDto, 0, len(u.Libraries))
for _, lib := range u.Libraries {
views = append(views, dto.BaseItemDto{
Id: strconv.Itoa(lib.ID),
Name: lib.Name,
Type: "CollectionFolder",
CollectionType: "music",
IsFolder: true,
BackdropImageTags: []string{},
})
}
api.ok(w, r, dto.QueryResult{Items: views, TotalRecordCount: len(views), StartIndex: 0})
}
func (api *Router) getCurrentUser(w http.ResponseWriter, r *http.Request) {
u, _ := request.UserFrom(r.Context())
api.ok(w, r, userToDto(&u, api.serverName()))
}
func (api *Router) getPublicUsers(w http.ResponseWriter, r *http.Request) {
api.ok(w, r, []dto.UserDto{}) // manual login only
}