Как предотвратить нежелательные свойства объекта от клиента в nestjs при обновлении существующей строки в mongodb
Создание нового пользователя будет игнорировать не указанные объекты из create-user.dto.ts
Однако, когда я обновляю пользователя, он добавляет нежелательные поля, как это:
// update-user.dto.ts
import { IsEmail } from 'class-validator';
import { Address } from '../model/address';
export class UpdateUserDto {
firstName: string;
lastName: string;
@IsEmail(undefined, { message: 'Not a valid e-mail' })
email: string;
username: string;
password: string;
addresses: Address[];
}
Это действие по обновлению от пользовательского сервиса
// user.service.ts
async update(data: UpdateUserDto) {
try {
this.logger.log(data);
const id = '5c6dd9852d4f441638c2df86';
const user = await this.userRepository.update(id, data);
return { message: 'Updated your information' };
} catch (error) {
this.logger.log(error);
throw new HttpException('', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
А вот и файл user.controller.ts
@Patch()
@UsePipes(CustomValidationPipe)
async update(@Body() data: UpdateUserDto) {
return this.userService.update(data);
}
Данные патча клиента:
// Unwanted junk from client
{
"email": "newemail@gmail.com",
"junk": "junk"
}
email
будет обновляться правильно, но строка будет иметь новое нежелательное свойство junk
со значением junk
5 ответов
Я предполагаю, что вы используете class-transformer
"s validate
метод в вашем CustomValidationPipe
,
Когда вы передаете whitelist
вариант к нему, validate
удалит все неизвестные (-> нет аннотации в вашем классе DTO) свойства:
validate(userUpdate, { whitelist: true })
Если вы хотите выбросить ошибку проверки вместо того, чтобы просто удалить неизвестные свойства, вы можете дополнительно передать forbidNonWhitelisted
вариант.
validate(userUpdate, { whitelist: true, forbidNonWhitelisted: true });
В случае обновления, вы, вероятно, также хотите использовать skipMissingProperties: true
, так что validate не выдаст ошибку, когда, например, lastName
не является частью обновления.
Обратите внимание, что вы должны аннотировать все свойства в вашем классе dto, чтобы проверка работала правильно:
@IsString()
lastName: string;
@ValidateNested()
@Type(() => Address)
address: Address
Не уверен, когда это поведение/опция было добавлено в NestJS (возможно, оно было добавлено после исходного вопроса и принятого ответа), но лучший способ добиться удаления неизвестного свойства:
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
}),
);
Вот и все. Просто убедитесь, что у вас есть
whitelist: true
в вашей конфигурации вы не получите неизвестного/недопустимого свойства.
Вы также можете полностью остановить запрос, установив другое свойство с именем
forbidNonWhitelisted
к
true
.
Подробнее об этом здесь: https://docs.nestjs.com/techniques/validation#stripping-properties
Для таких новичков, как я, которые все еще задаются вопросом, вот простой способ реализовать это:
@UsePipes(new ValidationPipe({ whitelist: true }))
Поместите декоратор под декоратор методов (@Post, @Put и т. д.)
ОбаUsePipe
иValidationPipe
импортируются@nestjs/common
Если вы также хотите выдать ошибку для неожиданных свойств, ее можно настроить следующим образом:
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
forbidUnknownValues: true
})
);
Неожиданное свойство приведет к
{
"statusCode": 400,
"message": [
"property XXX should not exist"
],
"error": "Bad Request"
}
Обсуждение можно найти здесь
Я нашел решение:
Вот как должен выглядеть user.service.ts update():
const user = await this.userRepository.create(data);
должен быть добавлен до
await this.userRepository.update(id, user);
Вот полное обновление user.service.ts ()
async update(data: UpdateUserDto) {
this.logger.log(data);
// added for testing purposes (id should be based on active user)
const id = '5c6ef2c823bf4e3414d65cd0';
const user = await this.userRepository.create(data);
await this.userRepository.update(id, user);
return { message: 'Updated your information' };
}
Теперь любые нежелательные свойства не будут добавлены в строку