[英]Serialization: How to exclude Entity columns in json response but not internal queries in Nestjs
Edit :编辑:
I have looked at this question/answer How to exclude entity field from controller json我看过这个问题/答案How to exclude entity field from controller json
But, as per below - this is excluding that field from all queries (to the porint where when trying to process user validation, the password field is excluded using the findOne repository query on a route/controller method that does not have ClassSerializerInterceptor但是,如下所示 - 这是从所有查询中排除该字段(到尝试处理用户验证时的端口,在没有 ClassSerializerInterceptor 的路由/控制器方法上使用 findOne 存储库查询排除密码字段
I have an entity within nest.js / typeorm;我在 nest.js / typeorm 中有一个实体; I am trying to exclude the password field from the returned json, but not exclude the password field from any repository queries within my service.
我试图从返回的 json 中排除密码字段,但不从我的服务中的任何存储库查询中排除密码字段。 For example:
例如:
user.entity.ts
: 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
: 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 };
}
}
If I add Exclude()
to password like so如果我像这样将
Exclude()
添加到密码中
@Exclude()
@Column()
password: string;
the password is included in the response密码包含在响应中
If I remove the Column()
from password,如果我从密码中删除
Column()
,
@Exclude()
password: string;
Password is excluded from response and all internal queries such as:密码不包括在响应和所有内部查询中,例如:
const user = await this.userRepository.findOne({ where: { id }, relations: ['account']});
Is this possible in nest.js using the ClassSerializerInterceptor
?这在 nest.js 中使用
ClassSerializerInterceptor
是否ClassSerializerInterceptor
?
If so, would appreciate a pointer in the right direction.如果是这样,将不胜感激指向正确方向的指针。
You can skip properties depending on the operation .您可以根据操作跳过属性。 In your case, you would use:
在您的情况下,您将使用:
@Column()
@Exclude({ toPlainOnly: true })
password: string;
This means, that password is only skipped when a class is transformed to json (when you send a response) and not when json is transformed to a class (when you get a request).这意味着,只有在类转换为 json 时(当您发送响应时)而不是在 json 转换为类时(当您收到请求时)才会跳过该密码。
Then add the @UseInterceptors(ClassSerializerInterceptor)
to your controller or a controller method.然后将
@UseInterceptors(ClassSerializerInterceptor)
添加到您的控制器或控制器方法中。 This will automatically transform an entity class to json, when you return it.这将在您返回实体类时自动将其转换为 json。
For the ClassSerializerInterceptor
to work, make sure that your entity was transformed to a class first.要使
ClassSerializerInterceptor
工作,请确保您的实体首先转换为类。 This can be automatically done by using the ValidationPipe
with the { transform: true}
option or by returning an entity from a repository (database).这可以通过使用带有
{ transform: true}
选项的ValidationPipe
或通过从存储库(数据库)返回实体来自动完成。 Also, you have to return the entity itself:此外,您必须返回实体本身:
@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;
}
Otherwise, you have to transform it manually:否则,您必须手动转换它:
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) };
}
Would advice also looking at TypeOrm hidden-columns Here you have @Column({select: false})
on your password column , all requests using a standard find or query will exclude the password column.建议还查看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;
}
Then during validations/cases where you need the password you do然后在您需要密码的验证/情况下
const users = await connection.getRepository(User)
.createQueryBuilder()
.select("user.id", "id")
.addSelect("user.password")
.getMany();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.