mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
chore!: remove without assets (#27835)
* chore!: remove without assets * fix: linting and e2e --------- Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
This commit is contained in:
@@ -3,7 +3,6 @@ import { ApiTags } from '@nestjs/swagger';
|
||||
import { Endpoint, HistoryBuilder } from 'src/decorators';
|
||||
import {
|
||||
AddUsersDto,
|
||||
AlbumInfoDto,
|
||||
AlbumResponseDto,
|
||||
AlbumsAddAssetsDto,
|
||||
AlbumsAddAssetsResponseDto,
|
||||
@@ -66,12 +65,8 @@ export class AlbumController {
|
||||
description: 'Retrieve information about a specific album by its ID.',
|
||||
history: new HistoryBuilder().added('v1').beta('v1').stable('v2'),
|
||||
})
|
||||
getAlbumInfo(
|
||||
@Auth() auth: AuthDto,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
@Query() dto: AlbumInfoDto,
|
||||
): Promise<AlbumResponseDto> {
|
||||
return this.service.get(auth, id, dto);
|
||||
getAlbumInfo(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<AlbumResponseDto> {
|
||||
return this.service.get(auth, id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
|
||||
@@ -10,13 +10,13 @@ describe('mapAlbum', () => {
|
||||
.asset({ localDateTime: endDate }, (builder) => builder.exif())
|
||||
.asset({ localDateTime: startDate }, (builder) => builder.exif())
|
||||
.build();
|
||||
const dto = mapAlbum(getForAlbum(album), false);
|
||||
const dto = mapAlbum(getForAlbum(album));
|
||||
expect(dto.startDate).toEqual(startDate.toISOString());
|
||||
expect(dto.endDate).toEqual(endDate.toISOString());
|
||||
});
|
||||
|
||||
it('should not set start and end dates for empty assets', () => {
|
||||
const dto = mapAlbum(getForAlbum(AlbumFactory.create()), false);
|
||||
const dto = mapAlbum(getForAlbum(AlbumFactory.create()));
|
||||
expect(dto.startDate).toBeUndefined();
|
||||
expect(dto.endDate).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -3,8 +3,7 @@ import _ from 'lodash';
|
||||
import { createZodDto } from 'nestjs-zod';
|
||||
import { AlbumUser, AuthSharedLink, User } from 'src/database';
|
||||
import { BulkIdErrorReasonSchema } from 'src/dtos/asset-ids.response.dto';
|
||||
import { AssetResponseSchema, MapAsset, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { MapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { UserResponseSchema, mapUser } from 'src/dtos/user.dto';
|
||||
import { AlbumUserRole, AlbumUserRoleSchema, AssetOrder, AssetOrderSchema } from 'src/enum';
|
||||
import { MaybeDehydrated } from 'src/types';
|
||||
@@ -12,12 +11,6 @@ import { asDateString } from 'src/utils/date';
|
||||
import { stringToBool } from 'src/validation';
|
||||
import z from 'zod';
|
||||
|
||||
const AlbumInfoSchema = z
|
||||
.object({
|
||||
withoutAssets: stringToBool.optional().describe('Exclude assets from response'),
|
||||
})
|
||||
.meta({ id: 'AlbumInfoDto' });
|
||||
|
||||
const AlbumUserAddSchema = z
|
||||
.object({
|
||||
userId: z.uuidv4().describe('User ID'),
|
||||
@@ -122,7 +115,6 @@ export const AlbumResponseSchema = z
|
||||
shared: z.boolean().describe('Is shared album'),
|
||||
albumUsers: z.array(AlbumUserResponseSchema),
|
||||
hasSharedLink: z.boolean().describe('Has shared link'),
|
||||
assets: z.array(AssetResponseSchema),
|
||||
owner: UserResponseSchema,
|
||||
assetCount: z.int().min(0).describe('Number of assets'),
|
||||
// TODO: use `isoDatetimeToDate` when using `ZodSerializerDto` on the controllers.
|
||||
@@ -141,7 +133,6 @@ export const AlbumResponseSchema = z
|
||||
})
|
||||
.meta({ id: 'AlbumResponseDto' });
|
||||
|
||||
export class AlbumInfoDto extends createZodDto(AlbumInfoSchema) {}
|
||||
export class AddUsersDto extends createZodDto(AddUsersSchema) {}
|
||||
export class AlbumUserCreateDto extends createZodDto(AlbumUserCreateSchema) {}
|
||||
export class CreateAlbumDto extends createZodDto(CreateAlbumSchema) {}
|
||||
@@ -170,11 +161,7 @@ export type MapAlbumDto = {
|
||||
order: AssetOrder;
|
||||
};
|
||||
|
||||
export const mapAlbum = (
|
||||
entity: MaybeDehydrated<MapAlbumDto>,
|
||||
withAssets: boolean,
|
||||
auth?: AuthDto,
|
||||
): AlbumResponseDto => {
|
||||
export const mapAlbum = (entity: MaybeDehydrated<MapAlbumDto>): AlbumResponseDto => {
|
||||
const albumUsers: AlbumUserResponseDto[] = [];
|
||||
|
||||
if (entity.albumUsers) {
|
||||
@@ -215,12 +202,8 @@ export const mapAlbum = (
|
||||
hasSharedLink,
|
||||
startDate: asDateString(startDate),
|
||||
endDate: asDateString(endDate),
|
||||
assets: (withAssets ? assets : []).map((asset) => mapAsset(asset, { auth })),
|
||||
assetCount: entity.assets?.length || 0,
|
||||
isActivityEnabled: entity.isActivityEnabled,
|
||||
order: entity.order,
|
||||
};
|
||||
};
|
||||
|
||||
export const mapAlbumWithAssets = (entity: MaybeDehydrated<MapAlbumDto>) => mapAlbum(entity, true);
|
||||
export const mapAlbumWithoutAssets = (entity: MaybeDehydrated<MapAlbumDto>) => mapAlbum(entity, false);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createZodDto } from 'nestjs-zod';
|
||||
import { SharedLink } from 'src/database';
|
||||
import { HistoryBuilder } from 'src/decorators';
|
||||
import { AlbumResponseSchema, mapAlbumWithoutAssets } from 'src/dtos/album.dto';
|
||||
import { AlbumResponseSchema, mapAlbum } from 'src/dtos/album.dto';
|
||||
import { AssetResponseSchema, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { SharedLinkTypeSchema } from 'src/enum';
|
||||
import { emptyStringToNull, isoDatetimeToDate } from 'src/validation';
|
||||
@@ -96,7 +96,7 @@ export function mapSharedLink(sharedLink: SharedLink, options: { stripAssetMetad
|
||||
createdAt: sharedLink.createdAt,
|
||||
expiresAt: sharedLink.expiresAt,
|
||||
assets: assets.map((asset) => mapAsset(asset, { stripMetadata: options.stripAssetMetadata })),
|
||||
album: sharedLink.album ? mapAlbumWithoutAssets(sharedLink.album) : undefined,
|
||||
album: sharedLink.album ? mapAlbum(sharedLink.album) : undefined,
|
||||
allowUpload: sharedLink.allowUpload,
|
||||
allowDownload: sharedLink.allowDownload,
|
||||
showMetadata: sharedLink.showExif,
|
||||
|
||||
@@ -563,9 +563,9 @@ describe(AlbumService.name, () => {
|
||||
},
|
||||
]);
|
||||
|
||||
await sut.get(AuthFactory.create(album.owner), album.id, {});
|
||||
await sut.get(AuthFactory.create(album.owner), album.id);
|
||||
|
||||
expect(mocks.album.getById).toHaveBeenCalledWith(album.id, { withAssets: true });
|
||||
expect(mocks.album.getById).toHaveBeenCalledWith(album.id, { withAssets: false });
|
||||
expect(mocks.access.album.checkOwnerAccess).toHaveBeenCalledWith(album.owner.id, new Set([album.id]));
|
||||
});
|
||||
|
||||
@@ -584,9 +584,9 @@ describe(AlbumService.name, () => {
|
||||
]);
|
||||
|
||||
const auth = AuthFactory.from().sharedLink().build();
|
||||
await sut.get(auth, album.id, {});
|
||||
await sut.get(auth, album.id);
|
||||
|
||||
expect(mocks.album.getById).toHaveBeenCalledWith(album.id, { withAssets: true });
|
||||
expect(mocks.album.getById).toHaveBeenCalledWith(album.id, { withAssets: false });
|
||||
expect(mocks.access.album.checkSharedLinkAccess).toHaveBeenCalledWith(auth.sharedLink!.id, new Set([album.id]));
|
||||
});
|
||||
|
||||
@@ -605,9 +605,9 @@ describe(AlbumService.name, () => {
|
||||
},
|
||||
]);
|
||||
|
||||
await sut.get(AuthFactory.create(user), album.id, {});
|
||||
await sut.get(AuthFactory.create(user), album.id);
|
||||
|
||||
expect(mocks.album.getById).toHaveBeenCalledWith(album.id, { withAssets: true });
|
||||
expect(mocks.album.getById).toHaveBeenCalledWith(album.id, { withAssets: false });
|
||||
expect(mocks.access.album.checkSharedAlbumAccess).toHaveBeenCalledWith(
|
||||
user.id,
|
||||
new Set([album.id]),
|
||||
@@ -617,7 +617,7 @@ describe(AlbumService.name, () => {
|
||||
|
||||
it('should throw an error for no access', async () => {
|
||||
const auth = AuthFactory.create();
|
||||
await expect(sut.get(auth, 'album-123', {})).rejects.toBeInstanceOf(BadRequestException);
|
||||
await expect(sut.get(auth, 'album-123')).rejects.toBeInstanceOf(BadRequestException);
|
||||
|
||||
expect(mocks.access.album.checkOwnerAccess).toHaveBeenCalledWith(auth.user.id, new Set(['album-123']));
|
||||
expect(mocks.access.album.checkSharedAlbumAccess).toHaveBeenCalledWith(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
AddUsersDto,
|
||||
AlbumInfoDto,
|
||||
AlbumResponseDto,
|
||||
AlbumsAddAssetsDto,
|
||||
AlbumsAddAssetsResponseDto,
|
||||
@@ -10,8 +9,6 @@ import {
|
||||
GetAlbumsDto,
|
||||
mapAlbum,
|
||||
MapAlbumDto,
|
||||
mapAlbumWithAssets,
|
||||
mapAlbumWithoutAssets,
|
||||
UpdateAlbumDto,
|
||||
UpdateAlbumUserDto,
|
||||
} from 'src/dtos/album.dto';
|
||||
@@ -64,7 +61,7 @@ export class AlbumService extends BaseService {
|
||||
}
|
||||
|
||||
return albums.map((album) => ({
|
||||
...mapAlbumWithoutAssets(album),
|
||||
...mapAlbum(album),
|
||||
sharedLinks: undefined,
|
||||
startDate: asDateString(albumMetadata[album.id]?.startDate ?? undefined),
|
||||
endDate: asDateString(albumMetadata[album.id]?.endDate ?? undefined),
|
||||
@@ -74,11 +71,10 @@ export class AlbumService extends BaseService {
|
||||
}));
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string, dto: AlbumInfoDto): Promise<AlbumResponseDto> {
|
||||
async get(auth: AuthDto, id: string): Promise<AlbumResponseDto> {
|
||||
await this.requireAccess({ auth, permission: Permission.AlbumRead, ids: [id] });
|
||||
await this.albumRepository.updateThumbnails();
|
||||
const withAssets = dto.withoutAssets === undefined ? true : !dto.withoutAssets;
|
||||
const album = await this.findOrFail(id, { withAssets });
|
||||
const album = await this.findOrFail(id, { withAssets: false });
|
||||
const [albumMetadataForIds] = await this.albumRepository.getMetadataForIds([album.id]);
|
||||
|
||||
const hasSharedUsers = album.albumUsers && album.albumUsers.length > 0;
|
||||
@@ -86,7 +82,7 @@ export class AlbumService extends BaseService {
|
||||
const isShared = hasSharedUsers || hasSharedLink;
|
||||
|
||||
return {
|
||||
...mapAlbum(album, withAssets, auth),
|
||||
...mapAlbum(album),
|
||||
startDate: asDateString(albumMetadataForIds?.startDate ?? undefined),
|
||||
endDate: asDateString(albumMetadataForIds?.endDate ?? undefined),
|
||||
assetCount: albumMetadataForIds?.assetCount ?? 0,
|
||||
@@ -144,7 +140,7 @@ export class AlbumService extends BaseService {
|
||||
await this.eventRepository.emit('AlbumInvite', { id: album.id, userId });
|
||||
}
|
||||
|
||||
return mapAlbumWithAssets(album);
|
||||
return mapAlbum(album);
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: UpdateAlbumDto): Promise<AlbumResponseDto> {
|
||||
@@ -167,7 +163,7 @@ export class AlbumService extends BaseService {
|
||||
order: dto.order,
|
||||
});
|
||||
|
||||
return mapAlbumWithoutAssets({ ...updatedAlbum, assets: album.assets });
|
||||
return mapAlbum({ ...updatedAlbum, assets: album.assets });
|
||||
}
|
||||
|
||||
async delete(auth: AuthDto, id: string): Promise<void> {
|
||||
@@ -305,7 +301,7 @@ export class AlbumService extends BaseService {
|
||||
await this.eventRepository.emit('AlbumInvite', { id, userId });
|
||||
}
|
||||
|
||||
return this.findOrFail(id, { withAssets: true }).then(mapAlbumWithoutAssets);
|
||||
return this.findOrFail(id, { withAssets: true }).then(mapAlbum);
|
||||
}
|
||||
|
||||
async removeUser(auth: AuthDto, id: string, userId: string | 'me'): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user