mirror of
https://github.com/immich-app/immich.git
synced 2025-02-09 18:57:46 +02:00
refactor: migrate album repo to kysely (#15474)
This commit is contained in:
parent
58d5cc1e4b
commit
c35fd6cbdb
@ -142,6 +142,10 @@ describe('/albums', () => {
|
||||
...user1Albums[0],
|
||||
assets: [expect.objectContaining({ isFavorite: false })],
|
||||
lastModifiedAssetTimestamp: expect.any(String),
|
||||
startDate: expect.any(String),
|
||||
endDate: expect.any(String),
|
||||
shared: true,
|
||||
albumUsers: expect.any(Array),
|
||||
});
|
||||
});
|
||||
|
||||
@ -299,6 +303,10 @@ describe('/albums', () => {
|
||||
...user1Albums[0],
|
||||
assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
|
||||
lastModifiedAssetTimestamp: expect.any(String),
|
||||
startDate: expect.any(String),
|
||||
endDate: expect.any(String),
|
||||
albumUsers: expect.any(Array),
|
||||
shared: true,
|
||||
});
|
||||
});
|
||||
|
||||
@ -330,6 +338,10 @@ describe('/albums', () => {
|
||||
...user1Albums[0],
|
||||
assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })],
|
||||
lastModifiedAssetTimestamp: expect.any(String),
|
||||
startDate: expect.any(String),
|
||||
endDate: expect.any(String),
|
||||
albumUsers: expect.any(Array),
|
||||
shared: true,
|
||||
});
|
||||
});
|
||||
|
||||
@ -344,6 +356,10 @@ describe('/albums', () => {
|
||||
assets: [],
|
||||
assetCount: 1,
|
||||
lastModifiedAssetTimestamp: expect.any(String),
|
||||
endDate: expect.any(String),
|
||||
startDate: expect.any(String),
|
||||
albumUsers: expect.any(Array),
|
||||
shared: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ export class AddUsersDto {
|
||||
albumUsers!: AlbumUserAddDto[];
|
||||
}
|
||||
|
||||
class AlbumUserCreateDto {
|
||||
export class AlbumUserCreateDto {
|
||||
@ValidateUUID()
|
||||
userId!: string;
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
import { Insertable, Updateable } from 'kysely';
|
||||
import { Albums } from 'src/db';
|
||||
import { AlbumUserCreateDto } from 'src/dtos/album.dto';
|
||||
import { AlbumEntity } from 'src/entities/album.entity';
|
||||
import { IBulkAsset } from 'src/utils/asset.util';
|
||||
|
||||
@ -15,7 +18,7 @@ export interface AlbumInfoOptions {
|
||||
}
|
||||
|
||||
export interface IAlbumRepository extends IBulkAsset {
|
||||
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null>;
|
||||
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | undefined>;
|
||||
getByAssetId(ownerId: string, assetId: string): Promise<AlbumEntity[]>;
|
||||
removeAsset(assetId: string): Promise<void>;
|
||||
getMetadataForIds(ids: string[]): Promise<AlbumAssetCount[]>;
|
||||
@ -25,8 +28,8 @@ export interface IAlbumRepository extends IBulkAsset {
|
||||
restoreAll(userId: string): Promise<void>;
|
||||
softDeleteAll(userId: string): Promise<void>;
|
||||
deleteAll(userId: string): Promise<void>;
|
||||
create(album: Partial<AlbumEntity>): Promise<AlbumEntity>;
|
||||
update(album: Partial<AlbumEntity>): Promise<AlbumEntity>;
|
||||
create(album: Insertable<Albums>, assetIds: string[], albumUsers: AlbumUserCreateDto[]): Promise<AlbumEntity>;
|
||||
update(id: string, album: Updateable<Albums>): Promise<AlbumEntity>;
|
||||
delete(id: string): Promise<void>;
|
||||
updateThumbnails(): Promise<number | undefined>;
|
||||
}
|
||||
|
@ -1,460 +1,490 @@
|
||||
-- NOTE: This file is auto generated by ./sql-generator
|
||||
|
||||
-- AlbumRepository.getById
|
||||
SELECT DISTINCT
|
||||
"distinctAlias"."AlbumEntity_id" AS "ids_AlbumEntity_id"
|
||||
FROM
|
||||
select
|
||||
"albums".*,
|
||||
(
|
||||
SELECT
|
||||
"AlbumEntity"."id" AS "AlbumEntity_id",
|
||||
"AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
|
||||
"AlbumEntity"."albumName" AS "AlbumEntity_albumName",
|
||||
"AlbumEntity"."description" AS "AlbumEntity_description",
|
||||
"AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
|
||||
"AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
|
||||
"AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
|
||||
"AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
|
||||
"AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
|
||||
"AlbumEntity"."order" AS "AlbumEntity_order",
|
||||
"AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
|
||||
"AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
|
||||
"AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
|
||||
"AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
|
||||
"AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
|
||||
"AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
|
||||
"AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
|
||||
"AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status",
|
||||
"AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileChangedAt" AS "AlbumEntity__AlbumEntity_owner_profileChangedAt",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" AS "AlbumEntity__AlbumEntity_albumUsers_usersId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."oauthId" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_oauthId",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileImagePath" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileImagePath",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."shouldChangePassword" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_shouldChangePassword",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."createdAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_createdAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileChangedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileChangedAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId"
|
||||
FROM
|
||||
"albums" "AlbumEntity"
|
||||
LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
|
||||
AND (
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
|
||||
)
|
||||
LEFT JOIN "albums_shared_users_users" "AlbumEntity__AlbumEntity_albumUsers" ON "AlbumEntity__AlbumEntity_albumUsers"."albumsId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "users" "a641d58cf46d4a391ba060ac4dc337665c69ffea" ON "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" = "AlbumEntity__AlbumEntity_albumUsers"."usersId"
|
||||
AND (
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" IS NULL
|
||||
)
|
||||
LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
|
||||
WHERE
|
||||
((("AlbumEntity"."id" = $1)))
|
||||
AND ("AlbumEntity"."deletedAt" IS NULL)
|
||||
) "distinctAlias"
|
||||
ORDER BY
|
||||
"AlbumEntity_id" ASC
|
||||
LIMIT
|
||||
1
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "albums"."ownerId"
|
||||
) as obj
|
||||
) as "owner",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"album_users".*,
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "album_users"."usersId"
|
||||
) as obj
|
||||
) as "user"
|
||||
from
|
||||
"albums_shared_users_users" as "album_users"
|
||||
where
|
||||
"album_users"."albumsId" = "albums"."id"
|
||||
) as agg
|
||||
) as "albumUsers",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"shared_links"
|
||||
where
|
||||
"shared_links"."albumId" = "albums"."id"
|
||||
) as agg
|
||||
) as "sharedLinks"
|
||||
from
|
||||
"albums"
|
||||
where
|
||||
"albums"."id" = $1
|
||||
and "albums"."deletedAt" is null
|
||||
|
||||
-- AlbumRepository.getByAssetId
|
||||
SELECT
|
||||
"AlbumEntity"."id" AS "AlbumEntity_id",
|
||||
"AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
|
||||
"AlbumEntity"."albumName" AS "AlbumEntity_albumName",
|
||||
"AlbumEntity"."description" AS "AlbumEntity_description",
|
||||
"AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
|
||||
"AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
|
||||
"AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
|
||||
"AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
|
||||
"AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
|
||||
"AlbumEntity"."order" AS "AlbumEntity_order",
|
||||
"AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
|
||||
"AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
|
||||
"AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
|
||||
"AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
|
||||
"AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
|
||||
"AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
|
||||
"AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
|
||||
"AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status",
|
||||
"AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileChangedAt" AS "AlbumEntity__AlbumEntity_owner_profileChangedAt",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" AS "AlbumEntity__AlbumEntity_albumUsers_usersId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."oauthId" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_oauthId",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileImagePath" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileImagePath",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."shouldChangePassword" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_shouldChangePassword",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."createdAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_createdAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileChangedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileChangedAt"
|
||||
FROM
|
||||
"albums" "AlbumEntity"
|
||||
LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
|
||||
AND (
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
|
||||
)
|
||||
LEFT JOIN "albums_shared_users_users" "AlbumEntity__AlbumEntity_albumUsers" ON "AlbumEntity__AlbumEntity_albumUsers"."albumsId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "users" "a641d58cf46d4a391ba060ac4dc337665c69ffea" ON "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" = "AlbumEntity__AlbumEntity_albumUsers"."usersId"
|
||||
AND (
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" IS NULL
|
||||
)
|
||||
LEFT JOIN "albums_assets_assets" "AlbumEntity_AlbumEntity__AlbumEntity_assets" ON "AlbumEntity_AlbumEntity__AlbumEntity_assets"."albumsId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "assets" "AlbumEntity__AlbumEntity_assets" ON "AlbumEntity__AlbumEntity_assets"."id" = "AlbumEntity_AlbumEntity__AlbumEntity_assets"."assetsId"
|
||||
AND (
|
||||
"AlbumEntity__AlbumEntity_assets"."deletedAt" IS NULL
|
||||
)
|
||||
WHERE
|
||||
select
|
||||
"albums".*,
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "albums"."ownerId"
|
||||
) as obj
|
||||
) as "owner",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"album_users".*,
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "album_users"."usersId"
|
||||
) as obj
|
||||
) as "user"
|
||||
from
|
||||
"albums_shared_users_users" as "album_users"
|
||||
where
|
||||
"album_users"."albumsId" = "albums"."id"
|
||||
) as agg
|
||||
) as "albumUsers"
|
||||
from
|
||||
"albums"
|
||||
left join "albums_assets_assets" as "album_assets" on "album_assets"."albumsId" = "albums"."id"
|
||||
left join "albums_shared_users_users" as "album_users" on "album_users"."albumsId" = "albums"."id"
|
||||
where
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
("AlbumEntity"."ownerId" = $1)
|
||||
AND ((("AlbumEntity__AlbumEntity_assets"."id" = $2)))
|
||||
)
|
||||
)
|
||||
OR (
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" = $3
|
||||
)
|
||||
)
|
||||
)
|
||||
AND ((("AlbumEntity__AlbumEntity_assets"."id" = $4)))
|
||||
)
|
||||
)
|
||||
"albums"."ownerId" = $1
|
||||
and "album_assets"."assetsId" = $2
|
||||
)
|
||||
or (
|
||||
"album_users"."usersId" = $3
|
||||
and "album_assets"."assetsId" = $4
|
||||
)
|
||||
)
|
||||
AND ("AlbumEntity"."deletedAt" IS NULL)
|
||||
ORDER BY
|
||||
"AlbumEntity"."createdAt" DESC
|
||||
and "albums"."deletedAt" is null
|
||||
order by
|
||||
"albums"."createdAt" desc,
|
||||
"albums"."createdAt" desc
|
||||
|
||||
-- AlbumRepository.getMetadataForIds
|
||||
SELECT
|
||||
"album"."id" AS "album_id",
|
||||
MIN("assets"."fileCreatedAt") AS "start_date",
|
||||
MAX("assets"."fileCreatedAt") AS "end_date",
|
||||
COUNT("assets"."id") AS "asset_count"
|
||||
FROM
|
||||
"albums" "album"
|
||||
LEFT JOIN "albums_assets_assets" "album_assets" ON "album_assets"."albumsId" = "album"."id"
|
||||
LEFT JOIN "assets" "assets" ON "assets"."id" = "album_assets"."assetsId"
|
||||
AND "assets"."deletedAt" IS NULL
|
||||
WHERE
|
||||
("album"."id" IN ($1))
|
||||
AND ("album"."deletedAt" IS NULL)
|
||||
GROUP BY
|
||||
"album"."id"
|
||||
select
|
||||
"albums"."id",
|
||||
min("assets"."fileCreatedAt") as "startDate",
|
||||
max("assets"."fileCreatedAt") as "endDate",
|
||||
count("assets"."id") as "assetCount"
|
||||
from
|
||||
"albums"
|
||||
left join "albums_assets_assets" as "album_assets" on "album_assets"."albumsId" = "albums"."id"
|
||||
left join "assets" on "assets"."id" = "album_assets"."assetsId"
|
||||
where
|
||||
"albums"."id" in ($1)
|
||||
group by
|
||||
"albums"."id"
|
||||
|
||||
-- AlbumRepository.getOwned
|
||||
SELECT
|
||||
"AlbumEntity"."id" AS "AlbumEntity_id",
|
||||
"AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
|
||||
"AlbumEntity"."albumName" AS "AlbumEntity_albumName",
|
||||
"AlbumEntity"."description" AS "AlbumEntity_description",
|
||||
"AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
|
||||
"AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
|
||||
"AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
|
||||
"AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
|
||||
"AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
|
||||
"AlbumEntity"."order" AS "AlbumEntity_order",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" AS "AlbumEntity__AlbumEntity_albumUsers_usersId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."oauthId" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_oauthId",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileImagePath" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileImagePath",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."shouldChangePassword" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_shouldChangePassword",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."createdAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_createdAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileChangedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileChangedAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId",
|
||||
"AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
|
||||
"AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
|
||||
"AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
|
||||
"AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
|
||||
"AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
|
||||
"AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
|
||||
"AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
|
||||
"AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status",
|
||||
"AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileChangedAt" AS "AlbumEntity__AlbumEntity_owner_profileChangedAt"
|
||||
FROM
|
||||
"albums" "AlbumEntity"
|
||||
LEFT JOIN "albums_shared_users_users" "AlbumEntity__AlbumEntity_albumUsers" ON "AlbumEntity__AlbumEntity_albumUsers"."albumsId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "users" "a641d58cf46d4a391ba060ac4dc337665c69ffea" ON "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" = "AlbumEntity__AlbumEntity_albumUsers"."usersId"
|
||||
AND (
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" IS NULL
|
||||
)
|
||||
LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
|
||||
AND (
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
|
||||
)
|
||||
WHERE
|
||||
((("AlbumEntity"."ownerId" = $1)))
|
||||
AND ("AlbumEntity"."deletedAt" IS NULL)
|
||||
ORDER BY
|
||||
"AlbumEntity"."createdAt" DESC
|
||||
select
|
||||
"albums".*,
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "albums"."ownerId"
|
||||
) as obj
|
||||
) as "owner",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"album_users".*,
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "album_users"."usersId"
|
||||
) as obj
|
||||
) as "user"
|
||||
from
|
||||
"albums_shared_users_users" as "album_users"
|
||||
where
|
||||
"album_users"."albumsId" = "albums"."id"
|
||||
) as agg
|
||||
) as "albumUsers",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"shared_links"
|
||||
where
|
||||
"shared_links"."albumId" = "albums"."id"
|
||||
) as agg
|
||||
) as "sharedLinks"
|
||||
from
|
||||
"albums"
|
||||
where
|
||||
"albums"."ownerId" = $1
|
||||
and "albums"."deletedAt" is null
|
||||
order by
|
||||
"albums"."createdAt" desc
|
||||
|
||||
-- AlbumRepository.getShared
|
||||
SELECT
|
||||
"AlbumEntity"."id" AS "AlbumEntity_id",
|
||||
"AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
|
||||
"AlbumEntity"."albumName" AS "AlbumEntity_albumName",
|
||||
"AlbumEntity"."description" AS "AlbumEntity_description",
|
||||
"AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
|
||||
"AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
|
||||
"AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
|
||||
"AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
|
||||
"AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
|
||||
"AlbumEntity"."order" AS "AlbumEntity_order",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" AS "AlbumEntity__AlbumEntity_albumUsers_usersId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_id",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."name" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_name",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."isAdmin" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_isAdmin",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."email" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_email",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."storageLabel" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_storageLabel",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."oauthId" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_oauthId",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileImagePath" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileImagePath",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."shouldChangePassword" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_shouldChangePassword",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."createdAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_createdAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_deletedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."status" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_status",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."updatedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_updatedAt",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaSizeInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaSizeInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."quotaUsageInBytes" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_quotaUsageInBytes",
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."profileChangedAt" AS "a641d58cf46d4a391ba060ac4dc337665c69ffea_profileChangedAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId",
|
||||
"AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
|
||||
"AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
|
||||
"AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
|
||||
"AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
|
||||
"AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
|
||||
"AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
|
||||
"AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
|
||||
"AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status",
|
||||
"AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileChangedAt" AS "AlbumEntity__AlbumEntity_owner_profileChangedAt"
|
||||
FROM
|
||||
"albums" "AlbumEntity"
|
||||
LEFT JOIN "albums_shared_users_users" "AlbumEntity__AlbumEntity_albumUsers" ON "AlbumEntity__AlbumEntity_albumUsers"."albumsId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "users" "a641d58cf46d4a391ba060ac4dc337665c69ffea" ON "a641d58cf46d4a391ba060ac4dc337665c69ffea"."id" = "AlbumEntity__AlbumEntity_albumUsers"."usersId"
|
||||
AND (
|
||||
"a641d58cf46d4a391ba060ac4dc337665c69ffea"."deletedAt" IS NULL
|
||||
)
|
||||
LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
|
||||
AND (
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
|
||||
)
|
||||
WHERE
|
||||
select distinct
|
||||
on ("albums"."createdAt") "albums".*,
|
||||
(
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
(
|
||||
select
|
||||
"album_users".*,
|
||||
(
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" = $1
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
OR (
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."userId" = $2
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
OR (
|
||||
(
|
||||
("AlbumEntity"."ownerId" = $3)
|
||||
AND (
|
||||
(
|
||||
(
|
||||
NOT (
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" IS NULL
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "album_users"."usersId"
|
||||
) as obj
|
||||
) as "user"
|
||||
from
|
||||
"albums_shared_users_users" as "album_users"
|
||||
where
|
||||
"album_users"."albumsId" = "albums"."id"
|
||||
) as agg
|
||||
) as "albumUsers",
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "albums"."ownerId"
|
||||
) as obj
|
||||
) as "owner",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"shared_links"
|
||||
where
|
||||
"shared_links"."albumId" = "albums"."id"
|
||||
) as agg
|
||||
) as "sharedLinks"
|
||||
from
|
||||
"albums"
|
||||
left join "albums_shared_users_users" as "shared_albums" on "shared_albums"."albumsId" = "albums"."id"
|
||||
left join "shared_links" on "shared_links"."albumId" = "albums"."id"
|
||||
where
|
||||
(
|
||||
"shared_albums"."usersId" = $1
|
||||
or "shared_links"."userId" = $2
|
||||
or (
|
||||
"albums"."ownerId" = $3
|
||||
and "shared_albums"."usersId" is not null
|
||||
)
|
||||
)
|
||||
AND ("AlbumEntity"."deletedAt" IS NULL)
|
||||
ORDER BY
|
||||
"AlbumEntity"."createdAt" DESC
|
||||
and "albums"."deletedAt" is null
|
||||
order by
|
||||
"albums"."createdAt" desc
|
||||
|
||||
-- AlbumRepository.getNotShared
|
||||
SELECT
|
||||
"AlbumEntity"."id" AS "AlbumEntity_id",
|
||||
"AlbumEntity"."ownerId" AS "AlbumEntity_ownerId",
|
||||
"AlbumEntity"."albumName" AS "AlbumEntity_albumName",
|
||||
"AlbumEntity"."description" AS "AlbumEntity_description",
|
||||
"AlbumEntity"."createdAt" AS "AlbumEntity_createdAt",
|
||||
"AlbumEntity"."updatedAt" AS "AlbumEntity_updatedAt",
|
||||
"AlbumEntity"."deletedAt" AS "AlbumEntity_deletedAt",
|
||||
"AlbumEntity"."albumThumbnailAssetId" AS "AlbumEntity_albumThumbnailAssetId",
|
||||
"AlbumEntity"."isActivityEnabled" AS "AlbumEntity_isActivityEnabled",
|
||||
"AlbumEntity"."order" AS "AlbumEntity_order",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."albumsId" AS "AlbumEntity__AlbumEntity_albumUsers_albumsId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" AS "AlbumEntity__AlbumEntity_albumUsers_usersId",
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."role" AS "AlbumEntity__AlbumEntity_albumUsers_role",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."id" AS "AlbumEntity__AlbumEntity_sharedLinks_id",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."description" AS "AlbumEntity__AlbumEntity_sharedLinks_description",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."password" AS "AlbumEntity__AlbumEntity_sharedLinks_password",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."userId" AS "AlbumEntity__AlbumEntity_sharedLinks_userId",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."key" AS "AlbumEntity__AlbumEntity_sharedLinks_key",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."type" AS "AlbumEntity__AlbumEntity_sharedLinks_type",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."createdAt" AS "AlbumEntity__AlbumEntity_sharedLinks_createdAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."expiresAt" AS "AlbumEntity__AlbumEntity_sharedLinks_expiresAt",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowUpload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowUpload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."allowDownload" AS "AlbumEntity__AlbumEntity_sharedLinks_allowDownload",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."showExif" AS "AlbumEntity__AlbumEntity_sharedLinks_showExif",
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."albumId" AS "AlbumEntity__AlbumEntity_sharedLinks_albumId",
|
||||
"AlbumEntity__AlbumEntity_owner"."id" AS "AlbumEntity__AlbumEntity_owner_id",
|
||||
"AlbumEntity__AlbumEntity_owner"."name" AS "AlbumEntity__AlbumEntity_owner_name",
|
||||
"AlbumEntity__AlbumEntity_owner"."isAdmin" AS "AlbumEntity__AlbumEntity_owner_isAdmin",
|
||||
"AlbumEntity__AlbumEntity_owner"."email" AS "AlbumEntity__AlbumEntity_owner_email",
|
||||
"AlbumEntity__AlbumEntity_owner"."storageLabel" AS "AlbumEntity__AlbumEntity_owner_storageLabel",
|
||||
"AlbumEntity__AlbumEntity_owner"."oauthId" AS "AlbumEntity__AlbumEntity_owner_oauthId",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileImagePath" AS "AlbumEntity__AlbumEntity_owner_profileImagePath",
|
||||
"AlbumEntity__AlbumEntity_owner"."shouldChangePassword" AS "AlbumEntity__AlbumEntity_owner_shouldChangePassword",
|
||||
"AlbumEntity__AlbumEntity_owner"."createdAt" AS "AlbumEntity__AlbumEntity_owner_createdAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" AS "AlbumEntity__AlbumEntity_owner_deletedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."status" AS "AlbumEntity__AlbumEntity_owner_status",
|
||||
"AlbumEntity__AlbumEntity_owner"."updatedAt" AS "AlbumEntity__AlbumEntity_owner_updatedAt",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaSizeInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaSizeInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."quotaUsageInBytes" AS "AlbumEntity__AlbumEntity_owner_quotaUsageInBytes",
|
||||
"AlbumEntity__AlbumEntity_owner"."profileChangedAt" AS "AlbumEntity__AlbumEntity_owner_profileChangedAt"
|
||||
FROM
|
||||
"albums" "AlbumEntity"
|
||||
LEFT JOIN "albums_shared_users_users" "AlbumEntity__AlbumEntity_albumUsers" ON "AlbumEntity__AlbumEntity_albumUsers"."albumsId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "shared_links" "AlbumEntity__AlbumEntity_sharedLinks" ON "AlbumEntity__AlbumEntity_sharedLinks"."albumId" = "AlbumEntity"."id"
|
||||
LEFT JOIN "users" "AlbumEntity__AlbumEntity_owner" ON "AlbumEntity__AlbumEntity_owner"."id" = "AlbumEntity"."ownerId"
|
||||
AND (
|
||||
"AlbumEntity__AlbumEntity_owner"."deletedAt" IS NULL
|
||||
)
|
||||
WHERE
|
||||
select distinct
|
||||
on ("albums"."createdAt") "albums".*,
|
||||
(
|
||||
(
|
||||
("AlbumEntity"."ownerId" = $1)
|
||||
AND (
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"album_users".*,
|
||||
(
|
||||
"AlbumEntity__AlbumEntity_albumUsers"."usersId" IS NULL
|
||||
)
|
||||
)
|
||||
)
|
||||
AND (
|
||||
(
|
||||
(
|
||||
"AlbumEntity__AlbumEntity_sharedLinks"."id" IS NULL
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
AND ("AlbumEntity"."deletedAt" IS NULL)
|
||||
ORDER BY
|
||||
"AlbumEntity"."createdAt" DESC
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "album_users"."usersId"
|
||||
) as obj
|
||||
) as "user"
|
||||
from
|
||||
"albums_shared_users_users" as "album_users"
|
||||
where
|
||||
"album_users"."albumsId" = "albums"."id"
|
||||
) as agg
|
||||
) as "albumUsers",
|
||||
(
|
||||
select
|
||||
to_json(obj)
|
||||
from
|
||||
(
|
||||
select
|
||||
"id",
|
||||
"email",
|
||||
"createdAt",
|
||||
"profileImagePath",
|
||||
"isAdmin",
|
||||
"shouldChangePassword",
|
||||
"deletedAt",
|
||||
"oauthId",
|
||||
"updatedAt",
|
||||
"storageLabel",
|
||||
"name",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"status",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"users"
|
||||
where
|
||||
"users"."id" = "albums"."ownerId"
|
||||
) as obj
|
||||
) as "owner",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"shared_links"
|
||||
where
|
||||
"shared_links"."albumId" = "albums"."id"
|
||||
) as agg
|
||||
) as "sharedLinks"
|
||||
from
|
||||
"albums"
|
||||
left join "albums_shared_users_users" as "shared_albums" on "shared_albums"."albumsId" = "albums"."id"
|
||||
left join "shared_links" on "shared_links"."albumId" = "albums"."id"
|
||||
where
|
||||
"albums"."ownerId" = $1
|
||||
and "shared_albums"."usersId" is null
|
||||
and "shared_links"."userId" is null
|
||||
and "albums"."deletedAt" is null
|
||||
order by
|
||||
"albums"."createdAt" desc
|
||||
|
||||
-- AlbumRepository.getAssetIds
|
||||
SELECT
|
||||
"albums_assets"."assetsId" AS "assetId"
|
||||
FROM
|
||||
"albums_assets_assets" "albums_assets"
|
||||
WHERE
|
||||
"albums_assets"."albumsId" = $1
|
||||
AND "albums_assets"."assetsId" IN ($2)
|
||||
select
|
||||
*
|
||||
from
|
||||
"albums_assets_assets"
|
||||
where
|
||||
"albums_assets_assets"."albumsId" = $1
|
||||
and "albums_assets_assets"."assetsId" in ($2)
|
||||
|
@ -1,72 +1,116 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { ExpressionBuilder, Insertable, Kysely, sql, Updateable } from 'kysely';
|
||||
import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { Albums, DB } from 'src/db';
|
||||
import { Chunked, ChunkedArray, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AlbumUserCreateDto } from 'src/dtos/album.dto';
|
||||
import { AlbumEntity } from 'src/entities/album.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
||||
import {
|
||||
DataSource,
|
||||
EntityManager,
|
||||
FindOptionsOrder,
|
||||
FindOptionsRelations,
|
||||
In,
|
||||
IsNull,
|
||||
Not,
|
||||
Repository,
|
||||
} from 'typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
const withoutDeletedUsers = <T extends AlbumEntity | null>(album: T) => {
|
||||
if (album) {
|
||||
album.albumUsers = album.albumUsers.filter((albumUser) => albumUser.user && !albumUser.user.deletedAt);
|
||||
}
|
||||
return album;
|
||||
const userColumns = [
|
||||
'id',
|
||||
'email',
|
||||
'createdAt',
|
||||
'profileImagePath',
|
||||
'isAdmin',
|
||||
'shouldChangePassword',
|
||||
'deletedAt',
|
||||
'oauthId',
|
||||
'updatedAt',
|
||||
'storageLabel',
|
||||
'name',
|
||||
'quotaSizeInBytes',
|
||||
'quotaUsageInBytes',
|
||||
'status',
|
||||
'profileChangedAt',
|
||||
] as const;
|
||||
|
||||
const withOwner = (eb: ExpressionBuilder<DB, 'albums'>) => {
|
||||
return jsonObjectFrom(eb.selectFrom('users').select(userColumns).whereRef('users.id', '=', 'albums.ownerId')).as(
|
||||
'owner',
|
||||
);
|
||||
};
|
||||
|
||||
const withAlbumUsers = (eb: ExpressionBuilder<DB, 'albums'>) => {
|
||||
return jsonArrayFrom(
|
||||
eb
|
||||
.selectFrom('albums_shared_users_users as album_users')
|
||||
.selectAll('album_users')
|
||||
.select((eb) =>
|
||||
jsonObjectFrom(eb.selectFrom('users').select(userColumns).whereRef('users.id', '=', 'album_users.usersId')).as(
|
||||
'user',
|
||||
),
|
||||
)
|
||||
.whereRef('album_users.albumsId', '=', 'albums.id'),
|
||||
).as('albumUsers');
|
||||
};
|
||||
|
||||
const withSharedLink = (eb: ExpressionBuilder<DB, 'albums'>) => {
|
||||
return jsonArrayFrom(eb.selectFrom('shared_links').selectAll().whereRef('shared_links.albumId', '=', 'albums.id')).as(
|
||||
'sharedLinks',
|
||||
);
|
||||
};
|
||||
|
||||
const withAssets = (eb: ExpressionBuilder<DB, 'albums'>) => {
|
||||
return eb
|
||||
.selectFrom((eb) =>
|
||||
eb
|
||||
.selectFrom('assets')
|
||||
.selectAll('assets')
|
||||
.innerJoin('exif', 'assets.id', 'exif.assetId')
|
||||
.select((eb) => eb.fn.toJson('exif').as('exifInfo'))
|
||||
.innerJoin('albums_assets_assets', 'albums_assets_assets.assetsId', 'assets.id')
|
||||
.whereRef('albums_assets_assets.albumsId', '=', 'albums.id')
|
||||
.orderBy('assets.fileCreatedAt', 'desc')
|
||||
.as('asset'),
|
||||
)
|
||||
.select((eb) => eb.fn.jsonAgg('asset').as('assets'))
|
||||
.as('assets');
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class AlbumRepository implements IAlbumRepository {
|
||||
constructor(
|
||||
@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>,
|
||||
@InjectRepository(AlbumEntity) private repository: Repository<AlbumEntity>,
|
||||
@InjectDataSource() private dataSource: DataSource,
|
||||
@InjectKysely() private db: Kysely<DB>,
|
||||
) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, {}] })
|
||||
async getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null> {
|
||||
const relations: FindOptionsRelations<AlbumEntity> = {
|
||||
owner: true,
|
||||
albumUsers: { user: true },
|
||||
assets: false,
|
||||
sharedLinks: true,
|
||||
};
|
||||
|
||||
const order: FindOptionsOrder<AlbumEntity> = {};
|
||||
|
||||
if (options.withAssets) {
|
||||
relations.assets = {
|
||||
exifInfo: true,
|
||||
};
|
||||
|
||||
order.assets = {
|
||||
fileCreatedAt: 'DESC',
|
||||
};
|
||||
}
|
||||
|
||||
const album = await this.repository.findOne({ where: { id }, relations, order });
|
||||
return withoutDeletedUsers(album);
|
||||
async getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | undefined> {
|
||||
return this.db
|
||||
.selectFrom('albums')
|
||||
.selectAll('albums')
|
||||
.where('albums.id', '=', id)
|
||||
.where('albums.deletedAt', 'is', null)
|
||||
.select(withOwner)
|
||||
.select(withAlbumUsers)
|
||||
.select(withSharedLink)
|
||||
.$if(options.withAssets, (eb) => eb.select(withAssets))
|
||||
.executeTakeFirst() as Promise<AlbumEntity | undefined>;
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID] })
|
||||
async getByAssetId(ownerId: string, assetId: string): Promise<AlbumEntity[]> {
|
||||
const albums = await this.repository.find({
|
||||
where: [
|
||||
{ ownerId, assets: { id: assetId } },
|
||||
{ albumUsers: { userId: ownerId }, assets: { id: assetId } },
|
||||
],
|
||||
relations: { owner: true, albumUsers: { user: true } },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
|
||||
return albums.map((album) => withoutDeletedUsers(album));
|
||||
return this.db
|
||||
.selectFrom('albums')
|
||||
.selectAll('albums')
|
||||
.leftJoin('albums_assets_assets as album_assets', 'album_assets.albumsId', 'albums.id')
|
||||
.leftJoin('albums_shared_users_users as album_users', 'album_users.albumsId', 'albums.id')
|
||||
.where((eb) =>
|
||||
eb.or([
|
||||
eb.and([eb('albums.ownerId', '=', ownerId), eb('album_assets.assetsId', '=', assetId)]),
|
||||
eb.and([eb('album_users.usersId', '=', ownerId), eb('album_assets.assetsId', '=', assetId)]),
|
||||
]),
|
||||
)
|
||||
.where('albums.deletedAt', 'is', null)
|
||||
.orderBy('albums.createdAt', 'desc')
|
||||
.select(withOwner)
|
||||
.select(withAlbumUsers)
|
||||
.orderBy('albums.createdAt', 'desc')
|
||||
.execute() as unknown as Promise<AlbumEntity[]>;
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [[DummyValue.UUID]] })
|
||||
@ -77,36 +121,38 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Only possible with query builder because of GROUP BY.
|
||||
const albumMetadatas = await this.repository
|
||||
.createQueryBuilder('album')
|
||||
.select('album.id')
|
||||
.addSelect('MIN(assets.fileCreatedAt)', 'start_date')
|
||||
.addSelect('MAX(assets.fileCreatedAt)', 'end_date')
|
||||
.addSelect('COUNT(assets.id)', 'asset_count')
|
||||
.leftJoin('albums_assets_assets', 'album_assets', 'album_assets.albumsId = album.id')
|
||||
.leftJoin('assets', 'assets', 'assets.id = album_assets.assetsId')
|
||||
.where('album.id IN (:...ids)', { ids })
|
||||
.groupBy('album.id')
|
||||
.getRawMany();
|
||||
const metadatas = await this.db
|
||||
.selectFrom('albums')
|
||||
.leftJoin('albums_assets_assets as album_assets', 'album_assets.albumsId', 'albums.id')
|
||||
.leftJoin('assets', 'assets.id', 'album_assets.assetsId')
|
||||
.select('albums.id')
|
||||
.select((eb) => eb.fn.min('assets.fileCreatedAt').as('startDate'))
|
||||
.select((eb) => eb.fn.max('assets.fileCreatedAt').as('endDate'))
|
||||
.select((eb) => eb.fn.count('assets.id').as('assetCount'))
|
||||
.where('albums.id', 'in', ids)
|
||||
.groupBy('albums.id')
|
||||
.execute();
|
||||
|
||||
return albumMetadatas.map<AlbumAssetCount>((metadatas) => ({
|
||||
albumId: metadatas['album_id'],
|
||||
assetCount: Number(metadatas['asset_count']),
|
||||
startDate: metadatas['end_date'] ? new Date(metadatas['start_date']) : undefined,
|
||||
endDate: metadatas['end_date'] ? new Date(metadatas['end_date']) : undefined,
|
||||
return metadatas.map((metadatas) => ({
|
||||
albumId: metadatas.id,
|
||||
assetCount: Number(metadatas.assetCount),
|
||||
startDate: metadatas.startDate ? new Date(metadatas.startDate) : undefined,
|
||||
endDate: metadatas.endDate ? new Date(metadatas.endDate) : undefined,
|
||||
}));
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
async getOwned(ownerId: string): Promise<AlbumEntity[]> {
|
||||
const albums = await this.repository.find({
|
||||
relations: { albumUsers: { user: true }, sharedLinks: true, owner: true },
|
||||
where: { ownerId },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
|
||||
return albums.map((album) => withoutDeletedUsers(album));
|
||||
return this.db
|
||||
.selectFrom('albums')
|
||||
.selectAll('albums')
|
||||
.select(withOwner)
|
||||
.select(withAlbumUsers)
|
||||
.select(withSharedLink)
|
||||
.where('albums.ownerId', '=', ownerId)
|
||||
.where('albums.deletedAt', 'is', null)
|
||||
.orderBy('albums.createdAt', 'desc')
|
||||
.execute() as unknown as Promise<AlbumEntity[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,17 +160,25 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
*/
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
async getShared(ownerId: string): Promise<AlbumEntity[]> {
|
||||
const albums = await this.repository.find({
|
||||
relations: { albumUsers: { user: true }, sharedLinks: true, owner: true },
|
||||
where: [
|
||||
{ albumUsers: { userId: ownerId } },
|
||||
{ sharedLinks: { userId: ownerId } },
|
||||
{ ownerId, albumUsers: { user: Not(IsNull()) } },
|
||||
],
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
|
||||
return albums.map((album) => withoutDeletedUsers(album));
|
||||
return this.db
|
||||
.selectFrom('albums')
|
||||
.selectAll('albums')
|
||||
.distinctOn('albums.createdAt')
|
||||
.leftJoin('albums_shared_users_users as shared_albums', 'shared_albums.albumsId', 'albums.id')
|
||||
.leftJoin('shared_links', 'shared_links.albumId', 'albums.id')
|
||||
.where((eb) =>
|
||||
eb.or([
|
||||
eb('shared_albums.usersId', '=', ownerId),
|
||||
eb('shared_links.userId', '=', ownerId),
|
||||
eb.and([eb('albums.ownerId', '=', ownerId), eb('shared_albums.usersId', 'is not', null)]),
|
||||
]),
|
||||
)
|
||||
.where('albums.deletedAt', 'is', null)
|
||||
.select(withAlbumUsers)
|
||||
.select(withOwner)
|
||||
.select(withSharedLink)
|
||||
.orderBy('albums.createdAt', 'desc')
|
||||
.execute() as unknown as Promise<AlbumEntity[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,35 +186,37 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
*/
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
async getNotShared(ownerId: string): Promise<AlbumEntity[]> {
|
||||
const albums = await this.repository.find({
|
||||
relations: { albumUsers: true, sharedLinks: true, owner: true },
|
||||
where: { ownerId, albumUsers: { user: IsNull() }, sharedLinks: { id: IsNull() } },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
|
||||
return albums.map((album) => withoutDeletedUsers(album));
|
||||
return this.db
|
||||
.selectFrom('albums')
|
||||
.selectAll('albums')
|
||||
.distinctOn('albums.createdAt')
|
||||
.leftJoin('albums_shared_users_users as shared_albums', 'shared_albums.albumsId', 'albums.id')
|
||||
.leftJoin('shared_links', 'shared_links.albumId', 'albums.id')
|
||||
.where('albums.ownerId', '=', ownerId)
|
||||
.where('shared_albums.usersId', 'is', null)
|
||||
.where('shared_links.userId', 'is', null)
|
||||
.where('albums.deletedAt', 'is', null)
|
||||
.select(withAlbumUsers)
|
||||
.select(withOwner)
|
||||
.select(withSharedLink)
|
||||
.orderBy('albums.createdAt', 'desc')
|
||||
.execute() as unknown as Promise<AlbumEntity[]>;
|
||||
}
|
||||
|
||||
async restoreAll(userId: string): Promise<void> {
|
||||
await this.repository.restore({ ownerId: userId });
|
||||
await this.db.updateTable('albums').set({ deletedAt: null }).where('ownerId', '=', userId).execute();
|
||||
}
|
||||
|
||||
async softDeleteAll(userId: string): Promise<void> {
|
||||
await this.repository.softDelete({ ownerId: userId });
|
||||
await this.db.updateTable('albums').set({ deletedAt: new Date() }).where('ownerId', '=', userId).execute();
|
||||
}
|
||||
|
||||
async deleteAll(userId: string): Promise<void> {
|
||||
await this.repository.delete({ ownerId: userId });
|
||||
await this.db.deleteFrom('albums').where('ownerId', '=', userId).execute();
|
||||
}
|
||||
|
||||
async removeAsset(assetId: string): Promise<void> {
|
||||
// Using dataSource, because there is no direct access to albums_assets_assets.
|
||||
await this.dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from('albums_assets_assets')
|
||||
.where('"albums_assets_assets"."assetsId" = :assetId', { assetId })
|
||||
.execute();
|
||||
await this.db.deleteFrom('albums_assets_assets').where('albums_assets_assets.assetsId', '=', assetId).execute();
|
||||
}
|
||||
|
||||
@Chunked({ paramIndex: 1 })
|
||||
@ -169,14 +225,10 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from('albums_assets_assets')
|
||||
.where({
|
||||
albumsId: albumId,
|
||||
assetsId: In(assetIds),
|
||||
})
|
||||
await this.db
|
||||
.deleteFrom('albums_assets_assets')
|
||||
.where('albums_assets_assets.albumsId', '=', albumId)
|
||||
.where('albums_assets_assets.assetsId', 'in', assetIds)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@ -194,73 +246,80 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
return new Set();
|
||||
}
|
||||
|
||||
const results = await this.dataSource
|
||||
.createQueryBuilder()
|
||||
.select('albums_assets.assetsId', 'assetId')
|
||||
.from('albums_assets_assets', 'albums_assets')
|
||||
.where('"albums_assets"."albumsId" = :albumId', { albumId })
|
||||
.andWhere('"albums_assets"."assetsId" IN (:...assetIds)', { assetIds })
|
||||
.getRawMany<{ assetId: string }>();
|
||||
|
||||
return new Set(results.map(({ assetId }) => assetId));
|
||||
return this.db
|
||||
.selectFrom('albums_assets_assets')
|
||||
.selectAll()
|
||||
.where('albums_assets_assets.albumsId', '=', albumId)
|
||||
.where('albums_assets_assets.assetsId', 'in', assetIds)
|
||||
.execute()
|
||||
.then((results) => new Set(results.map(({ assetsId }) => assetsId)));
|
||||
}
|
||||
|
||||
async addAssetIds(albumId: string, assetIds: string[]): Promise<void> {
|
||||
await this.addAssets(this.dataSource.manager, albumId, assetIds);
|
||||
await this.addAssets(this.db, albumId, assetIds);
|
||||
}
|
||||
|
||||
create(album: Partial<AlbumEntity>): Promise<AlbumEntity> {
|
||||
return this.dataSource.transaction<AlbumEntity>(async (manager) => {
|
||||
const { id } = await manager.save(AlbumEntity, { ...album, assets: [] });
|
||||
const assetIds = (album.assets || []).map((asset) => asset.id);
|
||||
await this.addAssets(manager, id, assetIds);
|
||||
return manager.findOneOrFail(AlbumEntity, {
|
||||
where: { id },
|
||||
relations: {
|
||||
owner: true,
|
||||
albumUsers: { user: true },
|
||||
sharedLinks: true,
|
||||
assets: true,
|
||||
},
|
||||
});
|
||||
create(album: Insertable<Albums>, assetIds: string[], albumUsers: AlbumUserCreateDto[]): Promise<AlbumEntity> {
|
||||
return this.db.transaction().execute(async (tx) => {
|
||||
const newAlbum = await tx.insertInto('albums').values(album).returning('albums.id').executeTakeFirst();
|
||||
|
||||
if (!newAlbum) {
|
||||
throw new Error('Failed to create album');
|
||||
}
|
||||
|
||||
if (assetIds.length > 0) {
|
||||
await this.addAssets(tx, newAlbum.id, assetIds);
|
||||
}
|
||||
|
||||
if (albumUsers.length > 0) {
|
||||
await tx
|
||||
.insertInto('albums_shared_users_users')
|
||||
.values(
|
||||
albumUsers.map((albumUser) => ({ albumsId: newAlbum.id, usersId: albumUser.userId, role: albumUser.role })),
|
||||
)
|
||||
.execute();
|
||||
}
|
||||
|
||||
return tx
|
||||
.selectFrom('albums')
|
||||
.selectAll()
|
||||
.where('id', '=', newAlbum.id)
|
||||
.select(withOwner)
|
||||
.select(withSharedLink)
|
||||
.select(withAssets)
|
||||
.select(withAlbumUsers)
|
||||
.executeTakeFirst() as unknown as Promise<AlbumEntity>;
|
||||
});
|
||||
}
|
||||
|
||||
update(album: Partial<AlbumEntity>): Promise<AlbumEntity> {
|
||||
return this.save(album);
|
||||
update(id: string, album: Updateable<Albums>): Promise<AlbumEntity> {
|
||||
return this.db
|
||||
.updateTable('albums')
|
||||
.set({ ...album, updatedAt: new Date() })
|
||||
.where('id', '=', id)
|
||||
.returningAll('albums')
|
||||
.returning(withOwner)
|
||||
.returning(withSharedLink)
|
||||
.returning(withAlbumUsers)
|
||||
.executeTakeFirst() as unknown as Promise<AlbumEntity>;
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
await this.repository.delete({ id });
|
||||
await this.db.deleteFrom('albums').where('id', '=', id).execute();
|
||||
}
|
||||
|
||||
@Chunked({ paramIndex: 2, chunkSize: 30_000 })
|
||||
private async addAssets(manager: EntityManager, albumId: string, assetIds: string[]): Promise<void> {
|
||||
private async addAssets(db: Kysely<DB>, albumId: string, assetIds: string[]): Promise<void> {
|
||||
if (assetIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into('albums_assets_assets', ['albumsId', 'assetsId'])
|
||||
await db
|
||||
.insertInto('albums_assets_assets')
|
||||
.values(assetIds.map((assetId) => ({ albumsId: albumId, assetsId: assetId })))
|
||||
.execute();
|
||||
}
|
||||
|
||||
private async save(album: Partial<AlbumEntity>) {
|
||||
const { id } = await this.repository.save(album);
|
||||
return this.repository.findOneOrFail({
|
||||
where: { id },
|
||||
relations: {
|
||||
owner: true,
|
||||
albumUsers: { user: true },
|
||||
sharedLinks: true,
|
||||
assets: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure all thumbnails for albums are updated by:
|
||||
* - Removing thumbnails from albums without assets
|
||||
@ -272,28 +331,44 @@ export class AlbumRepository implements IAlbumRepository {
|
||||
async updateThumbnails(): Promise<number | undefined> {
|
||||
// Subquery for getting a new thumbnail.
|
||||
|
||||
const builder = this.dataSource
|
||||
.createQueryBuilder('albums_assets_assets', 'album_assets')
|
||||
.innerJoin('assets', 'assets', '"album_assets"."assetsId" = "assets"."id"')
|
||||
.where('"album_assets"."albumsId" = "albums"."id"');
|
||||
const result = await this.db
|
||||
.updateTable('albums')
|
||||
.set((eb) => ({
|
||||
albumThumbnailAssetId: this.updateThumbnailBuilder(eb)
|
||||
.select('album_assets.assetsId')
|
||||
.orderBy('assets.fileCreatedAt', 'desc')
|
||||
.limit(1),
|
||||
updatedAt: new Date(),
|
||||
}))
|
||||
.where((eb) =>
|
||||
eb.or([
|
||||
eb.and([
|
||||
eb('albumThumbnailAssetId', 'is', null),
|
||||
eb.exists(this.updateThumbnailBuilder(eb).select(sql`1`.as('1'))), // Has assets
|
||||
]),
|
||||
eb.and([
|
||||
eb('albumThumbnailAssetId', 'is not', null),
|
||||
eb.not(
|
||||
eb.exists(
|
||||
this.updateThumbnailBuilder(eb)
|
||||
.select(sql`1`.as('1'))
|
||||
.whereRef('albums.albumThumbnailAssetId', '=', 'album_assets.assetsId'), // Has invalid assets
|
||||
),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
)
|
||||
.execute();
|
||||
|
||||
const newThumbnail = builder
|
||||
.clone()
|
||||
.select('"album_assets"."assetsId"')
|
||||
.orderBy('"assets"."fileCreatedAt"', 'DESC')
|
||||
.limit(1);
|
||||
const hasAssets = builder.clone().select('1');
|
||||
const hasInvalidAsset = hasAssets.clone().andWhere('"albums"."albumThumbnailAssetId" = "album_assets"."assetsId"');
|
||||
return Number(result[0].numUpdatedRows);
|
||||
}
|
||||
|
||||
const updateAlbums = this.repository
|
||||
.createQueryBuilder('albums')
|
||||
.update(AlbumEntity)
|
||||
.set({ albumThumbnailAssetId: () => `(${newThumbnail.getQuery()})` })
|
||||
.where(`"albums"."albumThumbnailAssetId" IS NULL AND EXISTS (${hasAssets.getQuery()})`)
|
||||
.orWhere(`"albums"."albumThumbnailAssetId" IS NOT NULL AND NOT EXISTS (${hasInvalidAsset.getQuery()})`);
|
||||
|
||||
const result = await updateAlbums.execute();
|
||||
|
||||
return result.affected;
|
||||
private updateThumbnailBuilder(eb: ExpressionBuilder<DB, 'albums'>) {
|
||||
return eb
|
||||
.selectFrom('albums_assets_assets as album_assets')
|
||||
.innerJoin('assets', (join) =>
|
||||
join.onRef('album_assets.assetsId', '=', 'assets.id').on('assets.deletedAt', 'is', null),
|
||||
)
|
||||
.whereRef('album_assets.albumsId', '=', 'albums.id');
|
||||
}
|
||||
}
|
||||
|
@ -135,14 +135,17 @@ describe(AlbumService.name, () => {
|
||||
assetIds: ['123'],
|
||||
});
|
||||
|
||||
expect(albumMock.create).toHaveBeenCalledWith({
|
||||
ownerId: authStub.admin.user.id,
|
||||
albumName: albumStub.empty.albumName,
|
||||
description: albumStub.empty.description,
|
||||
albumUsers: [{ userId: 'user-id', role: AlbumUserRole.EDITOR }],
|
||||
assets: [{ id: '123' }],
|
||||
albumThumbnailAssetId: '123',
|
||||
});
|
||||
expect(albumMock.create).toHaveBeenCalledWith(
|
||||
{
|
||||
ownerId: authStub.admin.user.id,
|
||||
albumName: albumStub.empty.albumName,
|
||||
description: albumStub.empty.description,
|
||||
|
||||
albumThumbnailAssetId: '123',
|
||||
},
|
||||
['123'],
|
||||
[{ userId: 'user-id', role: AlbumUserRole.EDITOR }],
|
||||
);
|
||||
|
||||
expect(userMock.get).toHaveBeenCalledWith('user-id', {});
|
||||
expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['123']));
|
||||
@ -175,14 +178,17 @@ describe(AlbumService.name, () => {
|
||||
assetIds: ['asset-1', 'asset-2'],
|
||||
});
|
||||
|
||||
expect(albumMock.create).toHaveBeenCalledWith({
|
||||
ownerId: authStub.admin.user.id,
|
||||
albumName: 'Test album',
|
||||
description: '',
|
||||
albumUsers: [],
|
||||
assets: [{ id: 'asset-1' }],
|
||||
albumThumbnailAssetId: 'asset-1',
|
||||
});
|
||||
expect(albumMock.create).toHaveBeenCalledWith(
|
||||
{
|
||||
ownerId: authStub.admin.user.id,
|
||||
albumName: 'Test album',
|
||||
description: '',
|
||||
|
||||
albumThumbnailAssetId: 'asset-1',
|
||||
},
|
||||
['asset-1'],
|
||||
[],
|
||||
);
|
||||
expect(accessMock.asset.checkOwnerAccess).toHaveBeenCalledWith(
|
||||
authStub.admin.user.id,
|
||||
new Set(['asset-1', 'asset-2']),
|
||||
@ -192,7 +198,7 @@ describe(AlbumService.name, () => {
|
||||
|
||||
describe('update', () => {
|
||||
it('should prevent updating an album that does not exist', async () => {
|
||||
albumMock.getById.mockResolvedValue(null);
|
||||
albumMock.getById.mockResolvedValue(void 0);
|
||||
|
||||
await expect(
|
||||
sut.update(authStub.user1, 'invalid-id', {
|
||||
@ -238,7 +244,7 @@ describe(AlbumService.name, () => {
|
||||
});
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledTimes(1);
|
||||
expect(albumMock.update).toHaveBeenCalledWith({
|
||||
expect(albumMock.update).toHaveBeenCalledWith('album-4', {
|
||||
id: 'album-4',
|
||||
albumName: 'new album name',
|
||||
});
|
||||
@ -344,7 +350,7 @@ describe(AlbumService.name, () => {
|
||||
describe('removeUser', () => {
|
||||
it('should require a valid album id', async () => {
|
||||
accessMock.album.checkOwnerAccess.mockResolvedValue(new Set(['album-1']));
|
||||
albumMock.getById.mockResolvedValue(null);
|
||||
albumMock.getById.mockResolvedValue(void 0);
|
||||
await expect(sut.removeUser(authStub.admin, 'album-1', 'user-1')).rejects.toBeInstanceOf(BadRequestException);
|
||||
expect(albumMock.update).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -529,7 +535,7 @@ describe(AlbumService.name, () => {
|
||||
{ success: true, id: 'asset-3' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({
|
||||
expect(albumMock.update).toHaveBeenCalledWith('album-123', {
|
||||
id: 'album-123',
|
||||
updatedAt: expect.any(Date),
|
||||
albumThumbnailAssetId: 'asset-1',
|
||||
@ -547,7 +553,7 @@ describe(AlbumService.name, () => {
|
||||
{ success: true, id: 'asset-1' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({
|
||||
expect(albumMock.update).toHaveBeenCalledWith('album-123', {
|
||||
id: 'album-123',
|
||||
updatedAt: expect.any(Date),
|
||||
albumThumbnailAssetId: 'asset-id',
|
||||
@ -569,7 +575,7 @@ describe(AlbumService.name, () => {
|
||||
{ success: true, id: 'asset-3' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({
|
||||
expect(albumMock.update).toHaveBeenCalledWith('album-123', {
|
||||
id: 'album-123',
|
||||
updatedAt: expect.any(Date),
|
||||
albumThumbnailAssetId: 'asset-1',
|
||||
@ -606,7 +612,7 @@ describe(AlbumService.name, () => {
|
||||
{ success: true, id: 'asset-3' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({
|
||||
expect(albumMock.update).toHaveBeenCalledWith('album-123', {
|
||||
id: 'album-123',
|
||||
updatedAt: expect.any(Date),
|
||||
albumThumbnailAssetId: 'asset-1',
|
||||
@ -629,7 +635,7 @@ describe(AlbumService.name, () => {
|
||||
{ success: true, id: 'asset-1' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({
|
||||
expect(albumMock.update).toHaveBeenCalledWith('album-123', {
|
||||
id: 'album-123',
|
||||
updatedAt: expect.any(Date),
|
||||
albumThumbnailAssetId: 'asset-1',
|
||||
@ -696,7 +702,6 @@ describe(AlbumService.name, () => {
|
||||
{ success: true, id: 'asset-id' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({ id: 'album-123', updatedAt: expect.any(Date) });
|
||||
expect(albumMock.removeAssetIds).toHaveBeenCalledWith('album-123', ['asset-id']);
|
||||
});
|
||||
|
||||
@ -720,8 +725,6 @@ describe(AlbumService.name, () => {
|
||||
await expect(sut.removeAssets(authStub.admin, 'album-123', { ids: ['asset-id'] })).resolves.toEqual([
|
||||
{ success: true, id: 'asset-id' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({ id: 'album-123', updatedAt: expect.any(Date) });
|
||||
});
|
||||
|
||||
it('should reset the thumbnail if it is removed', async () => {
|
||||
@ -734,10 +737,6 @@ describe(AlbumService.name, () => {
|
||||
{ success: true, id: 'asset-id' },
|
||||
]);
|
||||
|
||||
expect(albumMock.update).toHaveBeenCalledWith({
|
||||
id: 'album-123',
|
||||
updatedAt: expect.any(Date),
|
||||
});
|
||||
expect(albumMock.updateThumbnails).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -15,7 +15,6 @@ import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { AlbumUserEntity } from 'src/entities/album-user.entity';
|
||||
import { AlbumEntity } from 'src/entities/album.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { AlbumAssetCount, AlbumInfoOptions } from 'src/interfaces/album.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
@ -112,16 +111,18 @@ export class AlbumService extends BaseService {
|
||||
permission: Permission.ASSET_SHARE,
|
||||
ids: dto.assetIds || [],
|
||||
});
|
||||
const assets = [...allowedAssetIdsSet].map((id) => ({ id }) as AssetEntity);
|
||||
const assetIds = [...allowedAssetIdsSet].map((id) => id);
|
||||
|
||||
const album = await this.albumRepository.create({
|
||||
ownerId: auth.user.id,
|
||||
albumName: dto.albumName,
|
||||
description: dto.description,
|
||||
albumUsers: albumUsers.map((albumUser) => albumUser as AlbumUserEntity) ?? [],
|
||||
assets,
|
||||
albumThumbnailAssetId: assets[0]?.id || null,
|
||||
});
|
||||
const album = await this.albumRepository.create(
|
||||
{
|
||||
ownerId: auth.user.id,
|
||||
albumName: dto.albumName,
|
||||
description: dto.description,
|
||||
albumThumbnailAssetId: assetIds[0] || null,
|
||||
},
|
||||
assetIds,
|
||||
albumUsers,
|
||||
);
|
||||
|
||||
for (const { userId } of albumUsers) {
|
||||
await this.eventRepository.emit('album.invite', { id: album.id, userId });
|
||||
@ -141,7 +142,7 @@ export class AlbumService extends BaseService {
|
||||
throw new BadRequestException('Invalid album thumbnail');
|
||||
}
|
||||
}
|
||||
const updatedAlbum = await this.albumRepository.update({
|
||||
const updatedAlbum = await this.albumRepository.update(album.id, {
|
||||
id: album.id,
|
||||
albumName: dto.albumName,
|
||||
description: dto.description,
|
||||
@ -170,7 +171,7 @@ export class AlbumService extends BaseService {
|
||||
|
||||
const { id: firstNewAssetId } = results.find(({ success }) => success) || {};
|
||||
if (firstNewAssetId) {
|
||||
await this.albumRepository.update({
|
||||
await this.albumRepository.update(id, {
|
||||
id,
|
||||
updatedAt: new Date(),
|
||||
albumThumbnailAssetId: album.albumThumbnailAssetId ?? firstNewAssetId,
|
||||
@ -199,11 +200,8 @@ export class AlbumService extends BaseService {
|
||||
);
|
||||
|
||||
const removedIds = results.filter(({ success }) => success).map(({ id }) => id);
|
||||
if (removedIds.length > 0) {
|
||||
await this.albumRepository.update({ id, updatedAt: new Date() });
|
||||
if (album.albumThumbnailAssetId && removedIds.includes(album.albumThumbnailAssetId)) {
|
||||
await this.albumRepository.updateThumbnails();
|
||||
}
|
||||
if (removedIds.length > 0 && album.albumThumbnailAssetId && removedIds.includes(album.albumThumbnailAssetId)) {
|
||||
await this.albumRepository.updateThumbnails();
|
||||
}
|
||||
|
||||
return results;
|
||||
|
Loading…
x
Reference in New Issue
Block a user