【问题标题】:Serialization: How to exclude Entity columns in json response but not internal queries in Nestjs序列化:如何排除 json 响应中的实体列,但不排除 Nestjs 中的内部查询
【发布时间】:2019-06-17 02:54:39
【问题描述】:

编辑
我已经看过这个问题/答案How to exclude entity field from controller 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 是否可行?

如果是这样,将不胜感激指向正确方向的指针。

【问题讨论】:

    标签: javascript node.js typescript nestjs class-transformer


    【解决方案1】:

    您可以跳过属性depending on the operation。在您的情况下,您将使用:

    @Column()
    @Exclude({ toPlainOnly: true })
    password: string;
    

    这意味着,仅当类转换为 json 时(当您发送响应时)而不是当 json 转换为类时(当您收到请求时)才跳过密码。

    然后将@UseInterceptors(ClassSerializerInterceptor) 添加到您的控制器或控制器方法中。这将在您返回实体类时自动将其转换为 json。


    要使ClassSerializerInterceptor 正常工作,请确保您的实体首先转换为类。这可以通过使用带有{ transform: true} 选项的ValidationPipe 或通过从存储库(数据库)返回实体来自动完成。此外,您必须返回实体本身:

    @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) };
    }
    

    【讨论】:

    • 感谢您的回答。不幸的是,由于某种原因,这仍然不适用于@UseInterceptors(ClassSerializerInterceptor)。但是,添加类转换 @TransformClassToPlain() 就可以了
    • 啊,我只是看到你没有直接返回实体。 ClassSerializerInterceptor 仅在返回实体本身时才有效,因此 return profile 而不是 return {profile}。如果你不直接返回它,你必须使用plainToClass()手动转换它。
    【解决方案2】:

    建议也看看TypeOrm hidden-columns 在这里,您的密码列上有@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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-27
      • 2021-08-02
      • 2012-05-15
      • 2011-05-14
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 2018-10-25
      相关资源
      最近更新 更多