mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-27 02:37:21 +01:00
feat(database): add library filtering to album, folder, and media file queries
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
c1c7cfa49f
commit
5c01eb06ae
5 changed files with 39 additions and 3 deletions
|
|
@ -217,7 +217,8 @@ func (r *albumRepository) UpdateExternalInfo(al *model.Album) error {
|
|||
|
||||
func (r *albumRepository) selectAlbum(options ...model.QueryOptions) SelectBuilder {
|
||||
sql := r.newSelect(options...).Columns("album.*")
|
||||
return r.withAnnotation(sql, "album.id")
|
||||
sql = r.withAnnotation(sql, "album.id")
|
||||
return r.applyLibraryFilter(sql)
|
||||
}
|
||||
|
||||
func (r *albumRepository) Get(id string) (*model.Album, error) {
|
||||
|
|
|
|||
|
|
@ -61,8 +61,9 @@ func newFolderRepository(ctx context.Context, db dbx.Builder) model.FolderReposi
|
|||
}
|
||||
|
||||
func (r folderRepository) selectFolder(options ...model.QueryOptions) SelectBuilder {
|
||||
return r.newSelect(options...).Columns("folder.*", "library.path as library_path").
|
||||
sql := r.newSelect(options...).Columns("folder.*", "library.path as library_path").
|
||||
Join("library on library.id = folder.library_id")
|
||||
return r.applyLibraryFilter(sql)
|
||||
}
|
||||
|
||||
func (r folderRepository) Get(id string) (*model.Folder, error) {
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ func (r *mediaFileRepository) selectMediaFile(options ...model.QueryOptions) Sel
|
|||
sql := r.newSelect(options...).Columns("media_file.*", "library.path as library_path").
|
||||
LeftJoin("library on media_file.library_id = library.id")
|
||||
sql = r.withAnnotation(sql, "media_file.id")
|
||||
return r.withBookmark(sql, "media_file.id")
|
||||
sql = r.withBookmark(sql, "media_file.id")
|
||||
return r.applyLibraryFilter(sql)
|
||||
}
|
||||
|
||||
func (r *mediaFileRepository) Get(id string) (*model.MediaFile, error) {
|
||||
|
|
|
|||
|
|
@ -199,6 +199,29 @@ func (r sqlRepository) applyFilters(sq SelectBuilder, options ...model.QueryOpti
|
|||
return sq
|
||||
}
|
||||
|
||||
// applyLibraryFilter adds library filtering to queries for tables that have a library_id column
|
||||
// This ensures users only see content from libraries they have access to
|
||||
func (r sqlRepository) applyLibraryFilter(sq SelectBuilder) SelectBuilder {
|
||||
user := loggedUser(r.ctx)
|
||||
|
||||
// Admin users see all content
|
||||
if user.IsAdmin {
|
||||
return sq
|
||||
}
|
||||
|
||||
// Get user's accessible library IDs
|
||||
userID := userId(r.ctx)
|
||||
if userID == invalidUserId {
|
||||
// No user context - return empty result set
|
||||
return sq.Where(Eq{"1": "0"})
|
||||
}
|
||||
|
||||
// Use subquery to filter by user's library access
|
||||
// This approach doesn't require DataStore in context
|
||||
return sq.Where(Expr(r.tableName+".library_id IN ("+
|
||||
"SELECT ul.library_id FROM user_library ul WHERE ul.user_id = ?)", userID))
|
||||
}
|
||||
|
||||
func (r sqlRepository) seedKey() string {
|
||||
// Seed keys must be all lowercase, or else SQLite3 will encode it, making it not match the seed
|
||||
// used in the query. Hashing the user ID and converting it to a hex string will do the trick
|
||||
|
|
|
|||
|
|
@ -71,6 +71,16 @@ var _ = Describe("Scanner", Ordered, func() {
|
|||
}
|
||||
ds.MockedMediaFile = mfRepo
|
||||
|
||||
// Create the admin user in the database to match the context
|
||||
adminUser := model.User{
|
||||
ID: "123",
|
||||
UserName: "admin",
|
||||
Name: "Admin User",
|
||||
IsAdmin: true,
|
||||
NewPassword: "password",
|
||||
}
|
||||
Expect(ds.User(ctx).Put(&adminUser)).To(Succeed())
|
||||
|
||||
s = scanner.New(ctx, ds, artwork.NoopCacheWarmer(), events.NoopBroker(),
|
||||
core.NewPlaylists(ds), metrics.NewNoopInstance())
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue