mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:27:09 -05:00 
			
		
		
		
	feat(server): improve validation in controllers (#2149)
* feat(server): improve validation in controllers * set ValidationPipe config with decorator
This commit is contained in:
		
							parent
							
								
									ed551500e7
								
							
						
					
					
						commit
						c584791b65
					
				@ -1,14 +1,15 @@
 | 
				
			|||||||
import { AlbumService, AuthUserDto } from '@app/domain';
 | 
					import { AlbumService, AuthUserDto } from '@app/domain';
 | 
				
			||||||
import { GetAlbumsDto } from '@app/domain/album/dto/get-albums.dto';
 | 
					import { GetAlbumsDto } from '@app/domain/album/dto/get-albums.dto';
 | 
				
			||||||
import { Controller, Get, Query, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Controller, Get, Query } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
					import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('Album')
 | 
					@ApiTags('Album')
 | 
				
			||||||
@Controller('album')
 | 
					@Controller('album')
 | 
				
			||||||
@Authenticated()
 | 
					@Authenticated()
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class AlbumController {
 | 
					export class AlbumController {
 | 
				
			||||||
  constructor(private service: AlbumService) {}
 | 
					  constructor(private service: AlbumService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -6,15 +6,16 @@ import {
 | 
				
			|||||||
  APIKeyUpdateDto,
 | 
					  APIKeyUpdateDto,
 | 
				
			||||||
  AuthUserDto,
 | 
					  AuthUserDto,
 | 
				
			||||||
} from '@app/domain';
 | 
					} from '@app/domain';
 | 
				
			||||||
import { Body, Controller, Delete, Get, Param, Post, Put, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
					import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('API Key')
 | 
					@ApiTags('API Key')
 | 
				
			||||||
@Controller('api-key')
 | 
					@Controller('api-key')
 | 
				
			||||||
@Authenticated()
 | 
					@Authenticated()
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class APIKeyController {
 | 
					export class APIKeyController {
 | 
				
			||||||
  constructor(private service: APIKeyService) {}
 | 
					  constructor(private service: APIKeyService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,15 +13,16 @@ import {
 | 
				
			|||||||
  UserResponseDto,
 | 
					  UserResponseDto,
 | 
				
			||||||
  ValidateAccessTokenResponseDto,
 | 
					  ValidateAccessTokenResponseDto,
 | 
				
			||||||
} from '@app/domain';
 | 
					} from '@app/domain';
 | 
				
			||||||
import { Body, Controller, Ip, Post, Req, Res, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Body, Controller, Ip, Post, Req, Res } from '@nestjs/common';
 | 
				
			||||||
import { ApiBadRequestResponse, ApiTags } from '@nestjs/swagger';
 | 
					import { ApiBadRequestResponse, ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { Request, Response } from 'express';
 | 
					import { Request, Response } from 'express';
 | 
				
			||||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
					import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('Authentication')
 | 
					@ApiTags('Authentication')
 | 
				
			||||||
@Controller('auth')
 | 
					@Controller('auth')
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class AuthController {
 | 
					export class AuthController {
 | 
				
			||||||
  constructor(private readonly service: AuthService) {}
 | 
					  constructor(private readonly service: AuthService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,15 +4,16 @@ import {
 | 
				
			|||||||
  DeviceInfoService,
 | 
					  DeviceInfoService,
 | 
				
			||||||
  UpsertDeviceInfoDto as UpsertDto,
 | 
					  UpsertDeviceInfoDto as UpsertDto,
 | 
				
			||||||
} from '@app/domain';
 | 
					} from '@app/domain';
 | 
				
			||||||
import { Body, Controller, Put, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Body, Controller, Put } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
					import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('Device Info')
 | 
					@ApiTags('Device Info')
 | 
				
			||||||
@Controller('device-info')
 | 
					@Controller('device-info')
 | 
				
			||||||
@Authenticated()
 | 
					@Authenticated()
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class DeviceInfoController {
 | 
					export class DeviceInfoController {
 | 
				
			||||||
  constructor(private readonly service: DeviceInfoService) {}
 | 
					  constructor(private readonly service: DeviceInfoService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,13 @@
 | 
				
			|||||||
import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto, JobIdDto, JobService } from '@app/domain';
 | 
					import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto, JobIdDto, JobService } from '@app/domain';
 | 
				
			||||||
import { Body, Controller, Get, Param, Put, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Body, Controller, Get, Param, Put } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('Job')
 | 
					@ApiTags('Job')
 | 
				
			||||||
@Controller('jobs')
 | 
					@Controller('jobs')
 | 
				
			||||||
@Authenticated({ admin: true })
 | 
					@Authenticated({ admin: true })
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class JobController {
 | 
					export class JobController {
 | 
				
			||||||
  constructor(private service: JobService) {}
 | 
					  constructor(private service: JobService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,15 +7,16 @@ import {
 | 
				
			|||||||
  OAuthService,
 | 
					  OAuthService,
 | 
				
			||||||
  UserResponseDto,
 | 
					  UserResponseDto,
 | 
				
			||||||
} from '@app/domain';
 | 
					} from '@app/domain';
 | 
				
			||||||
import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { Request, Response } from 'express';
 | 
					import { Request, Response } from 'express';
 | 
				
			||||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
					import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('OAuth')
 | 
					@ApiTags('OAuth')
 | 
				
			||||||
@Controller('oauth')
 | 
					@Controller('oauth')
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class OAuthController {
 | 
					export class OAuthController {
 | 
				
			||||||
  constructor(private service: OAuthService) {}
 | 
					  constructor(private service: OAuthService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -6,15 +6,16 @@ import {
 | 
				
			|||||||
  SearchResponseDto,
 | 
					  SearchResponseDto,
 | 
				
			||||||
  SearchService,
 | 
					  SearchService,
 | 
				
			||||||
} from '@app/domain';
 | 
					} from '@app/domain';
 | 
				
			||||||
import { Controller, Get, Query, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Controller, Get, Query } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
					import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('Search')
 | 
					@ApiTags('Search')
 | 
				
			||||||
@Controller('search')
 | 
					@Controller('search')
 | 
				
			||||||
@Authenticated()
 | 
					@Authenticated()
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class SearchController {
 | 
					export class SearchController {
 | 
				
			||||||
  constructor(private service: SearchService) {}
 | 
					  constructor(private service: SearchService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,13 +5,14 @@ import {
 | 
				
			|||||||
  ServerStatsResponseDto,
 | 
					  ServerStatsResponseDto,
 | 
				
			||||||
  ServerVersionReponseDto,
 | 
					  ServerVersionReponseDto,
 | 
				
			||||||
} from '@app/domain';
 | 
					} from '@app/domain';
 | 
				
			||||||
import { Controller, Get, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Controller, Get } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('Server Info')
 | 
					@ApiTags('Server Info')
 | 
				
			||||||
@Controller('server-info')
 | 
					@Controller('server-info')
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class ServerInfoController {
 | 
					export class ServerInfoController {
 | 
				
			||||||
  constructor(private service: ServerInfoService) {}
 | 
					  constructor(private service: ServerInfoService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,13 @@
 | 
				
			|||||||
import { AuthUserDto, EditSharedLinkDto, SharedLinkResponseDto, ShareService } from '@app/domain';
 | 
					import { AuthUserDto, EditSharedLinkDto, SharedLinkResponseDto, ShareService } from '@app/domain';
 | 
				
			||||||
import { Body, Controller, Delete, Get, Param, Patch, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Body, Controller, Delete, Get, Param, Patch } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
					import { GetAuthUser } from '../decorators/auth-user.decorator';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('share')
 | 
					@ApiTags('share')
 | 
				
			||||||
@Controller('share')
 | 
					@Controller('share')
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class ShareController {
 | 
					export class ShareController {
 | 
				
			||||||
  constructor(private readonly service: ShareService) {}
 | 
					  constructor(private readonly service: ShareService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,13 @@
 | 
				
			|||||||
import { SystemConfigDto, SystemConfigService, SystemConfigTemplateStorageOptionDto } from '@app/domain';
 | 
					import { SystemConfigDto, SystemConfigService, SystemConfigTemplateStorageOptionDto } from '@app/domain';
 | 
				
			||||||
import { Body, Controller, Get, Put, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
					import { Body, Controller, Get, Put } from '@nestjs/common';
 | 
				
			||||||
import { ApiTags } from '@nestjs/swagger';
 | 
					import { ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('System Config')
 | 
					@ApiTags('System Config')
 | 
				
			||||||
@Controller('system-config')
 | 
					@Controller('system-config')
 | 
				
			||||||
@Authenticated({ admin: true })
 | 
					@Authenticated({ admin: true })
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class SystemConfigController {
 | 
					export class SystemConfigController {
 | 
				
			||||||
  constructor(private readonly service: SystemConfigService) {}
 | 
					  constructor(private readonly service: SystemConfigService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,6 @@ import {
 | 
				
			|||||||
  Delete,
 | 
					  Delete,
 | 
				
			||||||
  Body,
 | 
					  Body,
 | 
				
			||||||
  Param,
 | 
					  Param,
 | 
				
			||||||
  ValidationPipe,
 | 
					 | 
				
			||||||
  Put,
 | 
					  Put,
 | 
				
			||||||
  Query,
 | 
					  Query,
 | 
				
			||||||
  UseInterceptors,
 | 
					  UseInterceptors,
 | 
				
			||||||
@ -13,7 +12,6 @@ import {
 | 
				
			|||||||
  Response,
 | 
					  Response,
 | 
				
			||||||
  StreamableFile,
 | 
					  StreamableFile,
 | 
				
			||||||
  Header,
 | 
					  Header,
 | 
				
			||||||
  UsePipes,
 | 
					 | 
				
			||||||
} from '@nestjs/common';
 | 
					} from '@nestjs/common';
 | 
				
			||||||
import { UserService } from '@app/domain';
 | 
					import { UserService } from '@app/domain';
 | 
				
			||||||
import { Authenticated } from '../decorators/authenticated.decorator';
 | 
					import { Authenticated } from '../decorators/authenticated.decorator';
 | 
				
			||||||
@ -29,10 +27,11 @@ import { UserCountResponseDto } from '@app/domain';
 | 
				
			|||||||
import { CreateProfileImageDto } from '@app/domain';
 | 
					import { CreateProfileImageDto } from '@app/domain';
 | 
				
			||||||
import { CreateProfileImageResponseDto } from '@app/domain';
 | 
					import { CreateProfileImageResponseDto } from '@app/domain';
 | 
				
			||||||
import { UserCountDto } from '@app/domain';
 | 
					import { UserCountDto } from '@app/domain';
 | 
				
			||||||
 | 
					import { UseValidation } from '../decorators/use-validation.decorator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiTags('User')
 | 
					@ApiTags('User')
 | 
				
			||||||
@Controller('user')
 | 
					@Controller('user')
 | 
				
			||||||
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
 | 
					@UseValidation()
 | 
				
			||||||
export class UserController {
 | 
					export class UserController {
 | 
				
			||||||
  constructor(private service: UserService) {}
 | 
					  constructor(private service: UserService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import { applyDecorators, UsePipes, ValidationPipe } from '@nestjs/common';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function UseValidation() {
 | 
				
			||||||
 | 
					  return applyDecorators(
 | 
				
			||||||
 | 
					    UsePipes(
 | 
				
			||||||
 | 
					      new ValidationPipe({
 | 
				
			||||||
 | 
					        transform: true,
 | 
				
			||||||
 | 
					        whitelist: true,
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,21 +1,30 @@
 | 
				
			|||||||
import { SystemConfig } from '@app/infra/entities';
 | 
					import { SystemConfig } from '@app/infra/entities';
 | 
				
			||||||
import { ValidateNested } from 'class-validator';
 | 
					import { Type } from 'class-transformer';
 | 
				
			||||||
 | 
					import { IsObject, ValidateNested } from 'class-validator';
 | 
				
			||||||
import { SystemConfigFFmpegDto } from './system-config-ffmpeg.dto';
 | 
					import { SystemConfigFFmpegDto } from './system-config-ffmpeg.dto';
 | 
				
			||||||
import { SystemConfigOAuthDto } from './system-config-oauth.dto';
 | 
					import { SystemConfigOAuthDto } from './system-config-oauth.dto';
 | 
				
			||||||
import { SystemConfigPasswordLoginDto } from './system-config-password-login.dto';
 | 
					import { SystemConfigPasswordLoginDto } from './system-config-password-login.dto';
 | 
				
			||||||
import { SystemConfigStorageTemplateDto } from './system-config-storage-template.dto';
 | 
					import { SystemConfigStorageTemplateDto } from './system-config-storage-template.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class SystemConfigDto {
 | 
					export class SystemConfigDto {
 | 
				
			||||||
 | 
					  @Type(() => SystemConfigFFmpegDto)
 | 
				
			||||||
  @ValidateNested()
 | 
					  @ValidateNested()
 | 
				
			||||||
 | 
					  @IsObject()
 | 
				
			||||||
  ffmpeg!: SystemConfigFFmpegDto;
 | 
					  ffmpeg!: SystemConfigFFmpegDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Type(() => SystemConfigOAuthDto)
 | 
				
			||||||
  @ValidateNested()
 | 
					  @ValidateNested()
 | 
				
			||||||
 | 
					  @IsObject()
 | 
				
			||||||
  oauth!: SystemConfigOAuthDto;
 | 
					  oauth!: SystemConfigOAuthDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Type(() => SystemConfigPasswordLoginDto)
 | 
				
			||||||
  @ValidateNested()
 | 
					  @ValidateNested()
 | 
				
			||||||
 | 
					  @IsObject()
 | 
				
			||||||
  passwordLogin!: SystemConfigPasswordLoginDto;
 | 
					  passwordLogin!: SystemConfigPasswordLoginDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Type(() => SystemConfigStorageTemplateDto)
 | 
				
			||||||
  @ValidateNested()
 | 
					  @ValidateNested()
 | 
				
			||||||
 | 
					  @IsObject()
 | 
				
			||||||
  storageTemplate!: SystemConfigStorageTemplateDto;
 | 
					  storageTemplate!: SystemConfigStorageTemplateDto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user