feat: less asset-metadata validation (#24342)

This commit is contained in:
Jason Rasmussen
2025-12-02 10:56:31 -05:00
committed by GitHub
parent 7594136050
commit 116012f6f8
5 changed files with 6 additions and 43 deletions

View File

@@ -85,19 +85,6 @@ describe(AssetMediaController.name, () => {
expect(body).toEqual(factory.responses.badRequest(['metadata must be valid JSON'])); expect(body).toEqual(factory.responses.badRequest(['metadata must be valid JSON']));
}); });
it('should validate iCloudId is a string', async () => {
const { status, body } = await request(ctx.getHttpServer())
.post('/assets')
.attach('assetData', assetData, filename)
.field({
...makeUploadDto(),
metadata: JSON.stringify([{ key: AssetMetadataKey.MobileApp, value: { iCloudId: 123 } }]),
});
expect(status).toBe(400);
expect(body).toEqual(factory.responses.badRequest(['metadata.0.value.iCloudId must be a string']));
});
it('should require `deviceAssetId`', async () => { it('should require `deviceAssetId`', async () => {
const { status, body } = await request(ctx.getHttpServer()) const { status, body } = await request(ctx.getHttpServer())
.post('/assets') .post('/assets')

View File

@@ -19,7 +19,6 @@ import {
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AssetMetadataKey, AssetType, AssetVisibility } from 'src/enum'; import { AssetMetadataKey, AssetType, AssetVisibility } from 'src/enum';
import { AssetStats } from 'src/repositories/asset.repository'; import { AssetStats } from 'src/repositories/asset.repository';
import { AssetMetadata, AssetMetadataItem } from 'src/types';
import { IsNotSiblingOf, Optional, ValidateBoolean, ValidateEnum, ValidateUUID } from 'src/validation'; import { IsNotSiblingOf, Optional, ValidateBoolean, ValidateEnum, ValidateUUID } from 'src/validation';
export class DeviceIdDto { export class DeviceIdDto {
@@ -154,23 +153,12 @@ export class AssetMetadataUpsertDto {
items!: AssetMetadataUpsertItemDto[]; items!: AssetMetadataUpsertItemDto[];
} }
export class AssetMetadataUpsertItemDto implements AssetMetadataItem { export class AssetMetadataUpsertItemDto {
@ValidateEnum({ enum: AssetMetadataKey, name: 'AssetMetadataKey' }) @ValidateEnum({ enum: AssetMetadataKey, name: 'AssetMetadataKey' })
key!: AssetMetadataKey; key!: AssetMetadataKey;
@IsObject() @IsObject()
@ValidateNested() value!: object;
@Type((options) => {
switch (options?.object.key) {
case AssetMetadataKey.MobileApp: {
return AssetMetadataMobileAppDto;
}
default: {
return Object;
}
}
})
value!: AssetMetadata[AssetMetadataKey];
} }
export class AssetMetadataMobileAppDto { export class AssetMetadataMobileAppDto {

View File

@@ -11,7 +11,6 @@ import { AssetExifTable } from 'src/schema/tables/asset-exif.table';
import { AssetFileTable } from 'src/schema/tables/asset-file.table'; import { AssetFileTable } from 'src/schema/tables/asset-file.table';
import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table'; import { AssetJobStatusTable } from 'src/schema/tables/asset-job-status.table';
import { AssetTable } from 'src/schema/tables/asset.table'; import { AssetTable } from 'src/schema/tables/asset.table';
import { AssetMetadataItem } from 'src/types';
import { import {
anyUuid, anyUuid,
asUuid, asUuid,
@@ -224,7 +223,7 @@ export class AssetRepository {
.execute(); .execute();
} }
upsertMetadata(id: string, items: AssetMetadataItem[]) { upsertMetadata(id: string, items: Array<{ key: AssetMetadataKey; value: object }>) {
return this.db return this.db
.insertInto('asset_metadata') .insertInto('asset_metadata')
.values(items.map((item) => ({ assetId: id, ...item }))) .values(items.map((item) => ({ assetId: id, ...item })))

View File

@@ -12,7 +12,6 @@ import {
Timestamp, Timestamp,
UpdateDateColumn, UpdateDateColumn,
} from 'src/sql-tools'; } from 'src/sql-tools';
import { AssetMetadata, AssetMetadataItem } from 'src/types';
@UpdatedAtTrigger('asset_metadata_updated_at') @UpdatedAtTrigger('asset_metadata_updated_at')
@Table('asset_metadata') @Table('asset_metadata')
@@ -22,7 +21,7 @@ import { AssetMetadata, AssetMetadataItem } from 'src/types';
referencingOldTableAs: 'old', referencingOldTableAs: 'old',
when: 'pg_trigger_depth() = 0', when: 'pg_trigger_depth() = 0',
}) })
export class AssetMetadataTable<T extends keyof AssetMetadata = AssetMetadataKey> implements AssetMetadataItem<T> { export class AssetMetadataTable {
@ForeignKeyColumn(() => AssetTable, { @ForeignKeyColumn(() => AssetTable, {
onUpdate: 'CASCADE', onUpdate: 'CASCADE',
onDelete: 'CASCADE', onDelete: 'CASCADE',
@@ -33,10 +32,10 @@ export class AssetMetadataTable<T extends keyof AssetMetadata = AssetMetadataKey
assetId!: string; assetId!: string;
@PrimaryColumn({ type: 'character varying' }) @PrimaryColumn({ type: 'character varying' })
key!: T; key!: AssetMetadataKey;
@Column({ type: 'jsonb' }) @Column({ type: 'jsonb' })
value!: AssetMetadata[T]; value!: object;
@UpdateIdColumn({ index: true }) @UpdateIdColumn({ index: true })
updateId!: Generated<string>; updateId!: Generated<string>;

View File

@@ -4,7 +4,6 @@ import { Asset } from 'src/database';
import { UploadFieldName } from 'src/dtos/asset-media.dto'; import { UploadFieldName } from 'src/dtos/asset-media.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { import {
AssetMetadataKey,
AssetOrder, AssetOrder,
AssetType, AssetType,
DatabaseSslMode, DatabaseSslMode,
@@ -563,12 +562,3 @@ export interface UserMetadata extends Record<UserMetadataKey, Record<string, any
[UserMetadataKey.License]: { licenseKey: string; activationKey: string; activatedAt: string }; [UserMetadataKey.License]: { licenseKey: string; activationKey: string; activatedAt: string };
[UserMetadataKey.Onboarding]: { isOnboarded: boolean }; [UserMetadataKey.Onboarding]: { isOnboarded: boolean };
} }
export type AssetMetadataItem<T extends keyof AssetMetadata = AssetMetadataKey> = {
key: T;
value: AssetMetadata[T];
};
export interface AssetMetadata extends Record<AssetMetadataKey, Record<string, any>> {
[AssetMetadataKey.MobileApp]: { iCloudId: string };
}