diff --git a/server/src/controllers/system-config.controller.ts b/server/src/controllers/system-config.controller.ts index ca2bbb5f51a71..1fb9dfbea8ec6 100644 --- a/server/src/controllers/system-config.controller.ts +++ b/server/src/controllers/system-config.controller.ts @@ -1,8 +1,6 @@ import { Body, Controller, Get, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { MapThemeDto } from 'src/dtos/system-config-map-theme.dto'; -import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config-storage-template.dto'; -import { SystemConfigDto } from 'src/dtos/system-config.dto'; +import { MapThemeDto, SystemConfigDto, SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config.dto'; import { AdminRoute, Authenticated } from 'src/middleware/auth.guard'; import { SystemConfigService } from 'src/services/system-config.service'; diff --git a/server/src/dtos/server-info.dto.ts b/server/src/dtos/server-info.dto.ts index cce0de59a6173..497b7ab5e1651 100644 --- a/server/src/dtos/server-info.dto.ts +++ b/server/src/dtos/server-info.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'; import type { DateTime } from 'luxon'; import { FeatureFlags } from 'src/cores/system-config.core'; -import { SystemConfigThemeDto } from 'src/dtos/system-config-theme.dto'; +import { SystemConfigThemeDto } from 'src/dtos/system-config.dto'; import { IVersion, VersionType } from 'src/utils/version'; export class ServerPingResponse { diff --git a/server/src/dtos/system-config-ffmpeg.dto.ts b/server/src/dtos/system-config-ffmpeg.dto.ts deleted file mode 100644 index 017f69c2db6ad..0000000000000 --- a/server/src/dtos/system-config-ffmpeg.dto.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsEnum, IsInt, IsString, Max, Min } from 'class-validator'; -import { - AudioCodec, - CQMode, - ToneMapping, - TranscodeHWAccel, - TranscodePolicy, - VideoCodec, -} from 'src/entities/system-config.entity'; -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigFFmpegDto { - @IsInt() - @Min(0) - @Max(51) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - crf!: number; - - @IsInt() - @Min(0) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - threads!: number; - - @IsString() - preset!: string; - - @IsEnum(VideoCodec) - @ApiProperty({ enumName: 'VideoCodec', enum: VideoCodec }) - targetVideoCodec!: VideoCodec; - - @IsEnum(VideoCodec, { each: true }) - @ApiProperty({ enumName: 'VideoCodec', enum: VideoCodec, isArray: true }) - acceptedVideoCodecs!: VideoCodec[]; - - @IsEnum(AudioCodec) - @ApiProperty({ enumName: 'AudioCodec', enum: AudioCodec }) - targetAudioCodec!: AudioCodec; - - @IsEnum(AudioCodec, { each: true }) - @ApiProperty({ enumName: 'AudioCodec', enum: AudioCodec, isArray: true }) - acceptedAudioCodecs!: AudioCodec[]; - - @IsString() - targetResolution!: string; - - @IsString() - maxBitrate!: string; - - @IsInt() - @Min(-1) - @Max(16) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - bframes!: number; - - @IsInt() - @Min(0) - @Max(6) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - refs!: number; - - @IsInt() - @Min(0) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - gopSize!: number; - - @IsInt() - @Min(0) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - npl!: number; - - @ValidateBoolean() - temporalAQ!: boolean; - - @IsEnum(CQMode) - @ApiProperty({ enumName: 'CQMode', enum: CQMode }) - cqMode!: CQMode; - - @ValidateBoolean() - twoPass!: boolean; - - @IsString() - preferredHwDevice!: string; - - @IsEnum(TranscodePolicy) - @ApiProperty({ enumName: 'TranscodePolicy', enum: TranscodePolicy }) - transcode!: TranscodePolicy; - - @IsEnum(TranscodeHWAccel) - @ApiProperty({ enumName: 'TranscodeHWAccel', enum: TranscodeHWAccel }) - accel!: TranscodeHWAccel; - - @IsEnum(ToneMapping) - @ApiProperty({ enumName: 'ToneMapping', enum: ToneMapping }) - tonemap!: ToneMapping; -} diff --git a/server/src/dtos/system-config-job.dto.ts b/server/src/dtos/system-config-job.dto.ts deleted file mode 100644 index 2dc5404df1b81..0000000000000 --- a/server/src/dtos/system-config-job.dto.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator'; -import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface'; - -export class JobSettingsDto { - @IsInt() - @IsPositive() - @ApiProperty({ type: 'integer' }) - concurrency!: number; -} - -export class SystemConfigJobDto implements Record { - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.THUMBNAIL_GENERATION]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.METADATA_EXTRACTION]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.VIDEO_CONVERSION]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.SMART_SEARCH]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.MIGRATION]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.BACKGROUND_TASK]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.SEARCH]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.FACE_DETECTION]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.SIDECAR]!: JobSettingsDto; - - @ApiProperty({ type: JobSettingsDto }) - @ValidateNested() - @IsObject() - @Type(() => JobSettingsDto) - [QueueName.LIBRARY]!: JobSettingsDto; -} diff --git a/server/src/dtos/system-config-library.dto.ts b/server/src/dtos/system-config-library.dto.ts deleted file mode 100644 index 8c7501ae40b10..0000000000000 --- a/server/src/dtos/system-config-library.dto.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Type } from 'class-transformer'; -import { - IsNotEmpty, - IsObject, - IsString, - Validate, - ValidateIf, - ValidateNested, - ValidatorConstraint, - ValidatorConstraintInterface, -} from 'class-validator'; -import { ValidateBoolean, validateCronExpression } from 'src/validation'; - -const isEnabled = (config: SystemConfigLibraryScanDto) => config.enabled; - -@ValidatorConstraint({ name: 'cronValidator' }) -class CronValidator implements ValidatorConstraintInterface { - validate(expression: string): boolean { - return validateCronExpression(expression); - } -} - -export class SystemConfigLibraryScanDto { - @ValidateBoolean() - enabled!: boolean; - - @ValidateIf(isEnabled) - @IsNotEmpty() - @Validate(CronValidator, { message: 'Invalid cron expression' }) - @IsString() - cronExpression!: string; -} - -export class SystemConfigLibraryWatchDto { - @ValidateBoolean() - enabled!: boolean; -} - -export class SystemConfigLibraryDto { - @Type(() => SystemConfigLibraryScanDto) - @ValidateNested() - @IsObject() - scan!: SystemConfigLibraryScanDto; - - @Type(() => SystemConfigLibraryWatchDto) - @ValidateNested() - @IsObject() - watch!: SystemConfigLibraryWatchDto; -} diff --git a/server/src/dtos/system-config-logging.dto.ts b/server/src/dtos/system-config-logging.dto.ts deleted file mode 100644 index 53ef5d2f0f652..0000000000000 --- a/server/src/dtos/system-config-logging.dto.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum } from 'class-validator'; -import { LogLevel } from 'src/entities/system-config.entity'; -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigLoggingDto { - @ValidateBoolean() - enabled!: boolean; - - @ApiProperty({ enum: LogLevel, enumName: 'LogLevel' }) - @IsEnum(LogLevel) - level!: LogLevel; -} diff --git a/server/src/dtos/system-config-machine-learning.dto.ts b/server/src/dtos/system-config-machine-learning.dto.ts deleted file mode 100644 index 7abc9ac88c699..0000000000000 --- a/server/src/dtos/system-config-machine-learning.dto.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Type } from 'class-transformer'; -import { IsObject, IsUrl, ValidateIf, ValidateNested } from 'class-validator'; -import { CLIPConfig, RecognitionConfig } from 'src/dtos/model-config.dto'; -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigMachineLearningDto { - @ValidateBoolean() - enabled!: boolean; - - @IsUrl({ require_tld: false, allow_underscores: true }) - @ValidateIf((dto) => dto.enabled) - url!: string; - - @Type(() => CLIPConfig) - @ValidateNested() - @IsObject() - clip!: CLIPConfig; - - @Type(() => RecognitionConfig) - @ValidateNested() - @IsObject() - facialRecognition!: RecognitionConfig; -} diff --git a/server/src/dtos/system-config-map-theme.dto.ts b/server/src/dtos/system-config-map-theme.dto.ts deleted file mode 100644 index 9286d8d235cb0..0000000000000 --- a/server/src/dtos/system-config-map-theme.dto.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum } from 'class-validator'; - -export enum MapTheme { - LIGHT = 'light', - DARK = 'dark', -} - -export class MapThemeDto { - @IsEnum(MapTheme) - @ApiProperty({ enum: MapTheme, enumName: 'MapTheme' }) - theme!: MapTheme; -} diff --git a/server/src/dtos/system-config-map.dto.ts b/server/src/dtos/system-config-map.dto.ts deleted file mode 100644 index 9ec0abfa4ec14..0000000000000 --- a/server/src/dtos/system-config-map.dto.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { IsString } from 'class-validator'; -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigMapDto { - @ValidateBoolean() - enabled!: boolean; - - @IsString() - lightStyle!: string; - - @IsString() - darkStyle!: string; -} diff --git a/server/src/dtos/system-config-new-version-check.dto.ts b/server/src/dtos/system-config-new-version-check.dto.ts deleted file mode 100644 index 7d5c5134f2466..0000000000000 --- a/server/src/dtos/system-config-new-version-check.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigNewVersionCheckDto { - @ValidateBoolean() - enabled!: boolean; -} diff --git a/server/src/dtos/system-config-oauth.dto.ts b/server/src/dtos/system-config-oauth.dto.ts deleted file mode 100644 index 9c7fc5f408591..0000000000000 --- a/server/src/dtos/system-config-oauth.dto.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { IsNotEmpty, IsNumber, IsString, IsUrl, Min, ValidateIf } from 'class-validator'; -import { ValidateBoolean } from 'src/validation'; - -const isEnabled = (config: SystemConfigOAuthDto) => config.enabled; -const isOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled; - -export class SystemConfigOAuthDto { - @ValidateBoolean() - autoLaunch!: boolean; - - @ValidateBoolean() - autoRegister!: boolean; - - @IsString() - buttonText!: string; - - @ValidateIf(isEnabled) - @IsNotEmpty() - @IsString() - clientId!: string; - - @ValidateIf(isEnabled) - @IsNotEmpty() - @IsString() - clientSecret!: string; - - @IsNumber() - @Min(0) - defaultStorageQuota!: number; - - @ValidateBoolean() - enabled!: boolean; - - @ValidateIf(isEnabled) - @IsNotEmpty() - @IsString() - issuerUrl!: string; - - @ValidateBoolean() - mobileOverrideEnabled!: boolean; - - @ValidateIf(isOverrideEnabled) - @IsUrl() - mobileRedirectUri!: string; - - @IsString() - scope!: string; - - @IsString() - @IsNotEmpty() - signingAlgorithm!: string; - - @IsString() - storageLabelClaim!: string; - - @IsString() - storageQuotaClaim!: string; -} diff --git a/server/src/dtos/system-config-password-login.dto.ts b/server/src/dtos/system-config-password-login.dto.ts deleted file mode 100644 index 8d49a7002d37c..0000000000000 --- a/server/src/dtos/system-config-password-login.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigPasswordLoginDto { - @ValidateBoolean() - enabled!: boolean; -} diff --git a/server/src/dtos/system-config-reverse-geocoding.dto.ts b/server/src/dtos/system-config-reverse-geocoding.dto.ts deleted file mode 100644 index 8ff28660123ee..0000000000000 --- a/server/src/dtos/system-config-reverse-geocoding.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigReverseGeocodingDto { - @ValidateBoolean() - enabled!: boolean; -} diff --git a/server/src/dtos/system-config-server.dto.ts b/server/src/dtos/system-config-server.dto.ts deleted file mode 100644 index 83a2b0df9b604..0000000000000 --- a/server/src/dtos/system-config-server.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsString } from 'class-validator'; - -export class SystemConfigServerDto { - @IsString() - externalDomain!: string; - - @IsString() - loginPageMessage!: string; -} diff --git a/server/src/dtos/system-config-storage-template.dto.ts b/server/src/dtos/system-config-storage-template.dto.ts deleted file mode 100644 index d56cfedb8038c..0000000000000 --- a/server/src/dtos/system-config-storage-template.dto.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { IsNotEmpty, IsString } from 'class-validator'; -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigStorageTemplateDto { - @ValidateBoolean() - enabled!: boolean; - - @ValidateBoolean() - hashVerificationEnabled!: boolean; - - @IsNotEmpty() - @IsString() - template!: string; -} - -export class SystemConfigTemplateStorageOptionDto { - yearOptions!: string[]; - monthOptions!: string[]; - weekOptions!: string[]; - dayOptions!: string[]; - hourOptions!: string[]; - minuteOptions!: string[]; - secondOptions!: string[]; - presetOptions!: string[]; -} diff --git a/server/src/dtos/system-config-theme.dto.ts b/server/src/dtos/system-config-theme.dto.ts deleted file mode 100644 index f47b51e0e177a..0000000000000 --- a/server/src/dtos/system-config-theme.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IsString } from 'class-validator'; - -export class SystemConfigThemeDto { - @IsString() - customCss!: string; -} diff --git a/server/src/dtos/system-config-thumbnail.dto.ts b/server/src/dtos/system-config-thumbnail.dto.ts deleted file mode 100644 index d3240efb12b61..0000000000000 --- a/server/src/dtos/system-config-thumbnail.dto.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsEnum, IsInt, Max, Min } from 'class-validator'; -import { Colorspace } from 'src/entities/system-config.entity'; - -export class SystemConfigThumbnailDto { - @IsInt() - @Min(1) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - webpSize!: number; - - @IsInt() - @Min(1) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - jpegSize!: number; - - @IsInt() - @Min(1) - @Max(100) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - quality!: number; - - @IsEnum(Colorspace) - @ApiProperty({ enumName: 'Colorspace', enum: Colorspace }) - colorspace!: Colorspace; -} diff --git a/server/src/dtos/system-config-trash.dto.ts b/server/src/dtos/system-config-trash.dto.ts deleted file mode 100644 index a9e5483ebfbb3..0000000000000 --- a/server/src/dtos/system-config-trash.dto.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsInt, Min } from 'class-validator'; -import { ValidateBoolean } from 'src/validation'; - -export class SystemConfigTrashDto { - @ValidateBoolean() - enabled!: boolean; - - @IsInt() - @Min(0) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - days!: number; -} diff --git a/server/src/dtos/system-config-user.dto.ts b/server/src/dtos/system-config-user.dto.ts deleted file mode 100644 index 22d6ef5fc375e..0000000000000 --- a/server/src/dtos/system-config-user.dto.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsInt, Min } from 'class-validator'; - -export class SystemConfigUserDto { - @IsInt() - @Min(1) - @Type(() => Number) - @ApiProperty({ type: 'integer' }) - deleteDelay!: number; -} diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index 7c32376293f45..740f1672ee8b4 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -1,22 +1,433 @@ +import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; -import { IsObject, ValidateNested } from 'class-validator'; -import { SystemConfigFFmpegDto } from 'src/dtos/system-config-ffmpeg.dto'; -import { SystemConfigJobDto } from 'src/dtos/system-config-job.dto'; -import { SystemConfigLibraryDto } from 'src/dtos/system-config-library.dto'; -import { SystemConfigLoggingDto } from 'src/dtos/system-config-logging.dto'; -import { SystemConfigMachineLearningDto } from 'src/dtos/system-config-machine-learning.dto'; -import { SystemConfigMapDto } from 'src/dtos/system-config-map.dto'; -import { SystemConfigNewVersionCheckDto } from 'src/dtos/system-config-new-version-check.dto'; -import { SystemConfigOAuthDto } from 'src/dtos/system-config-oauth.dto'; -import { SystemConfigPasswordLoginDto } from 'src/dtos/system-config-password-login.dto'; -import { SystemConfigReverseGeocodingDto } from 'src/dtos/system-config-reverse-geocoding.dto'; -import { SystemConfigServerDto } from 'src/dtos/system-config-server.dto'; -import { SystemConfigStorageTemplateDto } from 'src/dtos/system-config-storage-template.dto'; -import { SystemConfigThemeDto } from 'src/dtos/system-config-theme.dto'; -import { SystemConfigThumbnailDto } from 'src/dtos/system-config-thumbnail.dto'; -import { SystemConfigTrashDto } from 'src/dtos/system-config-trash.dto'; -import { SystemConfigUserDto } from 'src/dtos/system-config-user.dto'; -import { SystemConfig } from 'src/entities/system-config.entity'; +import { + IsEnum, + IsInt, + IsNotEmpty, + IsNumber, + IsObject, + IsPositive, + IsString, + IsUrl, + Max, + Min, + Validate, + ValidateIf, + ValidateNested, + ValidatorConstraint, + ValidatorConstraintInterface, +} from 'class-validator'; +import { CLIPConfig, RecognitionConfig } from 'src/dtos/model-config.dto'; +import { + AudioCodec, + CQMode, + Colorspace, + LogLevel, + SystemConfig, + ToneMapping, + TranscodeHWAccel, + TranscodePolicy, + VideoCodec, +} from 'src/entities/system-config.entity'; +import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface'; +import { ValidateBoolean, validateCronExpression } from 'src/validation'; + +@ValidatorConstraint({ name: 'cronValidator' }) +class CronValidator implements ValidatorConstraintInterface { + validate(expression: string): boolean { + return validateCronExpression(expression); + } +} + +const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled; +const isOAuthEnabled = (config: SystemConfigOAuthDto) => config.enabled; +const isOAuthOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled; + +export class SystemConfigFFmpegDto { + @IsInt() + @Min(0) + @Max(51) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + crf!: number; + + @IsInt() + @Min(0) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + threads!: number; + + @IsString() + preset!: string; + + @IsEnum(VideoCodec) + @ApiProperty({ enumName: 'VideoCodec', enum: VideoCodec }) + targetVideoCodec!: VideoCodec; + + @IsEnum(VideoCodec, { each: true }) + @ApiProperty({ enumName: 'VideoCodec', enum: VideoCodec, isArray: true }) + acceptedVideoCodecs!: VideoCodec[]; + + @IsEnum(AudioCodec) + @ApiProperty({ enumName: 'AudioCodec', enum: AudioCodec }) + targetAudioCodec!: AudioCodec; + + @IsEnum(AudioCodec, { each: true }) + @ApiProperty({ enumName: 'AudioCodec', enum: AudioCodec, isArray: true }) + acceptedAudioCodecs!: AudioCodec[]; + + @IsString() + targetResolution!: string; + + @IsString() + maxBitrate!: string; + + @IsInt() + @Min(-1) + @Max(16) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + bframes!: number; + + @IsInt() + @Min(0) + @Max(6) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + refs!: number; + + @IsInt() + @Min(0) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + gopSize!: number; + + @IsInt() + @Min(0) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + npl!: number; + + @ValidateBoolean() + temporalAQ!: boolean; + + @IsEnum(CQMode) + @ApiProperty({ enumName: 'CQMode', enum: CQMode }) + cqMode!: CQMode; + + @ValidateBoolean() + twoPass!: boolean; + + @IsString() + preferredHwDevice!: string; + + @IsEnum(TranscodePolicy) + @ApiProperty({ enumName: 'TranscodePolicy', enum: TranscodePolicy }) + transcode!: TranscodePolicy; + + @IsEnum(TranscodeHWAccel) + @ApiProperty({ enumName: 'TranscodeHWAccel', enum: TranscodeHWAccel }) + accel!: TranscodeHWAccel; + + @IsEnum(ToneMapping) + @ApiProperty({ enumName: 'ToneMapping', enum: ToneMapping }) + tonemap!: ToneMapping; +} + +class JobSettingsDto { + @IsInt() + @IsPositive() + @ApiProperty({ type: 'integer' }) + concurrency!: number; +} + +class SystemConfigJobDto implements Record { + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.THUMBNAIL_GENERATION]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.METADATA_EXTRACTION]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.VIDEO_CONVERSION]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.SMART_SEARCH]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.MIGRATION]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.BACKGROUND_TASK]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.SEARCH]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.FACE_DETECTION]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.SIDECAR]!: JobSettingsDto; + + @ApiProperty({ type: JobSettingsDto }) + @ValidateNested() + @IsObject() + @Type(() => JobSettingsDto) + [QueueName.LIBRARY]!: JobSettingsDto; +} + +class SystemConfigLibraryScanDto { + @ValidateBoolean() + enabled!: boolean; + + @ValidateIf(isLibraryScanEnabled) + @IsNotEmpty() + @Validate(CronValidator, { message: 'Invalid cron expression' }) + @IsString() + cronExpression!: string; +} + +class SystemConfigLibraryWatchDto { + @ValidateBoolean() + enabled!: boolean; +} + +class SystemConfigLibraryDto { + @Type(() => SystemConfigLibraryScanDto) + @ValidateNested() + @IsObject() + scan!: SystemConfigLibraryScanDto; + + @Type(() => SystemConfigLibraryWatchDto) + @ValidateNested() + @IsObject() + watch!: SystemConfigLibraryWatchDto; +} + +class SystemConfigLoggingDto { + @ValidateBoolean() + enabled!: boolean; + + @ApiProperty({ enum: LogLevel, enumName: 'LogLevel' }) + @IsEnum(LogLevel) + level!: LogLevel; +} + +class SystemConfigMachineLearningDto { + @ValidateBoolean() + enabled!: boolean; + + @IsUrl({ require_tld: false, allow_underscores: true }) + @ValidateIf((dto) => dto.enabled) + url!: string; + + @Type(() => CLIPConfig) + @ValidateNested() + @IsObject() + clip!: CLIPConfig; + + @Type(() => RecognitionConfig) + @ValidateNested() + @IsObject() + facialRecognition!: RecognitionConfig; +} + +enum MapTheme { + LIGHT = 'light', + DARK = 'dark', +} + +export class MapThemeDto { + @IsEnum(MapTheme) + @ApiProperty({ enum: MapTheme, enumName: 'MapTheme' }) + theme!: MapTheme; +} + +class SystemConfigMapDto { + @ValidateBoolean() + enabled!: boolean; + + @IsString() + lightStyle!: string; + + @IsString() + darkStyle!: string; +} + +class SystemConfigNewVersionCheckDto { + @ValidateBoolean() + enabled!: boolean; +} + +class SystemConfigOAuthDto { + @ValidateBoolean() + autoLaunch!: boolean; + + @ValidateBoolean() + autoRegister!: boolean; + + @IsString() + buttonText!: string; + + @ValidateIf(isOAuthEnabled) + @IsNotEmpty() + @IsString() + clientId!: string; + + @ValidateIf(isOAuthEnabled) + @IsNotEmpty() + @IsString() + clientSecret!: string; + + @IsNumber() + @Min(0) + defaultStorageQuota!: number; + + @ValidateBoolean() + enabled!: boolean; + + @ValidateIf(isOAuthEnabled) + @IsNotEmpty() + @IsString() + issuerUrl!: string; + + @ValidateBoolean() + mobileOverrideEnabled!: boolean; + + @ValidateIf(isOAuthOverrideEnabled) + @IsUrl() + mobileRedirectUri!: string; + + @IsString() + scope!: string; + + @IsString() + @IsNotEmpty() + signingAlgorithm!: string; + + @IsString() + storageLabelClaim!: string; + + @IsString() + storageQuotaClaim!: string; +} + +class SystemConfigPasswordLoginDto { + @ValidateBoolean() + enabled!: boolean; +} + +class SystemConfigReverseGeocodingDto { + @ValidateBoolean() + enabled!: boolean; +} + +class SystemConfigServerDto { + @IsString() + externalDomain!: string; + + @IsString() + loginPageMessage!: string; +} + +class SystemConfigStorageTemplateDto { + @ValidateBoolean() + enabled!: boolean; + + @ValidateBoolean() + hashVerificationEnabled!: boolean; + + @IsNotEmpty() + @IsString() + template!: string; +} + +export class SystemConfigTemplateStorageOptionDto { + yearOptions!: string[]; + monthOptions!: string[]; + weekOptions!: string[]; + dayOptions!: string[]; + hourOptions!: string[]; + minuteOptions!: string[]; + secondOptions!: string[]; + presetOptions!: string[]; +} + +export class SystemConfigThemeDto { + @IsString() + customCss!: string; +} + +class SystemConfigThumbnailDto { + @IsInt() + @Min(1) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + webpSize!: number; + + @IsInt() + @Min(1) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + jpegSize!: number; + + @IsInt() + @Min(1) + @Max(100) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + quality!: number; + + @IsEnum(Colorspace) + @ApiProperty({ enumName: 'Colorspace', enum: Colorspace }) + colorspace!: Colorspace; +} + +class SystemConfigTrashDto { + @ValidateBoolean() + enabled!: boolean; + + @IsInt() + @Min(0) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + days!: number; +} + +class SystemConfigUserDto { + @IsInt() + @Min(1) + @Type(() => Number) + @ApiProperty({ type: 'integer' }) + deleteDelay!: number; +} export class SystemConfigDto implements SystemConfig { @Type(() => SystemConfigFFmpegDto) diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index d0850fd12aced..26aa2dce9f3f6 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -1,7 +1,7 @@ import { Inject, Injectable, UnsupportedMediaTypeException } from '@nestjs/common'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { SystemConfigFFmpegDto } from 'src/dtos/system-config-ffmpeg.dto'; +import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { AssetPathType } from 'src/entities/move.entity'; import { diff --git a/server/src/services/system-config.service.ts b/server/src/services/system-config.service.ts index 0067832a16ec2..5842342db6252 100644 --- a/server/src/services/system-config.service.ts +++ b/server/src/services/system-config.service.ts @@ -13,8 +13,7 @@ import { } from 'src/constants'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { OnEventInternal } from 'src/decorators'; -import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config-storage-template.dto'; -import { SystemConfigDto, mapConfig } from 'src/dtos/system-config.dto'; +import { SystemConfigDto, SystemConfigTemplateStorageOptionDto, mapConfig } from 'src/dtos/system-config.dto'; import { LogLevel, SystemConfig } from 'src/entities/system-config.entity'; import { ClientEvent, diff --git a/server/src/utils/media.ts b/server/src/utils/media.ts index f66eee6a5c707..5f1218766a5e7 100644 --- a/server/src/utils/media.ts +++ b/server/src/utils/media.ts @@ -1,4 +1,4 @@ -import { SystemConfigFFmpegDto } from 'src/dtos/system-config-ffmpeg.dto'; +import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto'; import { CQMode, ToneMapping, TranscodeHWAccel, TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity'; import { AudioStreamInfo,