我遇到了一些关于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);

推荐答案

默认情况下,处理PUT请求时使用的findByIdAndUpdate方法为Mongoose does not run validation.

但你可以这样强迫它:

const updatedTenant = await this.tenantModel.findByIdAndUpdate(
  id,
  updateTenantDto,
  { new: true, runValidators: true }
).exec();

Mongodb相关问答推荐

MongoDB Aggregate-如何在条件中替换字符串中的变量

为什么 mongoose 在 mongodb 中找不到我的数据

我无法在react 中使用 fetch 和express 从数据库中删除数据

从 Amazon S3(Next.js、Mongodb、Mongoose)删除图像

MongoDB DB参考返回null值

MongoDB:嵌套数组计数+原始文档

在 MongoDB 中加入多个集合

有没有办法从另一条记录中插入一条记录

程序可以运行,但我不断收到发送到客户端后无法设置标题,我应该忽略它吗?

Mongodb按值分组并计算出现次数

在 MongoDB 中打开连接的 SocketTimeout

Select 匹配mongodb中两个字段的concat值的记录

Mongoose 和新架构:返回ReferenceError: Schema is not defined

如何在 mongo JavaScript shell 中中止查询

将 mongodb 聚合框架结果导出到新集合

如何使用 mgo 和 Go 查询 MongoDB 的日期范围?

mongo中的稀疏索引和空值

mongodb安装失败运行mongod

Meteor 发布/订阅独特客户端集合的策略

mongoose查询返回 null