【发布时间】:2021-01-02 15:53:47
【问题描述】:
我正在寻找有关 Nest 中自定义验证器和自定义装饰器的帮助。
第一种情况:工作一个
一个 DTO,带有类验证器注释:
import { IsNotEmpty, IsString } from 'class-validator';
import { IsOwnerExisting } from '../decorators/is-owner-existing.decorator';
export class CreatePollDto {
@IsNotEmpty()
@IsString()
@IsOwnerExisting() // custom decorator, calling custom validator, using a service to check in db
ownerEmail: string;
@IsNotEmpty()
@IsString()
@NotContains(' ', { message: 'Slug should NOT contain any whitespace.' })
slug: string;
}
我在控制器中使用它:
@Controller()
@ApiTags('/polls')
export class PollsController {
constructor(private readonly pollsService: PollsService) {}
@Post()
public async create(@Body() createPollDto: CreatePollDto): Promise<Poll> {
return await this.pollsService.create(createPollDto);
}
}
当调用此端点时,dto 正在通过类验证器进行验证,并且我的自定义验证器可以工作。如果电子邮件不适合数据库中的任何用户,则会显示默认消息。 我是这么理解的。
第二种情况:如何让它发挥作用?
现在,我想做一些类似的事情,但在嵌套路由中,使用 ApiParam。我想使用自定义验证器检查参数是否与数据库中的某个对象匹配。
在那种情况下,我不能在 dto 中使用装饰器,因为 dto 不处理“slug”属性,它是 ManyToOne,而属性在另一边。
// ENTITIES
export class Choice {
@ManyToOne((type) => Poll)
poll: Poll;
}
export class Poll {
@Column({ unique: true })
slug: string;
@OneToMany((type) => Choice, (choice) => choice.poll, { cascade: true, eager: true })
@JoinColumn()
choices?: Choice[];
}
// DTOs
export class CreateChoiceDto {
@IsNotEmpty()
@IsString()
label: string;
@IsOptional()
@IsString()
imageUrl?: string;
}
export class CreatePollDto {
@IsNotEmpty()
@IsString()
@NotContains(' ', { message: 'Slug should NOT contain any whitespace.' })
slug: string;
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => CreateChoiceDto)
choices: CreateChoiceDto[] = [];
}
那么我应该在哪里挂钩我的验证?
我想直接在控制器中使用一些装饰器。也许这不是个好地方,我不知道。我也可以在服务中做到这一点。
@Controller()
@ApiTags('/polls/{slug}/choices')
export class ChoicesController {
constructor(private readonly choicesService: ChoicesService) {}
@Post()
@ApiParam({ name: 'slug', type: String })
async create(@Param('slug') slug: string, @Body() createChoiceDto: CreateChoiceDto): Promise<Choice> {
return await this.choicesService.create(slug, createChoiceDto);
}
}
在我的第一个案例中,我想使用类似以下的东西,但在控制器的 create 方法中。
@ValidatorConstraint({ async: true })
export class IsSlugMatchingAnyExistingPollConstraint implements ValidatorConstraintInterface {
constructor(@Inject(forwardRef(() => PollsService)) private readonly pollsService: PollsService) {}
public async validate(slug: string, args: ValidationArguments): Promise<boolean> {
return (await this.pollsService.findBySlug(slug)) ? true : false;
}
public defaultMessage(args: ValidationArguments): string {
return `No poll exists with this slug : $value. Use an existing slug, or register one.`;
}
}
你明白我想做什么吗?可行吗?有什么好办法?
非常感谢!
【问题讨论】:
标签: decorator nestjs class-validator