Сериализация: Как исключить столбцы сущностей в ответе json, но не внутренние запросы в Nestjs
Редактировать:
Я посмотрел на этот вопрос / ответ Как исключить поле сущности из контроллера JSON
Но, как показано ниже - это исключает это поле из всех запросов (в той части, где при попытке обработки проверки пользователя поле пароля исключается с помощью запроса репозитория findOne для метода маршрута / контроллера, который не имеет ClassSerializerInterceptor
У меня есть сущность в nest.js / typeorm; Я пытаюсь исключить поле пароля из возвращенного json, но не исключаю поле пароля из любых запросов к репозиторию в моем сервисе. Например:
user.entity.ts
:
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn,
UpdateDateColumn, ManyToOne } from 'typeorm';
import { Exclude } from 'class-transformer';
import { Account } from '../accounts/account.entity';
@Entity()
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
firstName: string;
@Column()
lastName: string;
@Column({
unique: true,
})
email: string;
@Column()
password: string;
}
auth.controller.ts
:
import { Controller, Post, Body, Request, Req, Get, UseInterceptors, ClassSerializerInterceptor, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { AuthService } from './auth.service';
import { IUserRequest } from '../../interfaces/user-request.interface';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('/login')
async login(@Request() req: Request) {
const user = await this.authService.checkCredentials(req.body);
return this.authService.logUserIn(user.id);
}
@Get('/profile')
@UseGuards(AuthGuard())
@UseInterceptors(ClassSerializerInterceptor)
async profile(@Request() req: IUserRequest) {
const profile = await this.authService.getLoggedInProfile(req.user.id);
return { profile };
}
}
Если я добавлю Exclude()
чтобы пароль как так
@Exclude()
@Column()
password: string;
пароль включен в ответ
Если я удалю Column()
из пароля,
@Exclude()
password: string;
Пароль исключен из ответа и всех внутренних запросов, таких как:
const user = await this.userRepository.findOne({ where: { id }, relations: ['account']});
Возможно ли это в nest.js, используя ClassSerializerInterceptor
?
Если это так, был бы признателен указатель в правильном направлении.
1 ответ
Вы можете пропустить свойства в зависимости от операции. В вашем случае вы бы использовали:
@Column()
@Exclude({ toPlainOnly: true })
password: string;
Это означает, что пароль пропускается только при преобразовании класса в json (при отправке ответа), а не при преобразовании json в класс (при получении запроса).
Затем добавьте @UseInterceptors(ClassSerializerInterceptor)
на ваш контроллер или метод контроллера. Это автоматически преобразует класс сущности в json, когда вы его вернете.
Для ClassSerializerInterceptor
чтобы работать, убедитесь, что ваша сущность была преобразована в класс первым. Это может быть сделано автоматически с помощью ValidationPipe
с { transform: true}
вариант или путем возврата объекта из хранилища (базы данных). Кроме того, вы должны вернуть саму сущность:
@Post()
@UseInterceptors(ClassSerializerInterceptor)
addUser(@Body(new ValidationPipe({transform: true})) user: User) {
// Logs user with password
console.log(user);
// Returns user as JSON without password
return user;
}
В противном случае вам придется преобразовать его вручную:
async profile(@Request() req: IUserRequest) {
// Profile comes from the database so it will be an entity class instance already
const profile = await this.authService.getLoggedInProfile(req.user.id);
// Since we are not returning the entity directly, we have to transform it manually
return { profile: plainToClass(profile) };
}
Посоветовал бы также посмотреть на скрытые столбцы TypeOrm
Здесь у вас есть@Column({select: false})
в столбце пароля, все запросы, использующие стандартный поиск или запрос, будут исключать столбец пароля.
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column({select: false})
password: string;
}
Затем во время проверок / случаев, когда вам нужен пароль, который вы делаете
const users = await connection.getRepository(User)
.createQueryBuilder()
.select("user.id", "id")
.addSelect("user.password")
.getMany();