From 4c754f29995236b3256db3a7e21402748fa5ee07 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Tue, 21 Jul 2026 02:07:56 +0200 Subject: [PATCH] fix: timebuckets locked permissions (#30066) --- server/src/services/timeline.service.ts | 3 +++ .../medium/specs/services/timeline.service.spec.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/server/src/services/timeline.service.ts b/server/src/services/timeline.service.ts index b7ecbad9a9..cb6813cf29 100644 --- a/server/src/services/timeline.service.ts +++ b/server/src/services/timeline.service.ts @@ -60,6 +60,9 @@ export class TimelineService extends BaseService { if (dto.visibility === AssetVisibility.Archive) { await this.requireAccess({ auth, permission: Permission.ArchiveRead, ids: [dto.userId] }); } + if (dto.visibility === AssetVisibility.Locked && dto.userId !== auth.user.id) { + throw new BadRequestException("You may not access another user's locked timeline"); + } } if (dto.tagId) { diff --git a/server/test/medium/specs/services/timeline.service.spec.ts b/server/test/medium/specs/services/timeline.service.spec.ts index d7013b84be..d7d3286733 100644 --- a/server/test/medium/specs/services/timeline.service.spec.ts +++ b/server/test/medium/specs/services/timeline.service.spec.ts @@ -87,6 +87,18 @@ describe(TimelineService.name, () => { ); }); + it('should return error if time bucket is requested with locked visibility for partner', 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 }); + + const auth = factory.auth({ user, session: { hasElevatedPermission: true } }); + + const response = sut.getTimeBuckets(auth, { userId: partner.id, visibility: AssetVisibility.Locked }); + await expect(response).rejects.toThrow("You may not access another user's locked timeline"); + }); + it('should not allow access for unrelated shared links', async () => { const { sut } = setup(); const auth = factory.auth({ sharedLink: {} });