简体   繁体   中英

NestJS setMetadata not working from authGuard

I have a few decorators that when called, I want to setMetadata to use it in my logging, In my controller, I have these:

  @Post("somePath")
  @Permission("somePermission")
  @UseGuards(JwtAuthGuard)
  @HttpCode(200)
  @Grafana(
    "endpoint",
    "functionalmap"
  )
  async getSubscriptionFromPwebFormFilter(
    @Body(ValidationPipe) someDto: someDtoType
  ): Promise<ISuccessResponse> {
    // some logic
  }

In my decorators I want to set some data into the metadata to use in my logging inteceptor,

Grafana decorator:

  export const Grafana = (functionalMap: string, endpoint: string) =>
    applyDecorators(
      SetMetadata("endpoint", endpoint),
      SetMetadata("functionalMap", functionalMap)
    );

AuthGuard decorator:

  @Injectable()
  export class JwtAuthGuard extends AuthGuard("jwt") {
    constructor(
      private readonly reflector: Reflector,
      private readonly someService: SomeService
    ) {
      super();
    }

    public async canActivate(context: ExecutionContext): Promise<boolean> {
      const role = this.reflector.get<string>("permission", context.getHandler());
      const request = context.switchToHttp().getRequest();
      const { valueToLog } = request.body;
      const jwtToken = request.headers.authorization;

      console.log("check value exist", valueToLog);
      SetMetadata("valueToLog", valueToLog);
  }

Now, in my logging interceptor, I am getting all the values of the metadata this way:

    @Injectable()
    export default class LoggingInterceptor {
      constructor(private readonly reflector: Reflector) {}

      intercept(context: ExecutionContext, next: CallHandler) {
        const executionStart = Date.now();

        return next.handle().pipe(
          tap((responseData) => {
            const response = context.switchToHttp().getResponse<ServerResponse>();
            const { statusCode } = response;
            const valueToLog = this.reflector.get(
              "valueToLog",
              context.getHandler()
            ); // this is undefined
            const endpoint = this.reflector.get("endpoint", context.getHandler()); // this have value
            const functionalMap = this.reflector.get(
              "functionalMap",
              context.getHandler()
            ); // this have value
            
            ... 
            // some logic
          })
        );
      }
    }

In my case, the value of endpoint and functionalMap can be retrieved from the reflector, however, valueToLog is appearing as undefined,

Is setting of metadata not working for auth guard decorator?

I will be using the term "Decorator" in this explanation so I will first define it.

Decorators are functions that accept information about the decorated declaration.

Ex:

function ClassDecorator(target: typeof DecoratedClass) {
  // do stuff
}

// it can then be used like this
@ClassDecorator
class DecoratedClass {}

when calling @SetMetadata(key, value) it returns a decorator. Functions like SetMetadata are referred to as Decorator Factories .

Decorators use the form @expression, where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.

In your example you called SetMetadata("valueToLog", valueToLog) . This returns a decorator. Decorators must be called with information about the decorated declaration. To actually attach the metadata you can do something like this:

SetMetadata("valueToLog", valueToLog)(context.getHandler());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM