feat(server): asset search endpoint (#4931)
* feat(server): GET /assets endpoint * chore: open api * chore: use dumb name * feat: search by make, model, lens, city, state, country * chore: open api * chore: pagination validation and tests * chore: pr feedback
This commit is contained in:
@@ -30,6 +30,8 @@ import {
|
||||
AssetIdsDto,
|
||||
AssetJobName,
|
||||
AssetJobsDto,
|
||||
AssetOrder,
|
||||
AssetSearchDto,
|
||||
AssetStatsDto,
|
||||
DownloadArchiveInfo,
|
||||
DownloadInfoDto,
|
||||
@@ -91,6 +93,34 @@ export class AssetService {
|
||||
this.configCore = SystemConfigCore.create(configRepository);
|
||||
}
|
||||
|
||||
search(authUser: AuthUserDto, dto: AssetSearchDto) {
|
||||
let checksum: Buffer | undefined = undefined;
|
||||
|
||||
if (dto.checksum) {
|
||||
const encoding = dto.checksum.length === 28 ? 'base64' : 'hex';
|
||||
checksum = Buffer.from(dto.checksum, encoding);
|
||||
}
|
||||
|
||||
const enumToOrder = { [AssetOrder.ASC]: 'ASC', [AssetOrder.DESC]: 'DESC' } as const;
|
||||
const order = dto.order ? enumToOrder[dto.order] : undefined;
|
||||
|
||||
return this.assetRepository
|
||||
.search({
|
||||
...dto,
|
||||
order,
|
||||
checksum,
|
||||
ownerId: authUser.id,
|
||||
})
|
||||
.then((assets) =>
|
||||
assets.map((asset) =>
|
||||
mapAsset(asset, {
|
||||
stripMetadata: false,
|
||||
withStack: true,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
canUploadFile({ authUser, fieldName, file }: UploadRequest): true {
|
||||
this.access.requireUploadAccess(authUser);
|
||||
|
||||
|
||||
@@ -1,8 +1,161 @@
|
||||
import { AssetType } from '@app/infra/entities';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsBoolean, IsInt, IsPositive, IsString } from 'class-validator';
|
||||
import { Optional, ValidateUUID } from '../../domain.util';
|
||||
import { IsBoolean, IsEnum, IsInt, IsPositive, IsString, Min } from 'class-validator';
|
||||
import { Optional, QueryBoolean, QueryDate, ValidateUUID } from '../../domain.util';
|
||||
import { BulkIdsDto } from '../response-dto';
|
||||
|
||||
export enum AssetOrder {
|
||||
ASC = 'asc',
|
||||
DESC = 'desc',
|
||||
}
|
||||
|
||||
export class AssetSearchDto {
|
||||
@ValidateUUID({ optional: true })
|
||||
id?: string;
|
||||
|
||||
@ValidateUUID({ optional: true })
|
||||
libraryId?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
deviceAssetId?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
deviceId?: string;
|
||||
|
||||
@IsEnum(AssetType)
|
||||
@Optional()
|
||||
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
|
||||
type?: AssetType;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
checksum?: string;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isArchived?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isEncoded?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isExternal?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isFavorite?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isMotion?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isOffline?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isReadOnly?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
isVisible?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
withDeleted?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
withStacked?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
withExif?: boolean;
|
||||
|
||||
@QueryBoolean({ optional: true })
|
||||
withPeople?: boolean;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
createdBefore?: Date;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
createdAfter?: Date;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
updatedBefore?: Date;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
updatedAfter?: Date;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
trashedBefore?: Date;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
trashedAfter?: Date;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
takenBefore?: Date;
|
||||
|
||||
@QueryDate({ optional: true })
|
||||
takenAfter?: Date;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
originalFileName?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
originalPath?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
resizePath?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
webpPath?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
encodedVideoPath?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
city?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
state?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
country?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
make?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
model?: string;
|
||||
|
||||
@IsString()
|
||||
@Optional()
|
||||
lensModel?: string;
|
||||
|
||||
@IsEnum(AssetOrder)
|
||||
@Optional()
|
||||
@ApiProperty({ enumName: 'AssetOrder', enum: AssetOrder })
|
||||
order?: AssetOrder;
|
||||
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Type(() => Number)
|
||||
@Optional()
|
||||
page?: number;
|
||||
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Type(() => Number)
|
||||
@Optional()
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export class AssetBulkUpdateDto extends BulkIdsDto {
|
||||
@Optional()
|
||||
@IsBoolean()
|
||||
|
||||
Reference in New Issue
Block a user