我遇到了一些关于nestjs/验证的问题.
我正在验证一个值为对象数组的属性.
此对象的一个属性将枚举数组作为值.
出于某些原因,它在POST上工作得很好:如果我放入一个无意义的字符串,而不是相应的枚举,它会抛出一个错误.
同样的情况不会发生在使用相同DTO的看跌期权上.
我说的是`defaultCapabilies`,它将‘capabilities’作为枚举array.
其他验证,如邮箱One,适用于这两种操作.
我将把代码留在这里,如果还有什么我应该指定的,请让我知道.
提前谢谢!
创建DTO
import { ApiProperty } from '@nestjs/swagger';
import { UserRole, UserCapability, CapabilitiesMap } from '../schemas/supp-tenant.schema';
import { IsEmail, ValidateNested, IsArray } from '@nestjs/class-validator';
import { Type } from '@nestjs/class-transformer';
export class TenantCreateDto {
@ApiProperty({ example: 'client1', description: 'The tenant name' })
client: string;
@IsEmail()
@ApiProperty({ example: 'client1@gmail.com', description: 'The tenant email' })
email: string;
@IsArray()
@Type(() => CapabilitiesMap)
@ValidateNested({ each: true })
@ApiProperty({
example:
[{
role: UserRole.USER,
capabilities: [UserCapability.CanCreatePost]
}],
type: [CapabilitiesMap],
description: 'Default capabilities for the tenant'
})
defaultCapabilities: CapabilitiesMap[];
}
更新DTO
import { ApiProperty } from '@nestjs/swagger';
import { UserRole, UserCapability, CapabilitiesMap } from '../schemas/supp-tenant.schema';
import { IsEmail, ValidateNested, IsArray } from '@nestjs/class-validator';
import { Type } from '@nestjs/class-transformer';
export class TenantUpdateDto {
@ApiProperty({ example: 'client1', description: 'The tenant name' })
client: string;
@IsEmail()
@ApiProperty({ example: 'client1@gmail.com', description: 'The tenant email' })
email: string;
@IsArray()
@Type(() => CapabilitiesMap)
@ValidateNested({ each: true })
@ApiProperty({
example:
[{
role: UserRole.USER,
capabilities: [UserCapability.CanCreatePost]
}],
type: [CapabilitiesMap],
description: 'Default capabilities for the tenant'
})
defaultCapabilities: CapabilitiesMap[];
}
控制器
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { TenantsService } from '../services/tenants.service';
import { TenantCreateDto } from '../dtos/tenant-create.dto';
import { TenantUpdateDto } from '../dtos/tenant-update.dto';
import { TenantResponseDto } from '../dtos/tenant-response.dto';
@ApiTags('Tenants')
@Controller('tenants')
export class TenantsController {
constructor(private readonly tenantsService: TenantsService) { }
@Post()
@ApiOperation({ summary: 'Create a new tenant' })
@ApiResponse({ status: 201, description: 'The tenant has been successfully created.', type: TenantResponseDto })
async create(@Body() createTenantDto: TenantCreateDto): Promise<TenantResponseDto> {
return this.tenantsService.create(createTenantDto);
}
@Get()
@ApiOperation({ summary: 'Retrieve all tenants' })
@ApiResponse({ status: 200, description: 'List of tenants', type: [TenantResponseDto] })
async findAll(): Promise<TenantResponseDto[]> {
return this.tenantsService.findAll();
}
@Get(':id')
@ApiOperation({ summary: 'Find tenant by id' })
@ApiResponse({ status: 200, description: 'The tenant with the matching id', type: TenantResponseDto })
async findOne(@Param('id') id: string): Promise<TenantResponseDto> {
return this.tenantsService.findOne(id);
}
@Put(':id')
@ApiOperation({ summary: 'Update tenant by id' })
@ApiResponse({ status: 200, description: 'The tenant has been successfully updated.', type: TenantResponseDto })
async update(@Param('id') id: string, @Body() updateTenantDto: TenantUpdateDto): Promise<TenantResponseDto> {
return this.tenantsService.update(id, updateTenantDto);
}
@Delete(':id')
@ApiOperation({ summary: 'Delete tenant by id' })
@ApiResponse({ status: 200, description: 'The tenant has been successfully deleted.', type: TenantResponseDto })
async remove(@Param('id') id: string): Promise<TenantResponseDto> {
return this.tenantsService.remove(id);
}
}
服务
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { SuppTenant, SuppTenantDocument } from '../schemas/supp-tenant.schema';
import { TenantCreateDto } from '../dtos/tenant-create.dto';
import { TenantUpdateDto } from '../dtos/tenant-update.dto';
import { TenantResponseDto } from '../dtos/tenant-response.dto';
@Injectable()
export class TenantsService {
constructor(@InjectModel(SuppTenant.name) private tenantModel: Model<SuppTenantDocument>) { }
async create(createTenantDto: TenantCreateDto): Promise<TenantResponseDto> {
const createdTenant = new this.tenantModel(createTenantDto);
const savedTenant = await createdTenant.save();
return new TenantResponseDto(savedTenant);
}
async findAll(): Promise<TenantResponseDto[]> {
const tenants = await this.tenantModel.find().exec();
return tenants.map(tenant => new TenantResponseDto(tenant));
}
async findOne(id: string): Promise<TenantResponseDto> {
const tenant = await this.tenantModel.findById(id).exec();
if (!tenant) {
return null;
}
return new TenantResponseDto(tenant);
}
async update(id: string, updateTenantDto: TenantUpdateDto): Promise<TenantResponseDto> {
const updatedTenant = await this.tenantModel.findByIdAndUpdate(id, updateTenantDto, { new: true }).exec();
if (!updatedTenant) {
return null;
}
return new TenantResponseDto(updatedTenant);
}
async remove(id: string): Promise<TenantResponseDto> {
const removedTenant = await this.tenantModel.findByIdAndRemove(id).exec();
if (!removedTenant) {
return null;
}
return new TenantResponseDto(removedTenant);
}
}
当我在"Capability"中使用无意义的字符串执行PUT操作时,我预计会看到一个验证错误,但它一直在接受这个值,同时具有相同条件的POST操作抛出了一个错误.我也try 在mongo模式中进行验证,但不起作用:
import { IsArray, IsEnum } from '@nestjs/class-validator';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { ApiProperty } from '@nestjs/swagger';
import { HydratedDocument } from 'mongoose';
export type SuppTenantDocument = HydratedDocument<SuppTenant>;
export enum UserCapability {
CanCreatePost = 'canCreatePost',
CanCreateComment = 'canCreateComment',
CanSupport = 'canSupport',
CanCreateReport = 'canCreateReport',
CanCreateProject = 'canCreateProject',
}
export enum UserRole {
ADMIN = 'admin',
MODERATOR = 'moderator',
EDITOR = 'editor',
USER = 'user',
}
@Schema({ _id: false, versionKey: false })
export class CapabilitiesMap {
@ApiProperty({
enum: UserRole,
default: UserRole.USER,
example: UserRole.USER,
description: 'User role'
})
@Prop({ type: String, enum: UserRole })
@IsEnum(UserRole)
role: UserRole;
@ApiProperty({
enum: UserCapability,
isArray: true,
default: [],
uniqueItems: true,
description: 'User capabilities',
example: [UserCapability.CanCreatePost]
})
@IsArray()
@IsEnum(UserCapability, { each: true })
@Prop({ type: [String], enum: UserCapability, default: [] })
capabilities: UserCapability[];
}
const CapabilitiesMapSchema = SchemaFactory.createForClass(CapabilitiesMap);
@Schema()
export class SuppTenant {
@Prop()
client: string;
@Prop({ required: true, minlength: 4, maxlength: 32, match: /.+@.+\..+/ })
email: string;
@Prop()
creationDate: string;
@Prop({ type: [CapabilitiesMapSchema], default: [] })
defaultCapabilities: CapabilitiesMap[];
}
export const SuppTenantSchema = SchemaFactory.createForClass(SuppTenant);