簡體   English   中英

序列化:如何在 json 響應中排除實體列而不是 Nestjs 中的內部查詢

[英]Serialization: How to exclude Entity columns in json response but not internal queries in Nestjs

編輯
我看過這個問題/答案How to exclude entity field from controller json
但是,如下所示 - 這是從所有查詢中排除該字段(到嘗試處理用戶驗證時的端口,在沒有 ClassSerializerInterceptor 的路由/控制器方法上使用 findOne 存儲庫查詢排除密碼字段

我在 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是否ClassSerializerInterceptor

如果是這樣,將不勝感激指向正確方向的指針。

您可以根據操作跳過屬性。 在您的情況下,您將使用:

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

建議還查看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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM