diff --git a/server/src/repositories/shared-link.repository.ts b/server/src/repositories/shared-link.repository.ts index 48afcf7d92..bc81e75c81 100644 --- a/server/src/repositories/shared-link.repository.ts +++ b/server/src/repositories/shared-link.repository.ts @@ -4,7 +4,7 @@ import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres'; import _ from 'lodash'; import { InjectKysely } from 'nestjs-kysely'; import { Album, columns } from 'src/database'; -import { DummyValue, GenerateSql } from 'src/decorators'; +import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; import { SharedLinkType } from 'src/enum'; import { DB } from 'src/schema'; import { AssetExifTable } from 'src/schema/tables/asset-exif.table'; @@ -249,6 +249,20 @@ export class SharedLinkRepository { await this.db.deleteFrom('shared_link').where('shared_link.id', '=', id).execute(); } + @ChunkedArray({ paramIndex: 1 }) + async addAssets(id: string, assetIds: string[]) { + if (assetIds.length === 0) { + return []; + } + + return await this.db + .insertInto('shared_link_asset') + .values(assetIds.map((assetId) => ({ assetId, sharedLinkId: id }))) + .onConflict((oc) => oc.doNothing()) + .returning(['shared_link_asset.assetId']) + .execute(); + } + @GenerateSql({ params: [DummyValue.UUID] }) private getSharedLinks(id: string) { return this.db diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index 020bda4df7..3c981ea61e 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -151,6 +151,10 @@ export class AssetMediaService extends BaseService { } const asset = await this.create(auth.user.id, dto, file, sidecarFile); + if (auth.sharedLink) { + await this.sharedLinkRepository.addAssets(auth.sharedLink.id, [asset.id]); + } + await this.userRepository.updateUsage(auth.user.id, file.size); return { id: asset.id, status: AssetMediaStatus.CREATED }; @@ -341,6 +345,11 @@ export class AssetMediaService extends BaseService { this.logger.error(`Error locating duplicate for checksum constraint`); throw new InternalServerErrorException(); } + + if (auth.sharedLink) { + await this.sharedLinkRepository.addAssets(auth.sharedLink.id, [duplicateId]); + } + return { status: AssetMediaStatus.DUPLICATE, id: duplicateId }; } diff --git a/server/src/services/shared-link.service.ts b/server/src/services/shared-link.service.ts index b942c32326..26b15031ee 100644 --- a/server/src/services/shared-link.service.ts +++ b/server/src/services/shared-link.service.ts @@ -150,6 +150,12 @@ export class SharedLinkService extends BaseService { } async addAssets(auth: AuthDto, id: string, dto: AssetIdsDto): Promise { + if (auth.sharedLink) { + this.logger.deprecate( + 'Assets uploaded using shared link authentication are now automatically added to the shared link during upload and in the next major release this endpoint will no longer accept shared link authentication', + ); + } + const sharedLink = await this.findOrFail(auth.user.id, id); if (sharedLink.type !== SharedLinkType.Individual) { diff --git a/web/src/lib/components/share-page/individual-shared-viewer.svelte b/web/src/lib/components/share-page/individual-shared-viewer.svelte index 94e00500fb..64eb98bec0 100644 --- a/web/src/lib/components/share-page/individual-shared-viewer.svelte +++ b/web/src/lib/components/share-page/individual-shared-viewer.svelte @@ -16,7 +16,7 @@ import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader'; import { handleError } from '$lib/utils/handle-error'; import { toTimelineAsset } from '$lib/utils/timeline-util'; - import { addSharedLinkAssets, getAssetInfo, type SharedLinkResponseDto } from '@immich/sdk'; + import { getAssetInfo, type SharedLinkResponseDto } from '@immich/sdk'; import { IconButton, Logo, toastManager } from '@immich/ui'; import { mdiArrowLeft, mdiDownload, mdiFileImagePlusOutline, mdiSelectAll } from '@mdi/js'; import { t } from 'svelte-i18n'; @@ -48,21 +48,11 @@ const handleUploadAssets = async (files: File[] = []) => { try { - let results: (string | undefined)[] = []; - results = await (!files || files.length === 0 || !Array.isArray(files) + await (!files || files.length === 0 || !Array.isArray(files) ? openFileUploadDialog() : fileUploadHandler({ files })); - const data = await addSharedLinkAssets({ - ...authManager.params, - id: sharedLink.id, - assetIdsDto: { - assetIds: results.filter((id) => !!id) as string[], - }, - }); - const added = data.filter((item) => item.success).length; - - toastManager.success($t('assets_added_count', { values: { count: added } })); + toastManager.success(); } catch (error) { handleError(error, $t('errors.unable_to_add_assets_to_shared_link')); }