Compare commits

...

2 Commits

Author SHA1 Message Date
bwees
3229a7550d chore: test 2026-01-26 12:53:43 -06:00
bwees
6ec3c8af73 fix: always serve edited version if using shared link. 2026-01-26 12:41:31 -06:00
2 changed files with 59 additions and 0 deletions

View File

@@ -572,6 +572,35 @@ describe(AssetMediaService.name, () => {
);
});
it('should download edited file when using a shared link and edited=false', async () => {
const editedAsset = {
...assetStub.withCropEdit,
files: [
...assetStub.withCropEdit.files,
{
id: 'edited-file',
type: AssetFileType.FullSize,
path: '/uploads/user-id/fullsize/edited.jpg',
isEdited: true,
},
],
};
mocks.access.asset.checkSharedLinkAccess.mockResolvedValue(new Set([assetStub.image.id]));
mocks.asset.getForOriginal.mockResolvedValue({
...editedAsset,
editedPath: '/uploads/user-id/fullsize/edited.jpg',
});
await expect(sut.downloadOriginal(authStub.adminSharedLink, 'asset-id', { edited: false })).resolves.toEqual(
new ImmichFileResponse({
path: '/uploads/user-id/fullsize/edited.jpg',
fileName: 'asset-id.jpg',
contentType: 'image/jpeg',
cacheControl: CacheControl.PrivateWithCache,
}),
);
});
it('should download original file when edited=false', async () => {
const editedAsset = {
...assetStub.withCropEdit,
@@ -711,6 +740,28 @@ describe(AssetMediaService.name, () => {
);
expect(mocks.asset.getForThumbnail).toHaveBeenCalledWith(assetStub.image.id, AssetFileType.Thumbnail, false);
});
it('should get edited thumbnail when using shared link and edited=false', async () => {
mocks.access.asset.checkSharedLinkAccess.mockResolvedValue(new Set([assetStub.image.id]));
mocks.asset.getForThumbnail.mockResolvedValue({
...assetStub.image,
path: '/uploads/user-id/thumbs/edited-thumbnail.jpg',
});
await expect(
sut.viewThumbnail(authStub.adminSharedLink, assetStub.image.id, {
size: AssetMediaSize.THUMBNAIL,
edited: true,
}),
).resolves.toEqual(
new ImmichFileResponse({
path: '/uploads/user-id/thumbs/edited-thumbnail.jpg',
cacheControl: CacheControl.PrivateWithCache,
contentType: 'image/jpeg',
fileName: 'asset-id_thumbnail.jpg',
}),
);
expect(mocks.asset.getForThumbnail).toHaveBeenCalledWith(assetStub.image.id, AssetFileType.Thumbnail, true);
});
});
describe('playbackVideo', () => {

View File

@@ -196,6 +196,10 @@ export class AssetMediaService extends BaseService {
async downloadOriginal(auth: AuthDto, id: string, dto: AssetDownloadOriginalDto): Promise<ImmichFileResponse> {
await this.requireAccess({ auth, permission: Permission.AssetDownload, ids: [id] });
if (auth.sharedLink) {
dto.edited = true;
}
const { originalPath, originalFileName, editedPath } = await this.assetRepository.getForOriginal(
id,
dto.edited ?? false,
@@ -222,6 +226,10 @@ export class AssetMediaService extends BaseService {
throw new BadRequestException('May not request original file');
}
if (auth.sharedLink) {
dto.edited = true;
}
const size = (dto.size ?? AssetMediaSize.THUMBNAIL) as unknown as AssetFileType;
const { originalPath, originalFileName, path } = await this.assetRepository.getForThumbnail(
id,