mirror of
https://github.com/immich-app/immich.git
synced 2025-06-23 15:30:51 -04:00
fix(server): non-nullable IsOptional
(#3939)
* custom `IsOptional` * added link to source * formatting * Update server/src/domain/domain.util.ts Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> * nullable birth date endpoint * made `nullable` a property * formatting * removed unused dto * updated decorator arg * fixed album e2e tests * add null tests for auth e2e * add null test for person e2e * fixed tests * added null test for user e2e * removed unusued import * log key in test name * chore: add note about mobile not being able to use the endpoint --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
parent
ca35e5557b
commit
9539a361e4
4
cli/src/api/open-api/api.ts
generated
4
cli/src/api/open-api/api.ts
generated
@ -1982,7 +1982,7 @@ export interface PeopleUpdateDto {
|
|||||||
*/
|
*/
|
||||||
export interface PeopleUpdateItem {
|
export interface PeopleUpdateItem {
|
||||||
/**
|
/**
|
||||||
* Person date of birth.
|
* Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof PeopleUpdateItem
|
* @memberof PeopleUpdateItem
|
||||||
*/
|
*/
|
||||||
@ -2056,7 +2056,7 @@ export interface PersonResponseDto {
|
|||||||
*/
|
*/
|
||||||
export interface PersonUpdateDto {
|
export interface PersonUpdateDto {
|
||||||
/**
|
/**
|
||||||
* Person date of birth.
|
* Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof PersonUpdateDto
|
* @memberof PersonUpdateDto
|
||||||
*/
|
*/
|
||||||
|
2
mobile/openapi/doc/PeopleUpdateItem.md
generated
2
mobile/openapi/doc/PeopleUpdateItem.md
generated
@ -8,7 +8,7 @@ import 'package:openapi/api.dart';
|
|||||||
## Properties
|
## Properties
|
||||||
Name | Type | Description | Notes
|
Name | Type | Description | Notes
|
||||||
------------ | ------------- | ------------- | -------------
|
------------ | ------------- | ------------- | -------------
|
||||||
**birthDate** | [**DateTime**](DateTime.md) | Person date of birth. | [optional]
|
**birthDate** | [**DateTime**](DateTime.md) | Person date of birth. Note: the mobile app cannot currently set the birth date to null. | [optional]
|
||||||
**featureFaceAssetId** | **String** | Asset is used to get the feature face thumbnail. | [optional]
|
**featureFaceAssetId** | **String** | Asset is used to get the feature face thumbnail. | [optional]
|
||||||
**id** | **String** | Person id. |
|
**id** | **String** | Person id. |
|
||||||
**isHidden** | **bool** | Person visibility | [optional]
|
**isHidden** | **bool** | Person visibility | [optional]
|
||||||
|
2
mobile/openapi/doc/PersonUpdateDto.md
generated
2
mobile/openapi/doc/PersonUpdateDto.md
generated
@ -8,7 +8,7 @@ import 'package:openapi/api.dart';
|
|||||||
## Properties
|
## Properties
|
||||||
Name | Type | Description | Notes
|
Name | Type | Description | Notes
|
||||||
------------ | ------------- | ------------- | -------------
|
------------ | ------------- | ------------- | -------------
|
||||||
**birthDate** | [**DateTime**](DateTime.md) | Person date of birth. | [optional]
|
**birthDate** | [**DateTime**](DateTime.md) | Person date of birth. Note: the mobile app cannot currently set the birth date to null. | [optional]
|
||||||
**featureFaceAssetId** | **String** | Asset is used to get the feature face thumbnail. | [optional]
|
**featureFaceAssetId** | **String** | Asset is used to get the feature face thumbnail. | [optional]
|
||||||
**isHidden** | **bool** | Person visibility | [optional]
|
**isHidden** | **bool** | Person visibility | [optional]
|
||||||
**name** | **String** | Person name. | [optional]
|
**name** | **String** | Person name. | [optional]
|
||||||
|
2
mobile/openapi/lib/model/people_update_item.dart
generated
2
mobile/openapi/lib/model/people_update_item.dart
generated
@ -20,7 +20,7 @@ class PeopleUpdateItem {
|
|||||||
this.name,
|
this.name,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Person date of birth.
|
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
DateTime? birthDate;
|
DateTime? birthDate;
|
||||||
|
|
||||||
/// Asset is used to get the feature face thumbnail.
|
/// Asset is used to get the feature face thumbnail.
|
||||||
|
2
mobile/openapi/lib/model/person_update_dto.dart
generated
2
mobile/openapi/lib/model/person_update_dto.dart
generated
@ -19,7 +19,7 @@ class PersonUpdateDto {
|
|||||||
this.name,
|
this.name,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Person date of birth.
|
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
DateTime? birthDate;
|
DateTime? birthDate;
|
||||||
|
|
||||||
/// Asset is used to get the feature face thumbnail.
|
/// Asset is used to get the feature face thumbnail.
|
||||||
|
2
mobile/openapi/test/people_update_item_test.dart
generated
2
mobile/openapi/test/people_update_item_test.dart
generated
@ -16,7 +16,7 @@ void main() {
|
|||||||
// final instance = PeopleUpdateItem();
|
// final instance = PeopleUpdateItem();
|
||||||
|
|
||||||
group('test PeopleUpdateItem', () {
|
group('test PeopleUpdateItem', () {
|
||||||
// Person date of birth.
|
// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
// DateTime birthDate
|
// DateTime birthDate
|
||||||
test('to test the property `birthDate`', () async {
|
test('to test the property `birthDate`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
2
mobile/openapi/test/person_update_dto_test.dart
generated
2
mobile/openapi/test/person_update_dto_test.dart
generated
@ -16,7 +16,7 @@ void main() {
|
|||||||
// final instance = PersonUpdateDto();
|
// final instance = PersonUpdateDto();
|
||||||
|
|
||||||
group('test PersonUpdateDto', () {
|
group('test PersonUpdateDto', () {
|
||||||
// Person date of birth.
|
// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
// DateTime birthDate
|
// DateTime birthDate
|
||||||
test('to test the property `birthDate`', () async {
|
test('to test the property `birthDate`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -6331,7 +6331,7 @@
|
|||||||
"PeopleUpdateItem": {
|
"PeopleUpdateItem": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"birthDate": {
|
"birthDate": {
|
||||||
"description": "Person date of birth.",
|
"description": "Person date of birth.\nNote: the mobile app cannot currently set the birth date to null.",
|
||||||
"format": "date",
|
"format": "date",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -6390,7 +6390,7 @@
|
|||||||
"PersonUpdateDto": {
|
"PersonUpdateDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"birthDate": {
|
"birthDate": {
|
||||||
"description": "Person date of birth.",
|
"description": "Person date of birth.\nNote: the mobile app cannot currently set the birth date to null.",
|
||||||
"format": "date",
|
"format": "date",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { ValidateUUID } from '../../domain.util';
|
import { Optional, ValidateUUID } from '../../domain.util';
|
||||||
|
|
||||||
export class CreateAlbumDto {
|
export class CreateAlbumDto {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -9,7 +9,7 @@ export class CreateAlbumDto {
|
|||||||
albumName!: string;
|
albumName!: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@ValidateUUID({ optional: true, each: true })
|
@ValidateUUID({ optional: true, each: true })
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { IsOptional, IsString } from 'class-validator';
|
import { IsString } from 'class-validator';
|
||||||
import { ValidateUUID } from '../../domain.util';
|
import { ValidateUUID, Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class UpdateAlbumDto {
|
export class UpdateAlbumDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
albumName?: string;
|
albumName?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsOptional } from 'class-validator';
|
import { IsBoolean } from 'class-validator';
|
||||||
import { toBoolean } from '../../domain.util';
|
import { toBoolean, Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class AlbumInfoDto {
|
export class AlbumInfoDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
withoutAssets?: boolean;
|
withoutAssets?: boolean;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsOptional } from 'class-validator';
|
import { IsBoolean } from 'class-validator';
|
||||||
import { toBoolean, ValidateUUID } from '../../domain.util';
|
import { toBoolean, ValidateUUID, Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class GetAlbumsDto {
|
export class GetAlbumsDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
import { Optional } from '../domain.util';
|
||||||
export class APIKeyCreateDto {
|
export class APIKeyCreateDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
name?: string;
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
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 { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsOptional } from 'class-validator';
|
import { IsBoolean } from 'class-validator';
|
||||||
import { toBoolean } from '../../domain.util';
|
import { toBoolean, Optional } from '../../domain.util';
|
||||||
import { AssetStats } from '../asset.repository';
|
import { AssetStats } from '../asset.repository';
|
||||||
|
|
||||||
export class AssetStatsDto {
|
export class AssetStatsDto {
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
@IsOptional()
|
@Optional()
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
@IsOptional()
|
@Optional()
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { IsBoolean, IsOptional } from 'class-validator';
|
import { IsBoolean } from 'class-validator';
|
||||||
import { BulkIdsDto } from '../response-dto';
|
import { BulkIdsDto } from '../response-dto';
|
||||||
|
import { Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class AssetBulkUpdateDto extends BulkIdsDto {
|
export class AssetBulkUpdateDto extends BulkIdsDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsInt, IsOptional, IsPositive } from 'class-validator';
|
import { IsInt, IsPositive } from 'class-validator';
|
||||||
import { ValidateUUID } from '../../domain.util';
|
import { Optional, ValidateUUID } from '../../domain.util';
|
||||||
|
|
||||||
export class DownloadInfoDto {
|
export class DownloadInfoDto {
|
||||||
@ValidateUUID({ each: true, optional: true })
|
@ValidateUUID({ each: true, optional: true })
|
||||||
@ -14,7 +14,7 @@ export class DownloadInfoDto {
|
|||||||
|
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
archiveSize?: number;
|
archiveSize?: number;
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform, Type } from 'class-transformer';
|
import { Transform, Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsDate, IsOptional } from 'class-validator';
|
import { IsBoolean, IsDate } from 'class-validator';
|
||||||
import { toBoolean } from '../../domain.util';
|
import { toBoolean, Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class MapMarkerDto {
|
export class MapMarkerDto {
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsDate()
|
@IsDate()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
fileCreatedAfter?: Date;
|
fileCreatedAfter?: Date;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsDate()
|
@IsDate()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
fileCreatedBefore?: Date;
|
fileCreatedBefore?: Date;
|
||||||
|
@ -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, IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsBoolean, IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { toBoolean, ValidateUUID } from '../../domain.util';
|
import { toBoolean, ValidateUUID, Optional } from '../../domain.util';
|
||||||
import { TimeBucketSize } from '../asset.repository';
|
import { TimeBucketSize } from '../asset.repository';
|
||||||
|
|
||||||
export class TimeBucketDto {
|
export class TimeBucketDto {
|
||||||
@ -19,12 +19,12 @@ export class TimeBucketDto {
|
|||||||
@ValidateUUID({ optional: true })
|
@ValidateUUID({ optional: true })
|
||||||
personId?: string;
|
personId?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { EntityType } from '@app/infra/entities';
|
import { EntityType } 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 { IsDate, IsEnum, IsOptional, IsUUID } from 'class-validator';
|
import { IsDate, IsEnum, IsUUID } from 'class-validator';
|
||||||
|
import { Optional } from '../domain.util';
|
||||||
|
|
||||||
export class AuditDeletesDto {
|
export class AuditDeletesDto {
|
||||||
@IsDate()
|
@IsDate()
|
||||||
@ -12,7 +13,7 @@ export class AuditDeletesDto {
|
|||||||
@IsEnum(EntityType)
|
@IsEnum(EntityType)
|
||||||
entityType!: EntityType;
|
entityType!: EntityType;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsUUID('4')
|
@IsUUID('4')
|
||||||
@ApiProperty({ format: 'uuid' })
|
@ApiProperty({ format: 'uuid' })
|
||||||
userId?: string;
|
userId?: string;
|
||||||
|
@ -4,8 +4,9 @@ import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
|
|||||||
|
|
||||||
export class LoginCredentialDto {
|
export class LoginCredentialDto {
|
||||||
@IsEmail({ require_tld: false })
|
@IsEmail({ require_tld: false })
|
||||||
|
@Transform(({ value }) => value?.toLowerCase())
|
||||||
|
@IsNotEmpty()
|
||||||
@ApiProperty({ example: 'testuser@email.com' })
|
@ApiProperty({ example: 'testuser@email.com' })
|
||||||
@Transform(({ value }) => value.toLowerCase())
|
|
||||||
email!: string;
|
email!: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -4,8 +4,9 @@ import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
|
|||||||
|
|
||||||
export class SignUpDto {
|
export class SignUpDto {
|
||||||
@IsEmail({ require_tld: false })
|
@IsEmail({ require_tld: false })
|
||||||
|
@Transform(({ value }) => value?.toLowerCase())
|
||||||
|
@IsNotEmpty()
|
||||||
@ApiProperty({ example: 'testuser@email.com' })
|
@ApiProperty({ example: 'testuser@email.com' })
|
||||||
@Transform(({ value }) => value.toLowerCase())
|
|
||||||
email!: string;
|
email!: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { applyDecorators } from '@nestjs/common';
|
import { applyDecorators } from '@nestjs/common';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsArray, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
|
import { IsArray, IsNotEmpty, IsOptional, IsString, IsUUID, ValidationOptions, ValidateIf } from 'class-validator';
|
||||||
import { basename, extname } from 'node:path';
|
import { basename, extname } from 'node:path';
|
||||||
import sanitize from 'sanitize-filename';
|
import sanitize from 'sanitize-filename';
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ export function ValidateUUID({ optional, each }: Options = { optional: false, ea
|
|||||||
return applyDecorators(
|
return applyDecorators(
|
||||||
IsUUID('4', { each }),
|
IsUUID('4', { each }),
|
||||||
ApiProperty({ format: 'uuid' }),
|
ApiProperty({ format: 'uuid' }),
|
||||||
optional ? IsOptional() : IsNotEmpty(),
|
optional ? Optional() : IsNotEmpty(),
|
||||||
each ? IsArray() : IsString(),
|
each ? IsArray() : IsString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -92,3 +92,23 @@ export async function* usePagination<T>(
|
|||||||
yield result.items;
|
yield result.items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OptionalOptions extends ValidationOptions {
|
||||||
|
nullable?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if value is missing and if so, ignores all validators.
|
||||||
|
*
|
||||||
|
* @param validationOptions {@link OptionalOptions}
|
||||||
|
*
|
||||||
|
* @see IsOptional exported from `class-validator.
|
||||||
|
*/
|
||||||
|
// https://stackoverflow.com/a/71353929
|
||||||
|
export function Optional({ nullable, ...validationOptions }: OptionalOptions = {}) {
|
||||||
|
if (nullable === true) {
|
||||||
|
return IsOptional(validationOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ValidateIf((obj: any, v: any) => v !== undefined, validationOptions);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsBoolean, IsEnum, IsNotEmpty, IsOptional } from 'class-validator';
|
import { IsBoolean, IsEnum, IsNotEmpty } from 'class-validator';
|
||||||
import { JobCommand, QueueName } from './job.constants';
|
import { JobCommand, QueueName } from './job.constants';
|
||||||
|
import { Optional } from '../domain.util';
|
||||||
|
|
||||||
export class JobIdParamDto {
|
export class JobIdParamDto {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -15,7 +16,7 @@ export class JobCommandDto {
|
|||||||
@ApiProperty({ type: 'string', enum: JobCommand, enumName: 'JobCommand' })
|
@ApiProperty({ type: 'string', enum: JobCommand, enumName: 'JobCommand' })
|
||||||
command!: JobCommand;
|
command!: JobCommand;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
force!: boolean;
|
force!: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,38 @@
|
|||||||
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 { Transform, Type } from 'class-transformer';
|
||||||
import {
|
import { IsArray, IsBoolean, IsDate, IsNotEmpty, IsString, ValidateNested } from 'class-validator';
|
||||||
IsArray,
|
import { Optional, toBoolean, ValidateUUID } from '../domain.util';
|
||||||
IsBoolean,
|
|
||||||
IsDate,
|
|
||||||
IsNotEmpty,
|
|
||||||
IsOptional,
|
|
||||||
IsString,
|
|
||||||
ValidateIf,
|
|
||||||
ValidateNested,
|
|
||||||
} from 'class-validator';
|
|
||||||
import { toBoolean, ValidateUUID } from '../domain.util';
|
|
||||||
|
|
||||||
export class PersonUpdateDto {
|
export class PersonUpdateDto {
|
||||||
/**
|
/**
|
||||||
* Person name.
|
* Person name.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Person date of birth.
|
* Person date of birth.
|
||||||
|
* Note: the mobile app cannot currently set the birth date to null.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@Optional({ nullable: true })
|
||||||
@IsDate()
|
@IsDate()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@ValidateIf((value) => value !== null)
|
|
||||||
@ApiProperty({ format: 'date' })
|
@ApiProperty({ format: 'date' })
|
||||||
birthDate?: Date | null;
|
birthDate?: Date | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asset is used to get the feature face thumbnail.
|
* Asset is used to get the feature face thumbnail.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
featureFaceAssetId?: string;
|
featureFaceAssetId?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Person visibility
|
* Person visibility
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isHidden?: boolean;
|
isHidden?: boolean;
|
||||||
}
|
}
|
||||||
@ -53,43 +44,13 @@ export class PeopleUpdateDto {
|
|||||||
people!: PeopleUpdateItem[];
|
people!: PeopleUpdateItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PeopleUpdateItem {
|
export class PeopleUpdateItem extends PersonUpdateDto {
|
||||||
/**
|
/**
|
||||||
* Person id.
|
* Person id.
|
||||||
*/
|
*/
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Person name.
|
|
||||||
*/
|
|
||||||
@IsOptional()
|
|
||||||
@IsString()
|
|
||||||
name?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Person date of birth.
|
|
||||||
*/
|
|
||||||
@IsOptional()
|
|
||||||
@IsDate()
|
|
||||||
@Type(() => Date)
|
|
||||||
@ApiProperty({ format: 'date' })
|
|
||||||
birthDate?: Date | null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asset is used to get the feature face thumbnail.
|
|
||||||
*/
|
|
||||||
@IsOptional()
|
|
||||||
@IsString()
|
|
||||||
featureFaceAssetId?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Person visibility
|
|
||||||
*/
|
|
||||||
@IsOptional()
|
|
||||||
@IsBoolean()
|
|
||||||
isHidden?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MergePersonDto {
|
export class MergePersonDto {
|
||||||
|
@ -1,87 +1,87 @@
|
|||||||
import { AssetType } from '@app/infra/entities';
|
import { AssetType } from '@app/infra/entities';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsArray, IsBoolean, IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsArray, IsBoolean, IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { toBoolean } from '../../domain.util';
|
import { toBoolean, Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class SearchDto {
|
export class SearchDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
q?: string;
|
q?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
query?: string;
|
query?: string;
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
clip?: boolean;
|
clip?: boolean;
|
||||||
|
|
||||||
@IsEnum(AssetType)
|
@IsEnum(AssetType)
|
||||||
@IsOptional()
|
@Optional()
|
||||||
type?: AssetType;
|
type?: AssetType;
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
'exifInfo.city'?: string;
|
'exifInfo.city'?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
'exifInfo.state'?: string;
|
'exifInfo.state'?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
'exifInfo.country'?: string;
|
'exifInfo.country'?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
'exifInfo.make'?: string;
|
'exifInfo.make'?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
'exifInfo.model'?: string;
|
'exifInfo.model'?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
'exifInfo.projectionType'?: string;
|
'exifInfo.projectionType'?: string;
|
||||||
|
|
||||||
@IsString({ each: true })
|
@IsString({ each: true })
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(({ value }) => value.split(','))
|
@Transform(({ value }) => value.split(','))
|
||||||
'smartInfo.objects'?: string[];
|
'smartInfo.objects'?: string[];
|
||||||
|
|
||||||
@IsString({ each: true })
|
@IsString({ each: true })
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(({ value }) => value.split(','))
|
@Transform(({ value }) => value.split(','))
|
||||||
'smartInfo.tags'?: string[];
|
'smartInfo.tags'?: string[];
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
recent?: boolean;
|
recent?: boolean;
|
||||||
|
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
motion?: boolean;
|
motion?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
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 { Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsDate, IsEnum, IsOptional, IsString } from 'class-validator';
|
import { IsBoolean, IsDate, IsEnum, IsString } from 'class-validator';
|
||||||
import { ValidateUUID } from '../domain.util';
|
import { ValidateUUID, Optional } from '../domain.util';
|
||||||
|
|
||||||
export class SharedLinkCreateDto {
|
export class SharedLinkCreateDto {
|
||||||
@IsEnum(SharedLinkType)
|
@IsEnum(SharedLinkType)
|
||||||
@ -16,40 +16,40 @@ export class SharedLinkCreateDto {
|
|||||||
albumId?: string;
|
albumId?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@IsDate()
|
@IsDate()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@IsOptional()
|
@Optional({ nullable: true })
|
||||||
expiresAt?: Date | null = null;
|
expiresAt?: Date | null = null;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
allowUpload?: boolean = false;
|
allowUpload?: boolean = false;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
allowDownload?: boolean = true;
|
allowDownload?: boolean = true;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
showExif?: boolean = true;
|
showExif?: boolean = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SharedLinkEditDto {
|
export class SharedLinkEditDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional({ nullable: true })
|
||||||
expiresAt?: Date | null;
|
expiresAt?: Date | null;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
allowUpload?: boolean;
|
allowUpload?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
allowDownload?: boolean;
|
allowDownload?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
showExif?: boolean;
|
showExif?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
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, IsOptional, IsString, Max, Min } from 'class-validator';
|
import { IsBoolean, IsEnum, IsNotEmpty, IsNumber, IsString, Max, Min } from 'class-validator';
|
||||||
import { CLIPMode, ModelType } from '../machine-learning.interface';
|
import { CLIPMode, ModelType } from '../machine-learning.interface';
|
||||||
|
import { Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class ModelConfig {
|
export class ModelConfig {
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@ -12,7 +13,7 @@ export class ModelConfig {
|
|||||||
modelName!: string;
|
modelName!: string;
|
||||||
|
|
||||||
@IsEnum(ModelType)
|
@IsEnum(ModelType)
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@ApiProperty({ enumName: 'ModelType', enum: ModelType })
|
@ApiProperty({ enumName: 'ModelType', enum: ModelType })
|
||||||
modelType?: ModelType;
|
modelType?: ModelType;
|
||||||
}
|
}
|
||||||
@ -28,7 +29,7 @@ export class ClassificationConfig extends ModelConfig {
|
|||||||
|
|
||||||
export class CLIPConfig extends ModelConfig {
|
export class CLIPConfig extends ModelConfig {
|
||||||
@IsEnum(CLIPMode)
|
@IsEnum(CLIPMode)
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@ApiProperty({ enumName: 'CLIPMode', enum: CLIPMode })
|
@ApiProperty({ enumName: 'CLIPMode', enum: CLIPMode })
|
||||||
mode?: CLIPMode;
|
mode?: CLIPMode;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { TagType } from '@app/infra/entities';
|
import { TagType } from '@app/infra/entities';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
import { Optional } from '../domain.util';
|
||||||
|
|
||||||
export class CreateTagDto {
|
export class CreateTagDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@ -15,6 +16,6 @@ export class CreateTagDto {
|
|||||||
|
|
||||||
export class UpdateTagDto {
|
export class UpdateTagDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
name?: string;
|
name?: string;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsBoolean, IsEmail, IsNotEmpty, IsString } from 'class-validator';
|
||||||
import { toEmail, toSanitized } from '../../domain.util';
|
import { toEmail, toSanitized, Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class CreateUserDto {
|
export class CreateUserDto {
|
||||||
@IsEmail({ require_tld: false })
|
@IsEmail({ require_tld: false })
|
||||||
@ -19,16 +19,16 @@ export class CreateUserDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
lastName!: string;
|
lastName!: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@Transform(toSanitized)
|
@Transform(toSanitized)
|
||||||
storageLabel?: string | null;
|
storageLabel?: string | null;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
externalPath?: string | null;
|
externalPath?: string | null;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,35 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsEmail, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
|
import { IsBoolean, IsEmail, IsNotEmpty, IsString, IsUUID } from 'class-validator';
|
||||||
import { toEmail, toSanitized } from '../../domain.util';
|
import { toEmail, toSanitized, Optional } from '../../domain.util';
|
||||||
|
|
||||||
export class UpdateUserDto {
|
export class UpdateUserDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsEmail({ require_tld: false })
|
@IsEmail({ require_tld: false })
|
||||||
@Transform(toEmail)
|
@Transform(toEmail)
|
||||||
email?: string;
|
email?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
password?: string;
|
password?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
firstName?: string;
|
firstName?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
lastName?: string;
|
lastName?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
@Transform(toSanitized)
|
@Transform(toSanitized)
|
||||||
storageLabel?: string;
|
storageLabel?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
externalPath?: string;
|
externalPath?: string;
|
||||||
|
|
||||||
@ -38,15 +38,15 @@ export class UpdateUserDto {
|
|||||||
@ApiProperty({ format: 'uuid' })
|
@ApiProperty({ format: 'uuid' })
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
shouldChangePassword?: boolean;
|
shouldChangePassword?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
memoriesEnabled?: boolean;
|
memoriesEnabled?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
import { Optional } from '../../domain.util';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsOptional } from 'class-validator';
|
import { IsBoolean } from 'class-validator';
|
||||||
|
|
||||||
export class UserCountDto {
|
export class UserCountDto {
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(({ value }) => value === 'true')
|
@Transform(({ value }) => value === 'true')
|
||||||
/**
|
/**
|
||||||
* When true, return the number of admins accounts
|
* When true, return the number of admins accounts
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
import { toBoolean } from '@app/domain';
|
import { Optional, toBoolean } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform, Type } from 'class-transformer';
|
import { Transform, Type } from 'class-transformer';
|
||||||
import { IsBoolean, IsDate, IsNotEmpty, IsNumber, IsOptional, IsUUID } from 'class-validator';
|
import { IsBoolean, IsDate, IsNotEmpty, IsNumber, IsUUID } from 'class-validator';
|
||||||
|
|
||||||
export class AssetSearchDto {
|
export class AssetSearchDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
skip?: number;
|
skip?: number;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsUUID('4')
|
@IsUUID('4')
|
||||||
@ApiProperty({ format: 'uuid' })
|
@ApiProperty({ format: 'uuid' })
|
||||||
userId?: string;
|
userId?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsDate()
|
@IsDate()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
updatedAfter?: Date;
|
updatedAfter?: Date;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { toBoolean, toSanitized, UploadFieldName } from '@app/domain';
|
import { Optional, toBoolean, toSanitized, UploadFieldName } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class CreateAssetBase {
|
export class CreateAssetBase {
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@ -19,20 +19,20 @@ export class CreateAssetBase {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
isFavorite!: boolean;
|
isFavorite!: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isVisible?: boolean;
|
isVisible?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
duration?: string;
|
duration?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CreateAssetDto extends CreateAssetBase {
|
export class CreateAssetDto extends CreateAssetBase {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isReadOnly?: boolean = false;
|
isReadOnly?: boolean = false;
|
||||||
@ -50,7 +50,7 @@ export class CreateAssetDto extends CreateAssetBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ImportAssetDto extends CreateAssetBase {
|
export class ImportAssetDto extends CreateAssetBase {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
isReadOnly?: boolean = true;
|
isReadOnly?: boolean = true;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ export class ImportAssetDto extends CreateAssetBase {
|
|||||||
assetPath!: string;
|
assetPath!: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@Transform(toSanitized)
|
@Transform(toSanitized)
|
||||||
sidecarPath?: string;
|
sidecarPath?: string;
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
import { IsNotEmpty, IsOptional } from 'class-validator';
|
|
||||||
|
|
||||||
export class CreateExifDto {
|
|
||||||
@IsNotEmpty()
|
|
||||||
assetId!: string;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
make?: string;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
model?: string;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
exifImageWidth?: number;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
exifImageHeight?: number;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
fileSizeInByte?: number;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
orientation?: string;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
dateTimeOriginal?: Date;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
modifiedDate?: Date;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
lensModel?: string;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
fNumber?: number;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
focalLenght?: number;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
iso?: number;
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
exposureTime?: number;
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
|
import { Optional } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsEnum, IsOptional } from 'class-validator';
|
import { IsEnum } from 'class-validator';
|
||||||
|
|
||||||
export enum GetAssetThumbnailFormatEnum {
|
export enum GetAssetThumbnailFormatEnum {
|
||||||
JPEG = 'JPEG',
|
JPEG = 'JPEG',
|
||||||
@ -7,7 +8,7 @@ export enum GetAssetThumbnailFormatEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class GetAssetThumbnailDto {
|
export class GetAssetThumbnailDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsEnum(GetAssetThumbnailFormatEnum)
|
@IsEnum(GetAssetThumbnailFormatEnum)
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { toBoolean } from '@app/domain';
|
import { Optional, toBoolean } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsOptional } from 'class-validator';
|
import { IsBoolean } from 'class-validator';
|
||||||
|
|
||||||
export class ServeFileDto {
|
export class ServeFileDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
@ApiProperty({ type: Boolean, title: 'Is serve thumbnail (resize) file' })
|
@ApiProperty({ type: Boolean, title: 'Is serve thumbnail (resize) file' })
|
||||||
isThumb?: boolean;
|
isThumb?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@Transform(toBoolean)
|
@Transform(toBoolean)
|
||||||
@ApiProperty({ type: Boolean, title: 'Is request made from web' })
|
@ApiProperty({ type: Boolean, title: 'Is request made from web' })
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
|
import { Optional } from '@app/domain';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsArray, IsBoolean, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class UpdateAssetDto {
|
export class UpdateAssetDto {
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isFavorite?: boolean;
|
isFavorite?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsString({ each: true })
|
@IsString({ each: true })
|
||||||
@IsNotEmpty({ each: true })
|
@IsNotEmpty({ each: true })
|
||||||
@ -26,7 +27,7 @@ export class UpdateAssetDto {
|
|||||||
})
|
})
|
||||||
tagIds?: string[];
|
tagIds?: string[];
|
||||||
|
|
||||||
@IsOptional()
|
@Optional()
|
||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,16 @@ import { AppModule, AuthController } from '@app/immich';
|
|||||||
import { INestApplication } from '@nestjs/common';
|
import { INestApplication } from '@nestjs/common';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
import { deviceStub, errorStub, loginResponseStub, signupResponseStub, signupStub, uuidStub } from '../fixtures';
|
import {
|
||||||
|
changePasswordStub,
|
||||||
|
deviceStub,
|
||||||
|
errorStub,
|
||||||
|
loginResponseStub,
|
||||||
|
loginStub,
|
||||||
|
signupResponseStub,
|
||||||
|
adminSignupStub,
|
||||||
|
uuidStub,
|
||||||
|
} from '../fixtures';
|
||||||
import { api, db } from '../test-utils';
|
import { api, db } from '../test-utils';
|
||||||
|
|
||||||
const firstName = 'Immich';
|
const firstName = 'Immich';
|
||||||
@ -64,7 +73,7 @@ describe(`${AuthController.name} (e2e)`, () => {
|
|||||||
it('should sign up the admin with a local domain', async () => {
|
it('should sign up the admin with a local domain', async () => {
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
.post('/auth/admin-sign-up')
|
.post('/auth/admin-sign-up')
|
||||||
.send({ ...signupStub, email: 'admin@local' });
|
.send({ ...adminSignupStub, email: 'admin@local' });
|
||||||
expect(status).toEqual(201);
|
expect(status).toEqual(201);
|
||||||
expect(body).toEqual({ ...signupResponseStub, email: 'admin@local' });
|
expect(body).toEqual({ ...signupResponseStub, email: 'admin@local' });
|
||||||
});
|
});
|
||||||
@ -72,7 +81,7 @@ describe(`${AuthController.name} (e2e)`, () => {
|
|||||||
it('should transform email to lower case', async () => {
|
it('should transform email to lower case', async () => {
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
.post('/auth/admin-sign-up')
|
.post('/auth/admin-sign-up')
|
||||||
.send({ ...signupStub, email: 'aDmIn@IMMICH.app' });
|
.send({ ...adminSignupStub, email: 'aDmIn@IMMICH.app' });
|
||||||
expect(status).toEqual(201);
|
expect(status).toEqual(201);
|
||||||
expect(body).toEqual(signupResponseStub);
|
expect(body).toEqual(signupResponseStub);
|
||||||
});
|
});
|
||||||
@ -80,11 +89,21 @@ describe(`${AuthController.name} (e2e)`, () => {
|
|||||||
it('should not allow a second admin to sign up', async () => {
|
it('should not allow a second admin to sign up', async () => {
|
||||||
await api.adminSignUp(server);
|
await api.adminSignUp(server);
|
||||||
|
|
||||||
const { status, body } = await request(server).post('/auth/admin-sign-up').send(signupStub);
|
const { status, body } = await request(server).post('/auth/admin-sign-up').send(adminSignupStub);
|
||||||
|
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorStub.alreadyHasAdmin);
|
expect(body).toEqual(errorStub.alreadyHasAdmin);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const key of Object.keys(adminSignupStub)) {
|
||||||
|
it(`should not allow null ${key}`, async () => {
|
||||||
|
const { status, body } = await request(server)
|
||||||
|
.post('/auth/admin-sign-up')
|
||||||
|
.send({ ...adminSignupStub, [key]: null });
|
||||||
|
expect(status).toBe(400);
|
||||||
|
expect(body).toEqual(errorStub.badRequest);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe(`POST /auth/login`, () => {
|
describe(`POST /auth/login`, () => {
|
||||||
@ -94,6 +113,16 @@ describe(`${AuthController.name} (e2e)`, () => {
|
|||||||
expect(status).toBe(401);
|
expect(status).toBe(401);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const key of Object.keys(loginStub.admin)) {
|
||||||
|
it(`should not allow null ${key}`, async () => {
|
||||||
|
const { status, body } = await request(server)
|
||||||
|
.post('/auth/login')
|
||||||
|
.send({ ...loginStub.admin, [key]: null });
|
||||||
|
expect(status).toBe(400);
|
||||||
|
expect(body).toEqual(errorStub.badRequest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should accept a correct password', async () => {
|
it('should accept a correct password', async () => {
|
||||||
const { status, body, headers } = await request(server).post('/auth/login').send({ email, password });
|
const { status, body, headers } = await request(server).post('/auth/login').send({ email, password });
|
||||||
expect(status).toBe(201);
|
expect(status).toBe(201);
|
||||||
@ -183,17 +212,26 @@ describe(`${AuthController.name} (e2e)`, () => {
|
|||||||
|
|
||||||
describe('POST /auth/change-password', () => {
|
describe('POST /auth/change-password', () => {
|
||||||
it('should require authentication', async () => {
|
it('should require authentication', async () => {
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server).post(`/auth/change-password`).send(changePasswordStub);
|
||||||
.post(`/auth/change-password`)
|
|
||||||
.send({ password: 'Password123', newPassword: 'Password1234' });
|
|
||||||
expect(status).toBe(401);
|
expect(status).toBe(401);
|
||||||
expect(body).toEqual(errorStub.unauthorized);
|
expect(body).toEqual(errorStub.unauthorized);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const key of Object.keys(changePasswordStub)) {
|
||||||
|
it(`should not allow null ${key}`, async () => {
|
||||||
|
const { status, body } = await request(server)
|
||||||
|
.post('/auth/change-password')
|
||||||
|
.send({ ...changePasswordStub, [key]: null })
|
||||||
|
.set('Authorization', `Bearer ${accessToken}`);
|
||||||
|
expect(status).toBe(400);
|
||||||
|
expect(body).toEqual(errorStub.badRequest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should require the current password', async () => {
|
it('should require the current password', async () => {
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
.post(`/auth/change-password`)
|
.post(`/auth/change-password`)
|
||||||
.send({ password: 'wrong-password', newPassword: 'Password1234' })
|
.send({ ...changePasswordStub, password: 'wrong-password' })
|
||||||
.set('Authorization', `Bearer ${accessToken}`);
|
.set('Authorization', `Bearer ${accessToken}`);
|
||||||
expect(status).toBe(400);
|
expect(status).toBe(400);
|
||||||
expect(body).toEqual(errorStub.wrongPassword);
|
expect(body).toEqual(errorStub.wrongPassword);
|
||||||
@ -202,7 +240,7 @@ describe(`${AuthController.name} (e2e)`, () => {
|
|||||||
it('should change the password', async () => {
|
it('should change the password', async () => {
|
||||||
const { status } = await request(server)
|
const { status } = await request(server)
|
||||||
.post(`/auth/change-password`)
|
.post(`/auth/change-password`)
|
||||||
.send({ password: 'Password123', newPassword: 'Password1234' })
|
.send(changePasswordStub)
|
||||||
.set('Authorization', `Bearer ${accessToken}`);
|
.set('Authorization', `Bearer ${accessToken}`);
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
|
|
||||||
|
@ -40,7 +40,20 @@ describe(`${PersonController.name}`, () => {
|
|||||||
expect(body).toEqual(errorStub.unauthorized);
|
expect(body).toEqual(errorStub.unauthorized);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not accept invalid dates', async () => {
|
for (const key of ['name', 'featureFaceAssetId', 'isHidden']) {
|
||||||
|
it(`should not allow null ${key}`, async () => {
|
||||||
|
const personRepository = app.get<IPersonRepository>(IPersonRepository);
|
||||||
|
const person = await personRepository.create({ ownerId: loginResponse.userId });
|
||||||
|
const { status, body } = await request(server)
|
||||||
|
.put(`/person/${person.id}`)
|
||||||
|
.set('Authorization', `Bearer ${accessToken}`)
|
||||||
|
.send({ [key]: null });
|
||||||
|
expect(status).toBe(400);
|
||||||
|
expect(body).toEqual(errorStub.badRequest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should not accept invalid birth dates', async () => {
|
||||||
for (const birthDate of [false, 'false', '123567', 123456]) {
|
for (const birthDate of [false, 'false', '123567', 123456]) {
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
.put(`/person/${uuidStub.notFound}`)
|
.put(`/person/${uuidStub.notFound}`)
|
||||||
@ -50,6 +63,7 @@ describe(`${PersonController.name}`, () => {
|
|||||||
expect(body).toEqual(errorStub.badRequest);
|
expect(body).toEqual(errorStub.badRequest);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update a date of birth', async () => {
|
it('should update a date of birth', async () => {
|
||||||
const personRepository = app.get<IPersonRepository>(IPersonRepository);
|
const personRepository = app.get<IPersonRepository>(IPersonRepository);
|
||||||
const person = await personRepository.create({ ownerId: loginResponse.userId });
|
const person = await personRepository.create({ ownerId: loginResponse.userId });
|
||||||
|
@ -3,7 +3,7 @@ import { AppModule, UserController } from '@app/immich';
|
|||||||
import { INestApplication } from '@nestjs/common';
|
import { INestApplication } from '@nestjs/common';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
import { errorStub } from '../fixtures';
|
import { errorStub, userSignupStub, userStub } from '../fixtures';
|
||||||
import { api, db } from '../test-utils';
|
import { api, db } from '../test-utils';
|
||||||
|
|
||||||
describe(`${UserController.name}`, () => {
|
describe(`${UserController.name}`, () => {
|
||||||
@ -118,13 +118,22 @@ describe(`${UserController.name}`, () => {
|
|||||||
|
|
||||||
describe('POST /user', () => {
|
describe('POST /user', () => {
|
||||||
it('should require authentication', async () => {
|
it('should require authentication', async () => {
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server).post(`/user`).send(userSignupStub);
|
||||||
.post(`/user`)
|
|
||||||
.send({ email: 'user1@immich.app', password: 'Password123', firstName: 'Immich', lastName: 'User' });
|
|
||||||
expect(status).toBe(401);
|
expect(status).toBe(401);
|
||||||
expect(body).toEqual(errorStub.unauthorized);
|
expect(body).toEqual(errorStub.unauthorized);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const key of Object.keys(userSignupStub)) {
|
||||||
|
it(`should not allow null ${key}`, async () => {
|
||||||
|
const { status, body } = await request(server)
|
||||||
|
.post(`/user`)
|
||||||
|
.set('Authorization', `Bearer ${accessToken}`)
|
||||||
|
.send({ ...userSignupStub, [key]: null });
|
||||||
|
expect(status).toBe(400);
|
||||||
|
expect(body).toEqual(errorStub.badRequest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should ignore `isAdmin`', async () => {
|
it('should ignore `isAdmin`', async () => {
|
||||||
const { status, body } = await request(server)
|
const { status, body } = await request(server)
|
||||||
.post(`/user`)
|
.post(`/user`)
|
||||||
@ -170,6 +179,17 @@ describe(`${UserController.name}`, () => {
|
|||||||
expect(body).toEqual(errorStub.unauthorized);
|
expect(body).toEqual(errorStub.unauthorized);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const key of Object.keys(userStub.admin)) {
|
||||||
|
it(`should not allow null ${key}`, async () => {
|
||||||
|
const { status, body } = await request(server)
|
||||||
|
.put(`/user`)
|
||||||
|
.set('Authorization', `Bearer ${accessToken}`)
|
||||||
|
.send({ ...userStub.admin, [key]: null });
|
||||||
|
expect(status).toBe(400);
|
||||||
|
expect(body).toEqual(errorStub.badRequest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should not allow a non-admin to become an admin', async () => {
|
it('should not allow a non-admin to become an admin', async () => {
|
||||||
const user = await api.userApi.create(server, accessToken, {
|
const user = await api.userApi.create(server, accessToken, {
|
||||||
email: 'user1@immich.app',
|
email: 'user1@immich.app',
|
||||||
|
12
server/test/fixtures/auth.stub.ts
vendored
12
server/test/fixtures/auth.stub.ts
vendored
@ -1,12 +1,17 @@
|
|||||||
import { AuthUserDto } from '@app/domain';
|
import { AuthUserDto } from '@app/domain';
|
||||||
|
|
||||||
export const signupStub = {
|
export const adminSignupStub = {
|
||||||
firstName: 'Immich',
|
firstName: 'Immich',
|
||||||
lastName: 'Admin',
|
lastName: 'Admin',
|
||||||
email: 'admin@immich.app',
|
email: 'admin@immich.app',
|
||||||
password: 'Password123',
|
password: 'Password123',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const userSignupStub = {
|
||||||
|
...adminSignupStub,
|
||||||
|
memoriesEnabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
export const signupResponseStub = {
|
export const signupResponseStub = {
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
email: 'admin@immich.app',
|
email: 'admin@immich.app',
|
||||||
@ -22,6 +27,11 @@ export const loginStub = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const changePasswordStub = {
|
||||||
|
password: 'Password123',
|
||||||
|
newPassword: 'Password1234',
|
||||||
|
};
|
||||||
|
|
||||||
export const authStub = {
|
export const authStub = {
|
||||||
admin: Object.freeze<AuthUserDto>({
|
admin: Object.freeze<AuthUserDto>({
|
||||||
id: 'admin_id',
|
id: 'admin_id',
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
} from '@app/domain';
|
} from '@app/domain';
|
||||||
import { dataSource } from '@app/infra';
|
import { dataSource } from '@app/infra';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
import { loginResponseStub, loginStub, signupResponseStub, signupStub } from './fixtures';
|
import { loginResponseStub, loginStub, signupResponseStub, adminSignupStub } from './fixtures';
|
||||||
|
|
||||||
export const db = {
|
export const db = {
|
||||||
reset: async () => {
|
reset: async () => {
|
||||||
@ -49,7 +49,7 @@ export function getAuthUser(): AuthUserDto {
|
|||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
adminSignUp: async (server: any) => {
|
adminSignUp: async (server: any) => {
|
||||||
const { status, body } = await request(server).post('/auth/admin-sign-up').send(signupStub);
|
const { status, body } = await request(server).post('/auth/admin-sign-up').send(adminSignupStub);
|
||||||
|
|
||||||
expect(status).toBe(201);
|
expect(status).toBe(201);
|
||||||
expect(body).toEqual(signupResponseStub);
|
expect(body).toEqual(signupResponseStub);
|
||||||
|
4
web/src/api/open-api/api.ts
generated
4
web/src/api/open-api/api.ts
generated
@ -1982,7 +1982,7 @@ export interface PeopleUpdateDto {
|
|||||||
*/
|
*/
|
||||||
export interface PeopleUpdateItem {
|
export interface PeopleUpdateItem {
|
||||||
/**
|
/**
|
||||||
* Person date of birth.
|
* Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof PeopleUpdateItem
|
* @memberof PeopleUpdateItem
|
||||||
*/
|
*/
|
||||||
@ -2056,7 +2056,7 @@ export interface PersonResponseDto {
|
|||||||
*/
|
*/
|
||||||
export interface PersonUpdateDto {
|
export interface PersonUpdateDto {
|
||||||
/**
|
/**
|
||||||
* Person date of birth.
|
* Person date of birth. Note: the mobile app cannot currently set the birth date to null.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof PersonUpdateDto
|
* @memberof PersonUpdateDto
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user