mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-30 15:07:56 +01:00
feat: add library access methods to User model
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
3f44e86299
commit
915f09a75c
2 changed files with 194 additions and 1 deletions
|
|
@ -1,6 +1,8 @@
|
|||
package model
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID string `structs:"id" json:"id"`
|
||||
|
|
@ -25,6 +27,45 @@ type User struct {
|
|||
CurrentPassword string `structs:"current_password,omitempty" json:"currentPassword,omitempty"`
|
||||
}
|
||||
|
||||
func (u User) HasLibraryAccess(libraryID int) bool {
|
||||
if u.IsAdmin {
|
||||
return true // Admin users have access to all libraries
|
||||
}
|
||||
for _, lib := range u.Libraries {
|
||||
if lib.ID == libraryID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AccessibleLibraryIDs returns a slice of library IDs that the user has access to
|
||||
func (u User) AccessibleLibraryIDs() []int {
|
||||
if len(u.Libraries) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ids := make([]int, len(u.Libraries))
|
||||
for i, lib := range u.Libraries {
|
||||
ids[i] = lib.ID
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func (u User) FilteredLibraries(libraryIds []int) Libraries {
|
||||
libMap := make(map[int]Library, len(u.Libraries))
|
||||
for _, lib := range u.Libraries {
|
||||
libMap[lib.ID] = lib
|
||||
}
|
||||
var filtered Libraries
|
||||
for _, id := range libraryIds {
|
||||
if lib, ok := libMap[id]; ok {
|
||||
filtered = append(filtered, lib)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
type Users []User
|
||||
|
||||
type UserRepository interface {
|
||||
|
|
|
|||
152
model/user_test.go
Normal file
152
model/user_test.go
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
package model_test
|
||||
|
||||
import (
|
||||
"github.com/navidrome/navidrome/model"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("User", func() {
|
||||
var user model.User
|
||||
var libraries model.Libraries
|
||||
|
||||
BeforeEach(func() {
|
||||
libraries = model.Libraries{
|
||||
{ID: 1, Name: "Rock Library", Path: "/music/rock"},
|
||||
{ID: 2, Name: "Jazz Library", Path: "/music/jazz"},
|
||||
{ID: 3, Name: "Classical Library", Path: "/music/classical"},
|
||||
}
|
||||
|
||||
user = model.User{
|
||||
ID: "user1",
|
||||
UserName: "testuser",
|
||||
Name: "Test User",
|
||||
Email: "test@example.com",
|
||||
IsAdmin: false,
|
||||
Libraries: libraries,
|
||||
}
|
||||
})
|
||||
|
||||
Describe("HasLibraryAccess", func() {
|
||||
Context("when user is admin", func() {
|
||||
BeforeEach(func() {
|
||||
user.IsAdmin = true
|
||||
})
|
||||
|
||||
It("returns true for any library ID", func() {
|
||||
Expect(user.HasLibraryAccess(1)).To(BeTrue())
|
||||
Expect(user.HasLibraryAccess(99)).To(BeTrue())
|
||||
Expect(user.HasLibraryAccess(-1)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("returns true even when user has no libraries assigned", func() {
|
||||
user.Libraries = nil
|
||||
Expect(user.HasLibraryAccess(1)).To(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Context("when user is not admin", func() {
|
||||
BeforeEach(func() {
|
||||
user.IsAdmin = false
|
||||
})
|
||||
|
||||
It("returns true for libraries the user has access to", func() {
|
||||
Expect(user.HasLibraryAccess(1)).To(BeTrue())
|
||||
Expect(user.HasLibraryAccess(2)).To(BeTrue())
|
||||
Expect(user.HasLibraryAccess(3)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("returns false for libraries the user does not have access to", func() {
|
||||
Expect(user.HasLibraryAccess(4)).To(BeFalse())
|
||||
Expect(user.HasLibraryAccess(99)).To(BeFalse())
|
||||
Expect(user.HasLibraryAccess(-1)).To(BeFalse())
|
||||
Expect(user.HasLibraryAccess(0)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("returns false when user has no libraries assigned", func() {
|
||||
user.Libraries = nil
|
||||
Expect(user.HasLibraryAccess(1)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("handles duplicate library IDs correctly", func() {
|
||||
user.Libraries = model.Libraries{
|
||||
{ID: 1, Name: "Library 1", Path: "/music1"},
|
||||
{ID: 1, Name: "Library 1 Duplicate", Path: "/music1-dup"},
|
||||
{ID: 2, Name: "Library 2", Path: "/music2"},
|
||||
}
|
||||
Expect(user.HasLibraryAccess(1)).To(BeTrue())
|
||||
Expect(user.HasLibraryAccess(2)).To(BeTrue())
|
||||
Expect(user.HasLibraryAccess(3)).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("FilteredLibraries", func() {
|
||||
It("returns only libraries that match the filter", func() {
|
||||
filtered := user.FilteredLibraries([]int{1, 3})
|
||||
expected := model.Libraries{
|
||||
{ID: 1, Name: "Rock Library", Path: "/music/rock"},
|
||||
{ID: 3, Name: "Classical Library", Path: "/music/classical"},
|
||||
}
|
||||
Expect(filtered).To(Equal(expected))
|
||||
})
|
||||
|
||||
It("returns single library when filter contains one matching ID", func() {
|
||||
filtered := user.FilteredLibraries([]int{2})
|
||||
expected := model.Libraries{
|
||||
{ID: 2, Name: "Jazz Library", Path: "/music/jazz"},
|
||||
}
|
||||
Expect(filtered).To(Equal(expected))
|
||||
})
|
||||
|
||||
It("returns nil slice when filter has no matching IDs", func() {
|
||||
filtered := user.FilteredLibraries([]int{99, 100})
|
||||
Expect(filtered).To(BeNil())
|
||||
})
|
||||
|
||||
It("returns nil slice when filter is empty", func() {
|
||||
filtered := user.FilteredLibraries([]int{})
|
||||
Expect(filtered).To(BeNil())
|
||||
})
|
||||
|
||||
It("returns nil slice when filter is nil", func() {
|
||||
filtered := user.FilteredLibraries(nil)
|
||||
Expect(filtered).To(BeNil())
|
||||
})
|
||||
|
||||
It("returns nil slice when user has no libraries", func() {
|
||||
user.Libraries = nil
|
||||
filtered := user.FilteredLibraries([]int{1, 2, 3})
|
||||
Expect(filtered).To(BeNil())
|
||||
})
|
||||
|
||||
It("returns nil slice when user has empty libraries", func() {
|
||||
user.Libraries = model.Libraries{}
|
||||
filtered := user.FilteredLibraries([]int{1, 2, 3})
|
||||
Expect(filtered).To(BeNil())
|
||||
})
|
||||
|
||||
It("handles partial matches correctly", func() {
|
||||
filtered := user.FilteredLibraries([]int{1, 99, 2, 100})
|
||||
expected := model.Libraries{
|
||||
{ID: 1, Name: "Rock Library", Path: "/music/rock"},
|
||||
{ID: 2, Name: "Jazz Library", Path: "/music/jazz"},
|
||||
}
|
||||
Expect(filtered).To(Equal(expected))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("AccessibleLibraryIDs", func() {
|
||||
It("returns all library IDs when user has libraries", func() {
|
||||
ids := user.AccessibleLibraryIDs()
|
||||
expected := []int{1, 2, 3}
|
||||
Expect(ids).To(Equal(expected))
|
||||
})
|
||||
|
||||
It("returns nil when user has no libraries", func() {
|
||||
user.Libraries = nil
|
||||
ids := user.AccessibleLibraryIDs()
|
||||
Expect(ids).To(BeNil())
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue