diff --git a/api/graphql/models/actions/album_actions.go b/api/graphql/models/actions/album_actions.go index d04bfd04..20f5c687 100644 --- a/api/graphql/models/actions/album_actions.go +++ b/api/graphql/models/actions/album_actions.go @@ -31,7 +31,7 @@ func MyAlbums(db *gorm.DB, user *models.User, order *models.Ordering, paginate * if singleRootAlbumID != -1 && len(user.Albums) > 1 { query = query.Where("parent_album_id = ?", singleRootAlbumID) } else { - query = query.Where("parent_album_id IS NULL") + query = query.Where("parent_album_id IS NULL OR parent_album_id NOT IN (?)", userAlbumIDs) } } diff --git a/api/graphql/models/actions/album_actions_test.go b/api/graphql/models/actions/album_actions_test.go index af91543d..81888495 100644 --- a/api/graphql/models/actions/album_actions_test.go +++ b/api/graphql/models/actions/album_actions_test.go @@ -267,3 +267,116 @@ func TestAlbumsSingleRootExpand(t *testing.T) { }) } + +// Related to #658 +func TestNonRootAlbumPath(t *testing.T) { + db := test_utils.DatabaseTest(t) + + boolTrue := true + boolFalse := false + + rootAlbum := models.Album{ + Title: "root", + Path: "/root", + } + + childAlbum := models.Album{ + Title: "child", + Path: "/root/child", + ParentAlbumID: &rootAlbum.ID, + } + + assert.NoError(t, db.Create(&rootAlbum).Error) + + // Register user + user, err := models.RegisterUser(db, "user", nil, false) + assert.NoError(t, err) + + // Assign album to user + err = db.Model(&user).Association("Albums").Append(&childAlbum) + assert.NoError(t, err) + + // The child album is a "local root album" for the user, as it does not have access to the root album + t.Run("User should only see child album", func(t *testing.T) { + returnedAlbums, err := actions.MyAlbums(db, user, nil, nil, &boolTrue, &boolTrue, &boolFalse) + assert.NoError(t, err) + + assert.Len(t, returnedAlbums, 1) + assert.Equal(t, "child", returnedAlbums[0].Title) + }) +} + +// Related to #658 +func TestNonRootAlbumPathMultipleUsers(t *testing.T) { + db := test_utils.DatabaseTest(t) + + boolTrue := true + boolFalse := false + + rootAlbum := models.Album{ + Title: "root", + Path: "/root", + } + + child1Album := models.Album{ + Title: "child1", + Path: "/root/child1", + ParentAlbumID: &rootAlbum.ID, + } + + child2Album := models.Album{ + Title: "child2", + Path: "/root/child2", + ParentAlbumID: &rootAlbum.ID, + } + + // Admin should have access to all albums + adminAlbums := []*models.Album{&rootAlbum, &child1Album, &child2Album} + + assert.NoError(t, db.Create(&rootAlbum).Error) + + // Register users + admin, err := models.RegisterUser(db, "admin", nil, false) + assert.NoError(t, err) + + user1, err := models.RegisterUser(db, "user1", nil, false) + assert.NoError(t, err) + + user2, err := models.RegisterUser(db, "user2", nil, false) + assert.NoError(t, err) + + // Assign albums to users + err = db.Model(&admin).Association("Albums").Append(&adminAlbums) + assert.NoError(t, err) + + err = db.Model(&user1).Association("Albums").Append(&child1Album) + assert.NoError(t, err) + + err = db.Model(&user2).Association("Albums").Append(&child2Album) + assert.NoError(t, err) + + t.Run("Admin should see all albums", func(t *testing.T) { + returnedAlbums, err := actions.MyAlbums(db, admin, nil, nil, &boolTrue, &boolTrue, &boolFalse) + assert.NoError(t, err) + + assert.Len(t, returnedAlbums, 2) + assert.Equal(t, "child1", returnedAlbums[0].Title) + assert.Equal(t, "child2", returnedAlbums[1].Title) + }) + + t.Run("User 1 should only see child1 album", func(t *testing.T) { + returnedAlbums, err := actions.MyAlbums(db, user1, nil, nil, &boolTrue, &boolTrue, &boolFalse) + assert.NoError(t, err) + + assert.Len(t, returnedAlbums, 1) + assert.Equal(t, "child1", returnedAlbums[0].Title) + }) + + t.Run("User 2 should only see child2 album", func(t *testing.T) { + returnedAlbums, err := actions.MyAlbums(db, user2, nil, nil, &boolTrue, &boolTrue, &boolFalse) + assert.NoError(t, err) + + assert.Len(t, returnedAlbums, 1) + assert.Equal(t, "child2", returnedAlbums[0].Title) + }) +}