From ad9b368cb8738450ebf8655122c4ee191a7c058a Mon Sep 17 00:00:00 2001 From: bo0tzz Date: Wed, 21 Oct 2026 18:36:12 +0200 Subject: [PATCH] fix(server): exclude partners' locked assets from legacy search (#32604) (cherry picked from commit 8dab52c7491c79cba742315dea8d7f5212915875) --- server/src/utils/database.ts | 5 ++++ .../specs/services/search.service.spec.ts | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/server/src/utils/database.ts b/server/src/utils/database.ts index 985d7bb40..51aac25b1 100644 --- a/server/src/utils/database.ts +++ b/server/src/utils/database.ts @@ -436,6 +436,11 @@ export function searchAssetBuilderLegacy(kysely: Kysely, options: AssetSearc ? qb.where('asset.visibility', '!=', AssetVisibility.Locked) : qb.where('asset.visibility', '=', options.visibility!), ) + .$if(!!options.viewingUserId, (qb) => + qb.where((eb) => + eb.or([eb('asset.visibility', '!=', AssetVisibility.Locked), eb('asset.ownerId', '=', options.viewingUserId!)]), + ), + ) .$if(!!options.albumIds && options.albumIds.length > 0, (qb) => inAlbums(qb, options.albumIds!)) .$if(!!options.tagIds && options.tagIds.length > 0, (qb) => hasTags(qb, options.tagIds!)) .$if(options.tagIds === null, (qb) => diff --git a/server/test/medium/specs/services/search.service.spec.ts b/server/test/medium/specs/services/search.service.spec.ts index 9617431ce..faab71eed 100644 --- a/server/test/medium/specs/services/search.service.spec.ts +++ b/server/test/medium/specs/services/search.service.spec.ts @@ -123,6 +123,31 @@ describe(SearchService.name, () => { expect(result).toEqual({ total: 0 }); }); + + it('should not return locked assets of partner in elevated session without a visibility filter', async () => { + const { sut, ctx } = setup(); + const { user } = await ctx.newUser(); + const { user: partner } = await ctx.newUser(); + + await ctx.newPartner({ sharedById: partner.id, sharedWithId: user.id }); + + await ctx.newAsset({ ownerId: user.id, visibility: AssetVisibility.Locked }); + await ctx.newAsset({ ownerId: partner.id, visibility: AssetVisibility.Locked }); + await ctx.newAsset({ ownerId: partner.id }); + + const auth = factory.auth({ user: { id: user.id }, session: { hasElevatedPermission: true } }); + + await expect(sut.searchStatistics(auth, {})).resolves.toEqual({ total: 2 }); + + const response = await sut.searchMetadata(auth, { size: 250, withStacked: false }); + expect(response.assets.items.map(({ ownerId, visibility }) => ({ ownerId, visibility }))).toEqual( + expect.arrayContaining([ + { ownerId: user.id, visibility: AssetVisibility.Locked }, + { ownerId: partner.id, visibility: AssetVisibility.Timeline }, + ]), + ); + expect(response.assets.items).toHaveLength(2); + }); }); describe('withStacked option', () => {