mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02:00
refactor: api validators (boolean and date) (#7709)
* refactor: api validators (boolean and date) * chore: open api * revert: time bucket change
This commit is contained in:
parent
753842745d
commit
a50f125dd1
@ -66,8 +66,8 @@ class Asset {
|
|||||||
assetData: new File([await fs.openAsBlob(this.path)], basename(this.path)),
|
assetData: new File([await fs.openAsBlob(this.path)], basename(this.path)),
|
||||||
deviceAssetId: this.deviceAssetId,
|
deviceAssetId: this.deviceAssetId,
|
||||||
deviceId: 'CLI',
|
deviceId: 'CLI',
|
||||||
fileCreatedAt: this.fileCreatedAt,
|
fileCreatedAt: this.fileCreatedAt.toISOString(),
|
||||||
fileModifiedAt: this.fileModifiedAt,
|
fileModifiedAt: this.fileModifiedAt.toISOString(),
|
||||||
isFavorite: String(false),
|
isFavorite: String(false),
|
||||||
};
|
};
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
@ -6,10 +6,9 @@ import request from 'supertest';
|
|||||||
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
const invalidBirthday = [
|
const invalidBirthday = [
|
||||||
// TODO: enable after replacing `@Type(() => Date)`
|
{ birthDate: 'false', response: 'birthDate must be a date string' },
|
||||||
// { birthDate: 'false', response: 'Invalid date' },
|
{ birthDate: '123567', response: 'birthDate must be a date string' },
|
||||||
// { birthDate: '123567', response: 'Invalid date },
|
{ birthDate: 123_567, response: 'birthDate must be a date string' },
|
||||||
// { birthDate: 123_567, response: ['Birth date cannot be in the future'] },
|
|
||||||
{ birthDate: new Date(9999, 0, 0).toISOString(), response: ['Birth date cannot be in the future'] },
|
{ birthDate: new Date(9999, 0, 0).toISOString(), response: ['Birth date cannot be in the future'] },
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -152,16 +151,16 @@ describe('/person', () => {
|
|||||||
expect(body).toEqual(errorDto.unauthorized);
|
expect(body).toEqual(errorDto.unauthorized);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not accept invalid birth dates', async () => {
|
|
||||||
for (const { birthDate, response } of invalidBirthday) {
|
for (const { birthDate, response } of invalidBirthday) {
|
||||||
|
it(`should not accept an invalid birth date [${birthDate}]`, async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.post(`/person`)
|
.post(`/person`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ birthDate });
|
.send({ birthDate });
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(response));
|
expect(body).toEqual(errorDto.badRequest(response));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should create a person', async () => {
|
it('should create a person', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
@ -202,16 +201,16 @@ describe('/person', () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should not accept invalid birth dates', async () => {
|
|
||||||
for (const { birthDate, response } of invalidBirthday) {
|
for (const { birthDate, response } of invalidBirthday) {
|
||||||
|
it(`should not accept an invalid birth date [${birthDate}]`, async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.put(`/person/${visiblePerson.id}`)
|
.put(`/person/${visiblePerson.id}`)
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ birthDate });
|
.send({ birthDate });
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorDto.badRequest(response));
|
expect(body).toEqual(errorDto.badRequest(response));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should update a date of birth', async () => {
|
it('should update a date of birth', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
|
BIN
mobile/openapi/doc/PersonApi.md
generated
BIN
mobile/openapi/doc/PersonApi.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/ScanLibraryDto.md
generated
BIN
mobile/openapi/doc/ScanLibraryDto.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/SharedLinkCreateDto.md
generated
BIN
mobile/openapi/doc/SharedLinkCreateDto.md
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/scan_library_dto.dart
generated
BIN
mobile/openapi/lib/model/scan_library_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/shared_link_create_dto.dart
generated
BIN
mobile/openapi/lib/model/shared_link_create_dto.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/scan_library_dto_test.dart
generated
BIN
mobile/openapi/test/scan_library_dto_test.dart
generated
Binary file not shown.
BIN
mobile/openapi/test/shared_link_create_dto_test.dart
generated
BIN
mobile/openapi/test/shared_link_create_dto_test.dart
generated
Binary file not shown.
@ -4012,7 +4012,6 @@
|
|||||||
"required": false,
|
"required": false,
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"schema": {
|
"schema": {
|
||||||
"default": false,
|
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8937,7 +8936,6 @@
|
|||||||
"ScanLibraryDto": {
|
"ScanLibraryDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"refreshAllFiles": {
|
"refreshAllFiles": {
|
||||||
"default": false,
|
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"refreshModifiedFiles": {
|
"refreshModifiedFiles": {
|
||||||
@ -9346,7 +9344,6 @@
|
|||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"allowUpload": {
|
"allowUpload": {
|
||||||
"default": false,
|
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"assetIds": {
|
"assetIds": {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { IsBoolean, IsString } from 'class-validator';
|
import { IsString } from 'class-validator';
|
||||||
import { Optional, ValidateUUID } from '../../domain.util';
|
import { Optional, ValidateBoolean, ValidateUUID } from '../../domain.util';
|
||||||
|
|
||||||
export class UpdateAlbumDto {
|
export class UpdateAlbumDto {
|
||||||
@Optional()
|
@Optional()
|
||||||
@ -13,7 +13,6 @@ export class UpdateAlbumDto {
|
|||||||
@ValidateUUID({ optional: true })
|
@ValidateUUID({ optional: true })
|
||||||
albumThumbnailAssetId?: string;
|
albumThumbnailAssetId?: string;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isActivityEnabled?: boolean;
|
isActivityEnabled?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
import { Transform } from 'class-transformer';
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
import { IsBoolean } from 'class-validator';
|
|
||||||
import { Optional, toBoolean } from '../../domain.util';
|
|
||||||
|
|
||||||
export class AlbumInfoDto {
|
export class AlbumInfoDto {
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
withoutAssets?: boolean;
|
withoutAssets?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ValidateBoolean, ValidateUUID } from '../../domain.util';
|
||||||
import { Transform } from 'class-transformer';
|
|
||||||
import { IsBoolean } from 'class-validator';
|
|
||||||
import { Optional, toBoolean, ValidateUUID } from '../../domain.util';
|
|
||||||
|
|
||||||
export class GetAlbumsDto {
|
export class GetAlbumsDto {
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
@ApiProperty()
|
|
||||||
/**
|
/**
|
||||||
* true: only shared albums
|
* true: only shared albums
|
||||||
* false: only non-shared own albums
|
* false: only non-shared own albums
|
||||||
|
@ -1,24 +1,16 @@
|
|||||||
import { AssetType } from '@app/infra/entities';
|
import { AssetType } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
import { IsBoolean } from 'class-validator';
|
|
||||||
import { Optional, toBoolean } from '../../domain.util';
|
|
||||||
import { AssetStats } from '../../repositories';
|
import { AssetStats } from '../../repositories';
|
||||||
|
|
||||||
export class AssetStatsDto {
|
export class AssetStatsDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Transform(toBoolean)
|
|
||||||
@Optional()
|
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Transform(toBoolean)
|
|
||||||
@Optional()
|
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Transform(toBoolean)
|
|
||||||
@Optional()
|
|
||||||
isTrashed?: boolean;
|
isTrashed?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import {
|
import {
|
||||||
IsBoolean,
|
|
||||||
IsDateString,
|
IsDateString,
|
||||||
IsInt,
|
IsInt,
|
||||||
IsLatitude,
|
IsLatitude,
|
||||||
@ -10,7 +9,7 @@ import {
|
|||||||
IsString,
|
IsString,
|
||||||
ValidateIf,
|
ValidateIf,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { Optional, ValidateUUID } from '../../domain.util';
|
import { Optional, ValidateBoolean, ValidateUUID } from '../../domain.util';
|
||||||
import { BulkIdsDto } from '../response-dto';
|
import { BulkIdsDto } from '../response-dto';
|
||||||
|
|
||||||
export class DeviceIdDto {
|
export class DeviceIdDto {
|
||||||
@ -28,23 +27,13 @@ const hasGPS = (o: { latitude: undefined; longitude: undefined }) =>
|
|||||||
o.latitude !== undefined || o.longitude !== undefined;
|
o.latitude !== undefined || o.longitude !== undefined;
|
||||||
const ValidateGPS = () => ValidateIf(hasGPS);
|
const ValidateGPS = () => ValidateIf(hasGPS);
|
||||||
|
|
||||||
export class AssetBulkUpdateDto extends BulkIdsDto {
|
export class UpdateAssetBase {
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@Optional()
|
|
||||||
@ValidateUUID()
|
|
||||||
stackParentId?: string;
|
|
||||||
|
|
||||||
@Optional()
|
|
||||||
@IsBoolean()
|
|
||||||
removeParent?: boolean;
|
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
dateTimeOriginal?: string;
|
dateTimeOriginal?: string;
|
||||||
@ -60,32 +49,21 @@ export class AssetBulkUpdateDto extends BulkIdsDto {
|
|||||||
longitude?: number;
|
longitude?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateAssetDto {
|
export class AssetBulkUpdateDto extends UpdateAssetBase {
|
||||||
@Optional()
|
@ValidateUUID({ each: true })
|
||||||
@IsBoolean()
|
ids!: string[];
|
||||||
isFavorite?: boolean;
|
|
||||||
|
|
||||||
@Optional()
|
@ValidateUUID({ optional: true })
|
||||||
@IsBoolean()
|
stackParentId?: string;
|
||||||
isArchived?: boolean;
|
|
||||||
|
|
||||||
|
@ValidateBoolean({ optional: true })
|
||||||
|
removeParent?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UpdateAssetDto extends UpdateAssetBase {
|
||||||
@Optional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@Optional()
|
|
||||||
@IsDateString()
|
|
||||||
dateTimeOriginal?: string;
|
|
||||||
|
|
||||||
@ValidateGPS()
|
|
||||||
@IsLatitude()
|
|
||||||
@IsNotEmpty()
|
|
||||||
latitude?: number;
|
|
||||||
|
|
||||||
@ValidateGPS()
|
|
||||||
@IsLongitude()
|
|
||||||
@IsNotEmpty()
|
|
||||||
longitude?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RandomAssetsDto {
|
export class RandomAssetsDto {
|
||||||
@ -97,7 +75,6 @@ export class RandomAssetsDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AssetBulkDeleteDto extends BulkIdsDto {
|
export class AssetBulkDeleteDto extends BulkIdsDto {
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,18 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ValidateBoolean, ValidateDate } from '../../domain.util';
|
||||||
import { Transform, Type } from 'class-transformer';
|
|
||||||
import { IsBoolean, IsDate } from 'class-validator';
|
|
||||||
import { Optional, toBoolean } from '../../domain.util';
|
|
||||||
|
|
||||||
export class MapMarkerDto {
|
export class MapMarkerDto {
|
||||||
@ApiProperty()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@ApiProperty()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateDate({ optional: true })
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
fileCreatedAfter?: Date;
|
fileCreatedAfter?: Date;
|
||||||
|
|
||||||
@Optional()
|
@ValidateDate({ optional: true })
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
fileCreatedBefore?: Date;
|
fileCreatedBefore?: Date;
|
||||||
|
|
||||||
@ApiProperty()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
withPartners?: boolean;
|
withPartners?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { IsBoolean, IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
import { ValidateBoolean, ValidateUUID } from '../../domain.util';
|
||||||
import { Optional, ValidateUUID, toBoolean } from '../../domain.util';
|
|
||||||
import { TimeBucketSize } from '../../repositories';
|
import { TimeBucketSize } from '../../repositories';
|
||||||
|
|
||||||
export class TimeBucketDto {
|
export class TimeBucketDto {
|
||||||
@ -19,34 +18,23 @@ export class TimeBucketDto {
|
|||||||
@ValidateUUID({ optional: true })
|
@ValidateUUID({ optional: true })
|
||||||
personId?: string;
|
personId?: string;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isTrashed?: boolean;
|
isTrashed?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
withStacked?: boolean;
|
withStacked?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
withPartners?: boolean;
|
withPartners?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TimeBucketAssetDto extends TimeBucketDto {
|
export class TimeBucketAssetDto extends TimeBucketDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
|
||||||
timeBucket!: string;
|
timeBucket!: string;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { AssetPathType, EntityType, PathType, PersonPathType, UserPathType } from '@app/infra/entities';
|
import { AssetPathType, EntityType, PathType, PersonPathType, UserPathType } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsArray, IsDate, IsEnum, IsString, IsUUID, ValidateNested } from 'class-validator';
|
import { IsArray, IsEnum, IsString, IsUUID, ValidateNested } from 'class-validator';
|
||||||
import { Optional, ValidateUUID } from '../domain.util';
|
import { Optional, ValidateDate, ValidateUUID } from '../domain.util';
|
||||||
|
|
||||||
const PathEnum = Object.values({ ...AssetPathType, ...PersonPathType, ...UserPathType });
|
const PathEnum = Object.values({ ...AssetPathType, ...PersonPathType, ...UserPathType });
|
||||||
|
|
||||||
export class AuditDeletesDto {
|
export class AuditDeletesDto {
|
||||||
@IsDate()
|
@ValidateDate()
|
||||||
@Type(() => Date)
|
|
||||||
after!: Date;
|
after!: Date;
|
||||||
|
|
||||||
@ApiProperty({ enum: EntityType, enumName: 'EntityType' })
|
@ApiProperty({ enum: EntityType, enumName: 'EntityType' })
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ImmichLogger } from '@app/infra/logger';
|
import { ImmichLogger } from '@app/infra/logger';
|
||||||
import { applyDecorators } from '@nestjs/common';
|
import { BadRequestException, applyDecorators } from '@nestjs/common';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform, Type } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import {
|
import {
|
||||||
IsArray,
|
IsArray,
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
@ -12,6 +12,7 @@ import {
|
|||||||
IsUUID,
|
IsUUID,
|
||||||
ValidateIf,
|
ValidateIf,
|
||||||
ValidationOptions,
|
ValidationOptions,
|
||||||
|
isDateString,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { CronJob } from 'cron';
|
import { CronJob } from 'cron';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@ -40,14 +41,10 @@ export interface OpenGraphTags {
|
|||||||
imageUrl?: string;
|
imageUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Options = {
|
|
||||||
optional?: boolean;
|
|
||||||
each?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED';
|
export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED';
|
||||||
|
|
||||||
export function ValidateUUID(options?: Options) {
|
type UUIDOptions = { optional?: boolean; each?: boolean };
|
||||||
|
export const ValidateUUID = (options?: UUIDOptions) => {
|
||||||
const { optional, each } = { optional: false, each: false, ...options };
|
const { optional, each } = { optional: false, each: false, ...options };
|
||||||
return applyDecorators(
|
return applyDecorators(
|
||||||
IsUUID('4', { each }),
|
IsUUID('4', { each }),
|
||||||
@ -55,8 +52,59 @@ export function ValidateUUID(options?: Options) {
|
|||||||
optional ? Optional() : IsNotEmpty(),
|
optional ? Optional() : IsNotEmpty(),
|
||||||
each ? IsArray() : IsString(),
|
each ? IsArray() : IsString(),
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type DateOptions = { optional?: boolean; nullable?: boolean; format?: 'date' | 'date-time' };
|
||||||
|
export const ValidateDate = (options?: DateOptions) => {
|
||||||
|
const { optional, nullable, format } = { optional: false, nullable: false, format: 'date-time', ...options };
|
||||||
|
|
||||||
|
const decorators = [
|
||||||
|
ApiProperty({ format }),
|
||||||
|
IsDate(),
|
||||||
|
optional ? Optional({ nullable: true }) : IsNotEmpty(),
|
||||||
|
Transform(({ key, value }) => {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isDateString(value)) {
|
||||||
|
throw new BadRequestException(`${key} must be a date string`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Date(value as string);
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (optional) {
|
||||||
|
decorators.push(Optional({ nullable }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return applyDecorators(...decorators);
|
||||||
|
};
|
||||||
|
|
||||||
|
type BooleanOptions = { optional?: boolean };
|
||||||
|
export const ValidateBoolean = (options?: BooleanOptions) => {
|
||||||
|
const { optional } = { optional: false, ...options };
|
||||||
|
const decorators = [
|
||||||
|
// ApiProperty(),
|
||||||
|
IsBoolean(),
|
||||||
|
Transform(({ value }) => {
|
||||||
|
if (value == 'true') {
|
||||||
|
return true;
|
||||||
|
} else if (value == 'false') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (optional) {
|
||||||
|
decorators.push(Optional());
|
||||||
|
}
|
||||||
|
|
||||||
|
return applyDecorators(...decorators);
|
||||||
|
};
|
||||||
|
|
||||||
export function validateCronExpression(expression: string) {
|
export function validateCronExpression(expression: string) {
|
||||||
try {
|
try {
|
||||||
new CronJob(expression, () => {});
|
new CronJob(expression, () => {});
|
||||||
@ -67,34 +115,7 @@ export function validateCronExpression(expression: string) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IValue {
|
type IValue = { value: string };
|
||||||
value?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const QueryBoolean = ({ optional }: { optional?: boolean }) => {
|
|
||||||
const decorators = [IsBoolean(), Transform(toBoolean)];
|
|
||||||
if (optional) {
|
|
||||||
decorators.push(Optional());
|
|
||||||
}
|
|
||||||
return applyDecorators(...decorators);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const QueryDate = ({ optional }: { optional?: boolean }) => {
|
|
||||||
const decorators = [IsDate(), Type(() => Date)];
|
|
||||||
if (optional) {
|
|
||||||
decorators.push(Optional());
|
|
||||||
}
|
|
||||||
return applyDecorators(...decorators);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toBoolean = ({ value }: IValue) => {
|
|
||||||
if (value == 'true') {
|
|
||||||
return true;
|
|
||||||
} else if (value == 'false') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toEmail = ({ value }: IValue) => value?.toLowerCase();
|
export const toEmail = ({ value }: IValue) => value?.toLowerCase();
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsBoolean, IsEnum, IsNotEmpty } from 'class-validator';
|
import { IsEnum, IsNotEmpty } from 'class-validator';
|
||||||
import { Optional } from '../domain.util';
|
import { ValidateBoolean } from '../domain.util';
|
||||||
import { JobCommand, QueueName } from './job.constants';
|
import { JobCommand, QueueName } from './job.constants';
|
||||||
|
|
||||||
export class JobIdParamDto {
|
export class JobIdParamDto {
|
||||||
@ -16,8 +16,7 @@ export class JobCommandDto {
|
|||||||
@ApiProperty({ type: 'string', enum: JobCommand, enumName: 'JobCommand' })
|
@ApiProperty({ type: 'string', enum: JobCommand, enumName: 'JobCommand' })
|
||||||
command!: JobCommand;
|
command!: JobCommand;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
force!: boolean;
|
force!: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { LibraryEntity, LibraryType } from '@app/infra/entities';
|
import { LibraryEntity, LibraryType } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { ArrayMaxSize, ArrayUnique, IsBoolean, IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
import { ArrayMaxSize, ArrayUnique, IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { Optional, ValidateUUID } from '../domain.util';
|
import { Optional, ValidateBoolean, ValidateUUID } from '../domain.util';
|
||||||
|
|
||||||
export class CreateLibraryDto {
|
export class CreateLibraryDto {
|
||||||
@IsEnum(LibraryType)
|
@IsEnum(LibraryType)
|
||||||
@ -16,8 +16,7 @@ export class CreateLibraryDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@ -34,8 +33,7 @@ export class CreateLibraryDto {
|
|||||||
@ArrayMaxSize(128)
|
@ArrayMaxSize(128)
|
||||||
exclusionPatterns?: string[];
|
exclusionPatterns?: string[];
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isWatched?: boolean;
|
isWatched?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,8 +43,7 @@ export class UpdateLibraryDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@ -102,13 +99,11 @@ export class LibrarySearchDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ScanLibraryDto {
|
export class ScanLibraryDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
refreshModifiedFiles?: boolean;
|
refreshModifiedFiles?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
refreshAllFiles?: boolean;
|
||||||
refreshAllFiles?: boolean = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SearchLibraryDto {
|
export class SearchLibraryDto {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { AssetFaceEntity, PersonEntity } from '@app/infra/entities';
|
import { AssetFaceEntity, PersonEntity } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform, Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsArray, IsBoolean, IsDate, IsNotEmpty, IsString, MaxDate, ValidateNested } from 'class-validator';
|
import { IsArray, IsNotEmpty, IsString, MaxDate, ValidateNested } from 'class-validator';
|
||||||
import { AuthDto } from '../auth';
|
import { AuthDto } from '../auth';
|
||||||
import { Optional, ValidateUUID, toBoolean } from '../domain.util';
|
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from '../domain.util';
|
||||||
|
|
||||||
export class PersonCreateDto {
|
export class PersonCreateDto {
|
||||||
/**
|
/**
|
||||||
@ -17,18 +17,14 @@ export class PersonCreateDto {
|
|||||||
* Person date of birth.
|
* Person date of birth.
|
||||||
* Note: the mobile app cannot currently set the birth date to null.
|
* Note: the mobile app cannot currently set the birth date to null.
|
||||||
*/
|
*/
|
||||||
@Optional({ nullable: true })
|
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
@MaxDate(() => new Date(), { message: 'Birth date cannot be in the future' })
|
@MaxDate(() => new Date(), { message: 'Birth date cannot be in the future' })
|
||||||
@ApiProperty({ format: 'date' })
|
@ValidateDate({ optional: true, nullable: true, format: 'date' })
|
||||||
birthDate?: Date | null;
|
birthDate?: Date | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Person visibility
|
* Person visibility
|
||||||
*/
|
*/
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isHidden?: boolean;
|
isHidden?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +59,8 @@ export class MergePersonDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PersonSearchDto {
|
export class PersonSearchDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Transform(toBoolean)
|
withHidden?: boolean;
|
||||||
withHidden?: boolean = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PersonResponseDto {
|
export class PersonResponseDto {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { AssetOrder } from '@app/domain/asset/dto/asset.dto';
|
import { AssetOrder } from '@app/domain/asset/dto/asset.dto';
|
||||||
import { AssetType, GeodataPlacesEntity } from '@app/infra/entities';
|
import { AssetType, GeodataPlacesEntity } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform, Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator';
|
import { IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator';
|
||||||
import { Optional, QueryBoolean, QueryDate, ValidateUUID, toBoolean } from '../../domain.util';
|
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from '../../domain.util';
|
||||||
|
|
||||||
class BaseSearchDto {
|
class BaseSearchDto {
|
||||||
@ValidateUUID({ optional: true })
|
@ValidateUUID({ optional: true })
|
||||||
@ -19,62 +19,62 @@ class BaseSearchDto {
|
|||||||
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
|
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
|
||||||
type?: AssetType;
|
type?: AssetType;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
@ApiProperty({ default: false })
|
@ApiProperty({ default: false })
|
||||||
withArchived?: boolean;
|
withArchived?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isEncoded?: boolean;
|
isEncoded?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isExternal?: boolean;
|
isExternal?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isMotion?: boolean;
|
isMotion?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isOffline?: boolean;
|
isOffline?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isReadOnly?: boolean;
|
isReadOnly?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
withDeleted?: boolean;
|
withDeleted?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
withExif?: boolean;
|
withExif?: boolean;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
createdBefore?: Date;
|
createdBefore?: Date;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
createdAfter?: Date;
|
createdAfter?: Date;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
updatedBefore?: Date;
|
updatedBefore?: Date;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
updatedAfter?: Date;
|
updatedAfter?: Date;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
trashedBefore?: Date;
|
trashedBefore?: Date;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
trashedAfter?: Date;
|
trashedAfter?: Date;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
takenBefore?: Date;
|
takenBefore?: Date;
|
||||||
|
|
||||||
@QueryDate({ optional: true })
|
@ValidateDate({ optional: true })
|
||||||
takenAfter?: Date;
|
takenAfter?: Date;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -120,7 +120,7 @@ class BaseSearchDto {
|
|||||||
@Optional()
|
@Optional()
|
||||||
size?: number;
|
size?: number;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isNotInAlbum?: boolean;
|
isNotInAlbum?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@ -141,10 +141,10 @@ export class MetadataSearchDto extends BaseSearchDto {
|
|||||||
@Optional()
|
@Optional()
|
||||||
checksum?: string;
|
checksum?: string;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
withStacked?: boolean;
|
withStacked?: boolean;
|
||||||
|
|
||||||
@QueryBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
withPeople?: boolean;
|
withPeople?: boolean;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -197,34 +197,24 @@ export class SearchDto {
|
|||||||
@Optional()
|
@Optional()
|
||||||
query?: string;
|
query?: string;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
smart?: boolean;
|
smart?: boolean;
|
||||||
|
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
clip?: boolean;
|
clip?: boolean;
|
||||||
|
|
||||||
@IsEnum(AssetType)
|
@IsEnum(AssetType)
|
||||||
@Optional()
|
@Optional()
|
||||||
type?: AssetType;
|
type?: AssetType;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
recent?: boolean;
|
recent?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
motion?: boolean;
|
motion?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Optional()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
withArchived?: boolean;
|
withArchived?: boolean;
|
||||||
|
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@ -252,9 +242,7 @@ export class SearchPeopleDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
name!: string;
|
name!: string;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean({ optional: true })
|
||||||
@Transform(toBoolean)
|
|
||||||
@Optional()
|
|
||||||
withHidden?: boolean;
|
withHidden?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { SharedLinkType } from '@app/infra/entities';
|
import { SharedLinkType } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Type } from 'class-transformer';
|
import { IsEnum, IsString } from 'class-validator';
|
||||||
import { IsBoolean, IsDate, IsEnum, IsString } from 'class-validator';
|
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from '../domain.util';
|
||||||
import { Optional, ValidateUUID } from '../domain.util';
|
|
||||||
|
|
||||||
export class SharedLinkCreateDto {
|
export class SharedLinkCreateDto {
|
||||||
@IsEnum(SharedLinkType)
|
@IsEnum(SharedLinkType)
|
||||||
@ -23,21 +22,16 @@ export class SharedLinkCreateDto {
|
|||||||
@Optional()
|
@Optional()
|
||||||
password?: string;
|
password?: string;
|
||||||
|
|
||||||
@IsDate()
|
@ValidateDate({ optional: true, nullable: true })
|
||||||
@Type(() => Date)
|
|
||||||
@Optional({ nullable: true })
|
|
||||||
expiresAt?: Date | null = null;
|
expiresAt?: Date | null = null;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
allowUpload?: boolean;
|
||||||
allowUpload?: boolean = false;
|
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
allowDownload?: boolean = true;
|
allowDownload?: boolean = true;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
showMetadata?: boolean = true;
|
showMetadata?: boolean = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,10 +48,10 @@ export class SharedLinkEditDto {
|
|||||||
@Optional()
|
@Optional()
|
||||||
allowUpload?: boolean;
|
allowUpload?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
allowDownload?: boolean;
|
allowDownload?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
showMetadata?: boolean;
|
showMetadata?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,8 +59,7 @@ export class SharedLinkEditDto {
|
|||||||
* Setting this flag and not sending expiryAt is considered as null instead.
|
* Setting this flag and not sending expiryAt is considered as null instead.
|
||||||
* Clients that can send null values can ignore this.
|
* Clients that can send null values can ignore this.
|
||||||
*/
|
*/
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
changeExpiryTime?: boolean;
|
changeExpiryTime?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsEnum, IsNotEmpty, IsNumber, IsString, Max, Min } from 'class-validator';
|
import { IsEnum, IsNotEmpty, IsNumber, IsString, Max, Min } from 'class-validator';
|
||||||
import { Optional } from '../../domain.util';
|
import { Optional, ValidateBoolean } from '../../domain.util';
|
||||||
import { CLIPMode, ModelType } from '../../repositories';
|
import { CLIPMode, ModelType } from '../../repositories';
|
||||||
|
|
||||||
export class ModelConfig {
|
export class ModelConfig {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { AudioCodec, CQMode, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec } from '@app/infra/entities';
|
import { AudioCodec, CQMode, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsEnum, IsInt, IsString, Max, Min } from 'class-validator';
|
import { IsEnum, IsInt, IsString, Max, Min } from 'class-validator';
|
||||||
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigFFmpegDto {
|
export class SystemConfigFFmpegDto {
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@ -68,14 +69,14 @@ export class SystemConfigFFmpegDto {
|
|||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
npl!: number;
|
npl!: number;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
temporalAQ!: boolean;
|
temporalAQ!: boolean;
|
||||||
|
|
||||||
@IsEnum(CQMode)
|
@IsEnum(CQMode)
|
||||||
@ApiProperty({ enumName: 'CQMode', enum: CQMode })
|
@ApiProperty({ enumName: 'CQMode', enum: CQMode })
|
||||||
cqMode!: CQMode;
|
cqMode!: CQMode;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
twoPass!: boolean;
|
twoPass!: boolean;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { validateCronExpression } from '@app/domain';
|
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import {
|
import {
|
||||||
IsBoolean,
|
|
||||||
IsNotEmpty,
|
IsNotEmpty,
|
||||||
IsObject,
|
IsObject,
|
||||||
IsString,
|
IsString,
|
||||||
@ -11,6 +9,7 @@ import {
|
|||||||
ValidatorConstraint,
|
ValidatorConstraint,
|
||||||
ValidatorConstraintInterface,
|
ValidatorConstraintInterface,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
|
import { ValidateBoolean, validateCronExpression } from '../../domain.util';
|
||||||
|
|
||||||
const isEnabled = (config: SystemConfigLibraryScanDto) => config.enabled;
|
const isEnabled = (config: SystemConfigLibraryScanDto) => config.enabled;
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ class CronValidator implements ValidatorConstraintInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SystemConfigLibraryScanDto {
|
export class SystemConfigLibraryScanDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
|
|
||||||
@ValidateIf(isEnabled)
|
@ValidateIf(isEnabled)
|
||||||
@ -33,7 +32,7 @@ export class SystemConfigLibraryScanDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SystemConfigLibraryWatchDto {
|
export class SystemConfigLibraryWatchDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { LogLevel } from '@app/infra/entities';
|
import { LogLevel } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsBoolean, IsEnum } from 'class-validator';
|
import { IsEnum } from 'class-validator';
|
||||||
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigLoggingDto {
|
export class SystemConfigLoggingDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
|
|
||||||
@ApiProperty({ enum: LogLevel, enumName: 'LogLevel' })
|
@ApiProperty({ enum: LogLevel, enumName: 'LogLevel' })
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { CLIPConfig, RecognitionConfig } from '@app/domain';
|
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsObject, IsUrl, ValidateIf, ValidateNested } from 'class-validator';
|
import { IsObject, IsUrl, ValidateIf, ValidateNested } from 'class-validator';
|
||||||
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
import { CLIPConfig, RecognitionConfig } from '../../smart-info/dto/model-config.dto';
|
||||||
|
|
||||||
export class SystemConfigMachineLearningDto {
|
export class SystemConfigMachineLearningDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
|
|
||||||
@IsUrl({ require_tld: false, allow_underscores: true })
|
@IsUrl({ require_tld: false, allow_underscores: true })
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { IsBoolean, IsString } from 'class-validator';
|
import { IsString } from 'class-validator';
|
||||||
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigMapDto {
|
export class SystemConfigMapDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IsBoolean } from 'class-validator';
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigNewVersionCheckDto {
|
export class SystemConfigNewVersionCheckDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { IsBoolean, IsNotEmpty, IsNumber, IsString, IsUrl, Min, ValidateIf } from 'class-validator';
|
import { IsNotEmpty, IsNumber, IsString, IsUrl, Min, ValidateIf } from 'class-validator';
|
||||||
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
const isEnabled = (config: SystemConfigOAuthDto) => config.enabled;
|
const isEnabled = (config: SystemConfigOAuthDto) => config.enabled;
|
||||||
const isOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled;
|
const isOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled;
|
||||||
|
|
||||||
export class SystemConfigOAuthDto {
|
export class SystemConfigOAuthDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
autoLaunch!: boolean;
|
autoLaunch!: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
autoRegister!: boolean;
|
autoRegister!: boolean;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -27,7 +28,7 @@ export class SystemConfigOAuthDto {
|
|||||||
@Min(0)
|
@Min(0)
|
||||||
defaultStorageQuota!: number;
|
defaultStorageQuota!: number;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
|
|
||||||
@ValidateIf(isEnabled)
|
@ValidateIf(isEnabled)
|
||||||
@ -35,7 +36,7 @@ export class SystemConfigOAuthDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
issuerUrl!: string;
|
issuerUrl!: string;
|
||||||
|
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
mobileOverrideEnabled!: boolean;
|
mobileOverrideEnabled!: boolean;
|
||||||
|
|
||||||
@ValidateIf(isOverrideEnabled)
|
@ValidateIf(isOverrideEnabled)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IsBoolean } from 'class-validator';
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigPasswordLoginDto {
|
export class SystemConfigPasswordLoginDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IsBoolean } from 'class-validator';
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigReverseGeocodingDto {
|
export class SystemConfigReverseGeocodingDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigStorageTemplateDto {
|
export class SystemConfigStorageTemplateDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
@IsBoolean()
|
|
||||||
|
@ValidateBoolean()
|
||||||
hashVerificationEnabled!: boolean;
|
hashVerificationEnabled!: boolean;
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
template!: string;
|
template!: string;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsInt, Min } from 'class-validator';
|
import { IsInt, Min } from 'class-validator';
|
||||||
|
import { ValidateBoolean } from '../../domain.util';
|
||||||
|
|
||||||
export class SystemConfigTrashDto {
|
export class SystemConfigTrashDto {
|
||||||
@IsBoolean()
|
@ValidateBoolean()
|
||||||
enabled!: boolean;
|
enabled!: boolean;
|
||||||
|
|
||||||
@IsInt()
|
@IsInt()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsEmail, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator';
|
import { IsEmail, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator';
|
||||||
import { Optional, toEmail, toSanitized } from '../../domain.util';
|
import { Optional, ValidateBoolean, toEmail, toSanitized } from '../../domain.util';
|
||||||
|
|
||||||
export class CreateUserDto {
|
export class CreateUserDto {
|
||||||
@IsEmail({ require_tld: false })
|
@IsEmail({ require_tld: false })
|
||||||
@ -21,8 +21,7 @@ export class CreateUserDto {
|
|||||||
@Transform(toSanitized)
|
@Transform(toSanitized)
|
||||||
storageLabel?: string | null;
|
storageLabel?: string | null;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
|
|
||||||
@Optional({ nullable: true })
|
@Optional({ nullable: true })
|
||||||
@ -31,8 +30,7 @@ export class CreateUserDto {
|
|||||||
@ApiProperty({ type: 'integer', format: 'int64' })
|
@ApiProperty({ type: 'integer', format: 'int64' })
|
||||||
quotaSizeInBytes?: number | null;
|
quotaSizeInBytes?: number | null;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
shouldChangePassword?: boolean;
|
shouldChangePassword?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { UserAvatarColor } from '@app/infra/entities';
|
import { UserAvatarColor } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator';
|
import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator';
|
||||||
import { Optional, toEmail, toSanitized } from '../../domain.util';
|
import { Optional, ValidateBoolean, toEmail, toSanitized } from '../../domain.util';
|
||||||
|
|
||||||
export class UpdateUserDto {
|
export class UpdateUserDto {
|
||||||
@Optional()
|
@Optional()
|
||||||
@ -30,16 +30,13 @@ export class UpdateUserDto {
|
|||||||
@ApiProperty({ format: 'uuid' })
|
@ApiProperty({ format: 'uuid' })
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
shouldChangePassword?: boolean;
|
shouldChangePassword?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
import { Optional, toBoolean } from '@app/domain';
|
import { Optional, ValidateBoolean, ValidateDate } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform, Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsDate, IsInt, IsNotEmpty, IsUUID } from 'class-validator';
|
import { IsInt, IsUUID } from 'class-validator';
|
||||||
|
|
||||||
export class AssetSearchDto {
|
export class AssetSearchDto {
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsNotEmpty()
|
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsNotEmpty()
|
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@ -33,13 +27,9 @@ export class AssetSearchDto {
|
|||||||
@ApiProperty({ format: 'uuid' })
|
@ApiProperty({ format: 'uuid' })
|
||||||
userId?: string;
|
userId?: string;
|
||||||
|
|
||||||
@Optional()
|
@ValidateDate({ optional: true })
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
updatedAfter?: Date;
|
updatedAfter?: Date;
|
||||||
|
|
||||||
@Optional()
|
@ValidateDate({ optional: true })
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
updatedBefore?: Date;
|
updatedBefore?: Date;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Optional, toBoolean, UploadFieldName, ValidateUUID } from '@app/domain';
|
import { Optional, UploadFieldName, ValidateBoolean, ValidateDate, ValidateUUID } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform, Type } from 'class-transformer';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { IsBoolean, IsDate, IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class CreateAssetDto {
|
export class CreateAssetDto {
|
||||||
@ValidateUUID({ optional: true })
|
@ValidateUUID({ optional: true })
|
||||||
@ -15,43 +14,29 @@ export class CreateAssetDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
deviceId!: string;
|
deviceId!: string;
|
||||||
|
|
||||||
@IsNotEmpty()
|
@ValidateDate()
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
fileCreatedAt!: Date;
|
fileCreatedAt!: Date;
|
||||||
|
|
||||||
@IsNotEmpty()
|
@ValidateDate()
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
fileModifiedAt!: Date;
|
fileModifiedAt!: Date;
|
||||||
|
|
||||||
@Optional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
duration?: string;
|
duration?: string;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isOffline?: boolean;
|
isOffline?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
|
||||||
@Transform(toBoolean)
|
|
||||||
isReadOnly?: boolean;
|
isReadOnly?: boolean;
|
||||||
|
|
||||||
// The properties below are added to correctly generate the API docs
|
// The properties below are added to correctly generate the API docs
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
import { Optional, toBoolean } from '@app/domain';
|
import { ValidateBoolean } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
|
||||||
import { IsBoolean } from 'class-validator';
|
|
||||||
|
|
||||||
export class ServeFileDto {
|
export class ServeFileDto {
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
@ApiProperty({ title: 'Is serve thumbnail (resize) file' })
|
||||||
@Transform(toBoolean)
|
|
||||||
@ApiProperty({ type: Boolean, title: 'Is serve thumbnail (resize) file' })
|
|
||||||
isThumb?: boolean;
|
isThumb?: boolean;
|
||||||
|
|
||||||
@Optional()
|
@ValidateBoolean({ optional: true })
|
||||||
@IsBoolean()
|
@ApiProperty({ title: 'Is request made from web' })
|
||||||
@Transform(toBoolean)
|
|
||||||
@ApiProperty({ type: Boolean, title: 'Is request made from web' })
|
|
||||||
isWeb?: boolean;
|
isWeb?: boolean;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user