mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02:00
refactor(server): more consistent param validation (#2166)
This commit is contained in:
parent
ad680b6a35
commit
d5f2e3e45c
BIN
mobile/openapi/doc/APIKeyApi.md
generated
BIN
mobile/openapi/doc/APIKeyApi.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/AlbumApi.md
generated
BIN
mobile/openapi/doc/AlbumApi.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/AssetApi.md
generated
BIN
mobile/openapi/doc/AssetApi.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/ShareApi.md
generated
BIN
mobile/openapi/doc/ShareApi.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/TagApi.md
generated
BIN
mobile/openapi/doc/TagApi.md
generated
Binary file not shown.
BIN
mobile/openapi/doc/UserApi.md
generated
BIN
mobile/openapi/doc/UserApi.md
generated
Binary file not shown.
@ -7,7 +7,6 @@ import {
|
||||
Param,
|
||||
Delete,
|
||||
ValidationPipe,
|
||||
ParseUUIDPipe,
|
||||
Put,
|
||||
Query,
|
||||
Response,
|
||||
@ -33,8 +32,7 @@ import {
|
||||
} from '../../constants/download.constant';
|
||||
import { DownloadDto } from '../asset/dto/download-library.dto';
|
||||
import { CreateAlbumShareLinkDto as CreateAlbumSharedLinkDto } from './dto/create-album-shared-link.dto';
|
||||
|
||||
// TODO might be worth creating a AlbumParamsDto that validates `albumId` instead of using the pipe.
|
||||
import { AlbumIdDto } from './dto/album-id.dto';
|
||||
|
||||
@ApiTags('Album')
|
||||
@Controller('album')
|
||||
@ -58,7 +56,7 @@ export class AlbumController {
|
||||
async addUsersToAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Body(ValidationPipe) addUsersDto: AddUsersDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
@Param() { albumId }: AlbumIdDto,
|
||||
) {
|
||||
return this.albumService.addUsersToAlbum(authUser, addUsersDto, albumId);
|
||||
}
|
||||
@ -68,17 +66,14 @@ export class AlbumController {
|
||||
async addAssetsToAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Body(ValidationPipe) addAssetsDto: AddAssetsDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
@Param() { albumId }: AlbumIdDto,
|
||||
): Promise<AddAssetsResponseDto> {
|
||||
return this.albumService.addAssetsToAlbum(authUser, addAssetsDto, albumId);
|
||||
}
|
||||
|
||||
@Authenticated({ isShared: true })
|
||||
@Get('/:albumId')
|
||||
async getAlbumInfo(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
) {
|
||||
async getAlbumInfo(@GetAuthUser() authUser: AuthUserDto, @Param() { albumId }: AlbumIdDto) {
|
||||
return this.albumService.getAlbumInfo(authUser, albumId);
|
||||
}
|
||||
|
||||
@ -87,17 +82,14 @@ export class AlbumController {
|
||||
async removeAssetFromAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Body(ValidationPipe) removeAssetsDto: RemoveAssetsDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
@Param() { albumId }: AlbumIdDto,
|
||||
): Promise<AlbumResponseDto> {
|
||||
return this.albumService.removeAssetsFromAlbum(authUser, removeAssetsDto, albumId);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete('/:albumId')
|
||||
async deleteAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
) {
|
||||
async deleteAlbum(@GetAuthUser() authUser: AuthUserDto, @Param() { albumId }: AlbumIdDto) {
|
||||
return this.albumService.deleteAlbum(authUser, albumId);
|
||||
}
|
||||
|
||||
@ -105,7 +97,7 @@ export class AlbumController {
|
||||
@Delete('/:albumId/user/:userId')
|
||||
async removeUserFromAlbum(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
@Param() { albumId }: AlbumIdDto,
|
||||
@Param('userId', new ParseMeUUIDPipe({ version: '4' })) userId: string,
|
||||
) {
|
||||
return this.albumService.removeUserFromAlbum(authUser, albumId, userId);
|
||||
@ -116,7 +108,7 @@ export class AlbumController {
|
||||
async updateAlbumInfo(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Body(ValidationPipe) updateAlbumInfoDto: UpdateAlbumDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
@Param() { albumId }: AlbumIdDto,
|
||||
) {
|
||||
return this.albumService.updateAlbumInfo(authUser, updateAlbumInfoDto, albumId);
|
||||
}
|
||||
@ -126,7 +118,7 @@ export class AlbumController {
|
||||
@ApiOkResponse({ content: { 'application/zip': { schema: { type: 'string', format: 'binary' } } } })
|
||||
async downloadArchive(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('albumId', new ParseUUIDPipe({ version: '4' })) albumId: string,
|
||||
@Param() { albumId }: AlbumIdDto,
|
||||
@Query(new ValidationPipe({ transform: true })) dto: DownloadDto,
|
||||
@Response({ passthrough: true }) res: Res,
|
||||
) {
|
||||
|
9
server/apps/immich/src/api-v1/album/dto/album-id.dto.ts
Normal file
9
server/apps/immich/src/api-v1/album/dto/album-id.dto.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
export class AlbumIdDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID('4')
|
||||
@ApiProperty({ format: 'uuid' })
|
||||
albumId!: string;
|
||||
}
|
@ -57,6 +57,8 @@ import { AssetSearchDto } from './dto/asset-search.dto';
|
||||
import { assetUploadOption, ImmichFile } from '../../config/asset-upload.config';
|
||||
import FileNotEmptyValidator from '../validation/file-not-empty-validator';
|
||||
import { RemoveAssetsDto } from '../album/dto/remove-assets.dto';
|
||||
import { AssetIdDto } from './dto/asset-id.dto';
|
||||
import { DeviceIdDto } from './dto/device-id.dto';
|
||||
|
||||
function asStreamableFile({ stream, type, length }: ImmichReadStream) {
|
||||
return new StreamableFile(stream, { type, length });
|
||||
@ -111,7 +113,7 @@ export class AssetController {
|
||||
async downloadFile(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Response({ passthrough: true }) res: Res,
|
||||
@Param('assetId') assetId: string,
|
||||
@Param() { assetId }: AssetIdDto,
|
||||
) {
|
||||
return this.assetService.downloadFile(authUser, assetId).then(asStreamableFile);
|
||||
}
|
||||
@ -163,7 +165,7 @@ export class AssetController {
|
||||
@Headers() headers: Record<string, string>,
|
||||
@Response({ passthrough: true }) res: Res,
|
||||
@Query(new ValidationPipe({ transform: true })) query: ServeFileDto,
|
||||
@Param('assetId') assetId: string,
|
||||
@Param() { assetId }: AssetIdDto,
|
||||
) {
|
||||
await this.assetService.checkAssetsAccess(authUser, [assetId]);
|
||||
return this.assetService.serveFile(authUser, assetId, query, res, headers);
|
||||
@ -177,7 +179,7 @@ export class AssetController {
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Headers() headers: Record<string, string>,
|
||||
@Response({ passthrough: true }) res: Res,
|
||||
@Param('assetId') assetId: string,
|
||||
@Param() { assetId }: AssetIdDto,
|
||||
@Query(new ValidationPipe({ transform: true })) query: GetAssetThumbnailDto,
|
||||
) {
|
||||
await this.assetService.checkAssetsAccess(authUser, [assetId]);
|
||||
@ -258,7 +260,7 @@ export class AssetController {
|
||||
*/
|
||||
@Authenticated()
|
||||
@Get('/:deviceId')
|
||||
async getUserAssetsByDeviceId(@GetAuthUser() authUser: AuthUserDto, @Param('deviceId') deviceId: string) {
|
||||
async getUserAssetsByDeviceId(@GetAuthUser() authUser: AuthUserDto, @Param() { deviceId }: DeviceIdDto) {
|
||||
return await this.assetService.getUserAssetsByDeviceId(authUser, deviceId);
|
||||
}
|
||||
|
||||
@ -269,7 +271,7 @@ export class AssetController {
|
||||
@Get('/assetById/:assetId')
|
||||
async getAssetById(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('assetId') assetId: string,
|
||||
@Param() { assetId }: AssetIdDto,
|
||||
): Promise<AssetResponseDto> {
|
||||
await this.assetService.checkAssetsAccess(authUser, [assetId]);
|
||||
return await this.assetService.getAssetById(authUser, assetId);
|
||||
@ -282,7 +284,7 @@ export class AssetController {
|
||||
@Put('/:assetId')
|
||||
async updateAsset(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('assetId') assetId: string,
|
||||
@Param() { assetId }: AssetIdDto,
|
||||
@Body(ValidationPipe) dto: UpdateAssetDto,
|
||||
): Promise<AssetResponseDto> {
|
||||
await this.assetService.checkAssetsAccess(authUser, [assetId], true);
|
||||
|
9
server/apps/immich/src/api-v1/asset/dto/asset-id.dto.ts
Normal file
9
server/apps/immich/src/api-v1/asset/dto/asset-id.dto.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
export class AssetIdDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID('4')
|
||||
@ApiProperty({ format: 'uuid' })
|
||||
assetId!: string;
|
||||
}
|
9
server/apps/immich/src/api-v1/asset/dto/device-id.dto.ts
Normal file
9
server/apps/immich/src/api-v1/asset/dto/device-id.dto.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
export class DeviceIdDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID('4')
|
||||
@ApiProperty({ format: 'uuid' })
|
||||
deviceId!: string;
|
||||
}
|
@ -6,6 +6,7 @@ import { Authenticated } from '../../decorators/authenticated.decorator';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
|
||||
import { mapTag, TagResponseDto } from '@app/domain';
|
||||
import { UUIDParamDto } from '../../controllers/dto/uuid-param.dto';
|
||||
|
||||
@Authenticated()
|
||||
@ApiTags('Tag')
|
||||
@ -27,7 +28,7 @@ export class TagController {
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
async findOne(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<TagResponseDto> {
|
||||
async findOne(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<TagResponseDto> {
|
||||
const tag = await this.tagService.findOne(authUser, id);
|
||||
return mapTag(tag);
|
||||
}
|
||||
@ -35,14 +36,14 @@ export class TagController {
|
||||
@Patch(':id')
|
||||
update(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('id') id: string,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
@Body(ValidationPipe) updateTagDto: UpdateTagDto,
|
||||
): Promise<TagResponseDto> {
|
||||
return this.tagService.update(authUser, id, updateTagDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
delete(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<void> {
|
||||
delete(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.tagService.remove(authUser, id);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import { ApiTags } from '@nestjs/swagger';
|
||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
import { UseValidation } from '../decorators/use-validation.decorator';
|
||||
import { UUIDParamDto } from './dto/uuid-param.dto';
|
||||
|
||||
@ApiTags('API Key')
|
||||
@Controller('api-key')
|
||||
@ -30,21 +31,21 @@ export class APIKeyController {
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
getKey(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<APIKeyResponseDto> {
|
||||
getKey(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<APIKeyResponseDto> {
|
||||
return this.service.getById(authUser, id);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
updateKey(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('id') id: string,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
@Body() dto: APIKeyUpdateDto,
|
||||
): Promise<APIKeyResponseDto> {
|
||||
return this.service.update(authUser, id, dto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
deleteKey(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<void> {
|
||||
deleteKey(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.service.delete(authUser, id);
|
||||
}
|
||||
}
|
||||
|
9
server/apps/immich/src/controllers/dto/uuid-param.dto.ts
Normal file
9
server/apps/immich/src/controllers/dto/uuid-param.dto.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
export class UUIDParamDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID('4')
|
||||
@ApiProperty({ format: 'uuid' })
|
||||
id!: string;
|
||||
}
|
@ -4,6 +4,7 @@ import { ApiTags } from '@nestjs/swagger';
|
||||
import { GetAuthUser } from '../decorators/auth-user.decorator';
|
||||
import { Authenticated } from '../decorators/authenticated.decorator';
|
||||
import { UseValidation } from '../decorators/use-validation.decorator';
|
||||
import { UUIDParamDto } from './dto/uuid-param.dto';
|
||||
|
||||
@ApiTags('share')
|
||||
@Controller('share')
|
||||
@ -25,13 +26,16 @@ export class ShareController {
|
||||
|
||||
@Authenticated()
|
||||
@Get(':id')
|
||||
getSharedLinkById(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<SharedLinkResponseDto> {
|
||||
getSharedLinkById(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
): Promise<SharedLinkResponseDto> {
|
||||
return this.service.getById(authUser, id, true);
|
||||
}
|
||||
|
||||
@Authenticated()
|
||||
@Delete(':id')
|
||||
removeSharedLink(@GetAuthUser() authUser: AuthUserDto, @Param('id') id: string): Promise<void> {
|
||||
removeSharedLink(@GetAuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.service.remove(authUser, id);
|
||||
}
|
||||
|
||||
@ -39,7 +43,7 @@ export class ShareController {
|
||||
@Patch(':id')
|
||||
editSharedLink(
|
||||
@GetAuthUser() authUser: AuthUserDto,
|
||||
@Param('id') id: string,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
@Body() dto: EditSharedLinkDto,
|
||||
): Promise<SharedLinkResponseDto> {
|
||||
return this.service.edit(authUser, id, dto);
|
||||
|
@ -28,6 +28,7 @@ import { CreateProfileImageDto } from '@app/domain';
|
||||
import { CreateProfileImageResponseDto } from '@app/domain';
|
||||
import { UserCountDto } from '@app/domain';
|
||||
import { UseValidation } from '../decorators/use-validation.decorator';
|
||||
import { UserIdDto } from '@app/domain/user/dto/user-id.dto';
|
||||
|
||||
@ApiTags('User')
|
||||
@Controller('user')
|
||||
@ -43,7 +44,7 @@ export class UserController {
|
||||
|
||||
@Authenticated()
|
||||
@Get('/info/:userId')
|
||||
getUserById(@Param('userId') userId: string): Promise<UserResponseDto> {
|
||||
getUserById(@Param() { userId }: UserIdDto): Promise<UserResponseDto> {
|
||||
return this.service.getUserById(userId);
|
||||
}
|
||||
|
||||
@ -66,13 +67,13 @@ export class UserController {
|
||||
|
||||
@Authenticated({ admin: true })
|
||||
@Delete('/:userId')
|
||||
deleteUser(@GetAuthUser() authUser: AuthUserDto, @Param('userId') userId: string): Promise<UserResponseDto> {
|
||||
deleteUser(@GetAuthUser() authUser: AuthUserDto, @Param() { userId }: UserIdDto): Promise<UserResponseDto> {
|
||||
return this.service.deleteUser(authUser, userId);
|
||||
}
|
||||
|
||||
@Authenticated({ admin: true })
|
||||
@Post('/:userId/restore')
|
||||
restoreUser(@GetAuthUser() authUser: AuthUserDto, @Param('userId') userId: string): Promise<UserResponseDto> {
|
||||
restoreUser(@GetAuthUser() authUser: AuthUserDto, @Param() { userId }: UserIdDto): Promise<UserResponseDto> {
|
||||
return this.service.restoreUser(authUser, userId);
|
||||
}
|
||||
|
||||
@ -100,7 +101,7 @@ export class UserController {
|
||||
@Authenticated()
|
||||
@Get('/profile-image/:userId')
|
||||
@Header('Cache-Control', 'max-age=600')
|
||||
async getProfileImage(@Param('userId') userId: string, @Response({ passthrough: true }) res: Res): Promise<any> {
|
||||
async getProfileImage(@Param() { userId }: UserIdDto, @Response({ passthrough: true }) res: Res): Promise<any> {
|
||||
const readableStream = await this.service.getUserProfileImage(userId);
|
||||
res.header('Content-Type', 'image/jpeg');
|
||||
return new StreamableFile(readableStream);
|
||||
|
@ -172,6 +172,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -209,6 +210,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -256,6 +258,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1117,6 +1120,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1154,6 +1158,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1184,6 +1189,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1479,6 +1485,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1580,6 +1587,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1619,6 +1627,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1699,6 +1708,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -1788,6 +1798,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -1955,6 +1966,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -2003,6 +2015,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -2414,6 +2427,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -2456,6 +2470,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -2503,6 +2518,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -2850,6 +2866,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -2887,6 +2904,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -2934,6 +2952,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -2996,6 +3015,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -3045,6 +3065,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -3100,6 +3121,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -3149,6 +3171,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -3194,6 +3217,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -3224,6 +3248,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@ -3273,6 +3298,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@ -3313,6 +3339,7 @@
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
|
9
server/libs/domain/src/user/dto/user-id.dto.ts
Normal file
9
server/libs/domain/src/user/dto/user-id.dto.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
export class UserIdDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID('4')
|
||||
@ApiProperty({ format: 'uuid' })
|
||||
userId!: string;
|
||||
}
|
Loading…
Reference in New Issue
Block a user