【问题标题】:How to Expose field for the current user only?如何仅为当前用户公开字段?
【发布时间】:2019-03-21 21:05:35
【问题描述】:

仅当登录用户与实体具有相同的 id 时,我才会序列化实体用户的属性“电子邮件”。

实体用户:

@Entity()
@Exclude()
export class User {

    @Expose()
    @PrimaryGeneratedColumn("uuid")
    id: string;

    @Expose() // Only if logged user == this
    @Column({nullable: true, default: null})
    public email: string;

    @Expose()
    @Column({nullable: true, default: null})
    public username: string;

    @Column({nullable: true, default: null})
    public password: string;

    @CreateDateColumn()
    public create_at: Date;

    @UpdateDateColumn()
    public update_at: Date;
}

【问题讨论】:

    标签: javascript node.js nestjs typeorm


    【解决方案1】:

    没有直接的方法可以根据对象本身有条件地排除属性。您可以使用组来控制曝光:

    @Expose({ groups: ['owner'] })
    @Column({nullable: true, default: null})
    public email: string;
    

    然后在您的控制器中根据您的条件添加组:

    const groups = [];
    if (isCurrentUser) {
      groups.push('owner');
    }
    classToPlain(user, { groups })
    

    【讨论】:

    • 我在全球范围内使用ClassSerializerInterceptor。你知道是否可以向其中添加 ReflectMetada 吗?像这样:ReflectMetadata(CLASS_SERIALIZER_OPTIONS, {groups: ['user']});
    • 对不起,我不知道。 :-/ 也许为它打开一个新问题?
    • 把这个留在这里,以防有人偶然发现。如果要动态添加组(即使用ClassSerializerInterceptor而不是手动调用classToPlain),可以调用Reflect.defineMetadata('class_serializer:options', { groups: 'owner' }, Class.prototype, 'method');
    • @Mr.T 真棒昵称。这就是我非常想做的事情!我在拦截器中尝试了这条指令,但 Class.prototype 抛出错误“未找到名称类”。知道我想念什么兄弟吗?谢谢和问候
    【解决方案2】:

    你可以这样做:

    @Entity()
    @Exclude()
    export class User {
    
        @Expose()
        @PrimaryGeneratedColumn("uuid")
        id: string;
    
        @Column({nullable: true, default: null})
        public email: string;
    
        public connectedUser: string?;
    
        @Expose({ name: 'email'}) // Only if logged user
        public get hideableEmail(): string? {
            if(this.email === this.connectedUser) {
                retun this.email;
            }
            return null;
        }
    
        @Expose()
        @Column({nullable: true, default: null})
        public username: string;
    
        @Column({nullable: true, default: null})
        public password: string;
    
        @CreateDateColumn()
        public create_at: Date;
    
        @UpdateDateColumn()
        public update_at: Date;
    }
    

    【讨论】:

    • 感谢您的快速回答!如何获取实体中的 CurrentUser ?
    【解决方案3】:

    因为我花了两天时间才找到最优雅的解决方案,所以我将把它留在这里以供将来参考并节省人们的时间。 创建一个扩展 ClassSerializerInterceptor 的拦截器。 注: = 你需要让用户在上下文中注册他的角色

    import { CallHandler, ClassSerializerInterceptor, ExecutionContext, Injectable } from "@nestjs/common";
    import { Observable } from "rxjs";
    
    @Injectable()
    export class TransformWithGroupsInterceptor extends ClassSerializerInterceptor {
    
    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        const { user } = context.switchToHttp().getRequest();
        Reflect.defineMetadata('class_serializer:options', { 'groups': user.roles }, context.getHandler());
        return super.intercept(context, next);
      };
    };
    

    然后全局分配拦截器

    import { Module } from '@nestjs/common';
    import { APP_INTERCEPTOR } from '@nestjs/core';
    
    @Module({
    providers: [
      {
        provide: APP_INTERCEPTOR,
        useClass: LoggingInterceptor,
      }
    ]})
    export class AppModule {}
    

    现在你可以使用例子

    @Expose({ groups: [Role.Admin] })
    

    最好的问候

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-05
      • 2011-05-08
      • 2017-11-11
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多