diff --git a/server/src/immich/api-v1/asset/asset-repository.ts b/server/src/immich/api-v1/asset/asset-repository.ts index 722ca3e38b..dcc686c364 100644 --- a/server/src/immich/api-v1/asset/asset-repository.ts +++ b/server/src/immich/api-v1/asset/asset-repository.ts @@ -19,11 +19,14 @@ export interface AssetOwnerCheck extends AssetCheck { ownerId: string; } +export type AssetCreate = Omit< + AssetEntity, + 'id' | 'createdAt' | 'updatedAt' | 'owner' | 'livePhotoVideoId' | 'library' +>; + export interface IAssetRepository { get(id: string): Promise; - create( - asset: Omit, - ): Promise; + create(asset: AssetCreate): Promise; remove(asset: AssetEntity): Promise; getAllByUserId(userId: string, dto: AssetSearchDto): Promise; getAllByDeviceId(userId: string, deviceId: string): Promise; @@ -151,9 +154,7 @@ export class AssetRepository implements IAssetRepository { }); } - create( - asset: Omit, - ): Promise { + create(asset: AssetCreate): Promise { return this.assetRepository.save(asset); } diff --git a/server/src/immich/api-v1/asset/asset.core.ts b/server/src/immich/api-v1/asset/asset.core.ts index a736ff79ac..f25708d645 100644 --- a/server/src/immich/api-v1/asset/asset.core.ts +++ b/server/src/immich/api-v1/asset/asset.core.ts @@ -1,5 +1,5 @@ import { AuthUserDto, IJobRepository, JobName, mimeTypes, UploadFile } from '@app/domain'; -import { AssetEntity, LibraryEntity, UserEntity } from '@app/infra/entities'; +import { AssetEntity } from '@app/infra/entities'; import { parse } from 'node:path'; import { IAssetRepository } from './asset-repository'; import { CreateAssetDto, ImportAssetDto } from './dto/create-asset.dto'; @@ -12,14 +12,14 @@ export class AssetCore { async create( authUser: AuthUserDto, - dto: CreateAssetDto | ImportAssetDto, + dto: (CreateAssetDto | ImportAssetDto) & { libraryId: string }, file: UploadFile, livePhotoAssetId?: string, sidecarPath?: string, ): Promise { const asset = await this.repository.create({ - owner: { id: authUser.id } as UserEntity, - library: { id: dto.libraryId } as LibraryEntity, + ownerId: authUser.id, + libraryId: dto.libraryId, checksum: file.checksum, originalPath: file.originalPath, diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 91ae3ce73a..a80d7675b4 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -90,22 +90,19 @@ export class AssetService { let livePhotoAsset: AssetEntity | null = null; try { + const libraryId = await this.getLibraryId(authUser, dto.libraryId); if (livePhotoFile) { - const livePhotoDto = { ...dto, assetType: AssetType.VIDEO, isVisible: false }; + const livePhotoDto = { ...dto, assetType: AssetType.VIDEO, isVisible: false, libraryId }; livePhotoAsset = await this.assetCore.create(authUser, livePhotoDto, livePhotoFile); } - if (!dto.libraryId) { - // No library given, fall back to default upload library - const defaultUploadLibrary = await this.libraryRepository.getDefaultUploadLibrary(authUser.id); - - if (!defaultUploadLibrary) { - throw new InternalServerErrorException('Cannot find default upload library for user ' + authUser.id); - } - dto.libraryId = defaultUploadLibrary.id; - } - - const asset = await this.assetCore.create(authUser, dto, file, livePhotoAsset?.id, sidecarFile?.originalPath); + const asset = await this.assetCore.create( + authUser, + { ...dto, libraryId }, + file, + livePhotoAsset?.id, + sidecarFile?.originalPath, + ); return { id: asset.id, duplicate: false }; } catch (error: any) { @@ -164,7 +161,8 @@ export class AssetService { }; try { - const asset = await this.assetCore.create(authUser, dto, assetFile, undefined, dto.sidecarPath); + const libraryId = await this.getLibraryId(authUser, dto.libraryId); + const asset = await this.assetCore.create(authUser, { ...dto, libraryId }, assetFile, undefined, dto.sidecarPath); return { id: asset.id, duplicate: false }; } catch (error: QueryFailedError | Error | any) { // handle duplicates with a success response @@ -505,4 +503,25 @@ export class AssetService { } }); } + + private async getLibraryId(authUser: AuthUserDto, libraryId?: string) { + if (libraryId) { + return libraryId; + } + + let library = await this.libraryRepository.getDefaultUploadLibrary(authUser.id); + if (!library) { + library = await this.libraryRepository.create({ + ownerId: authUser.id, + name: 'Default Library', + assets: [], + type: LibraryType.UPLOAD, + importPaths: [], + exclusionPatterns: [], + isVisible: true, + }); + } + + return library.id; + } }