question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support request-scoped, global enhancers

See original GitHub issue

I’m submitting a…


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

The transform method of global pipes is not called.

Expected behavior

The transform method of global pipes should be called before calling a resolver method.

Minimal reproduction of the problem with instructions

core.module.ts

providers: [
      {
        provide: APP_PIPE,
        scope: Scope.REQUEST,
        useClass: CheckInputPipe,
      }
]

check-input.pipe.ts

@Injectable({ scope: Scope.REQUEST })
export class CheckInputPipe implements PipeTransform<any> {

  constructor(@Inject(CONTEXT) private readonly context) {}

  async transform(value: any, { metatype }: ArgumentMetadata) {
    console.log('Transform method is called!'); 
  }

Console log does not occur.

To test this, you can use the following repository:
https://github.com/yostools/nest-example

clone https://github.com/yostools/nest-example.git
cd nest-example
npm i
npm run test:e2e

If everything would work, the console log Current context should appear.

What is the motivation / use case for changing the behavior?

I would like to use a global pipe that compares the input with the rights of the current user and only passes on the inputs to which the user has authorization.

check-input.pipe.ts

import { ArgumentMetadata, BadRequestException, Inject, Injectable, PipeTransform, Scope } from '@nestjs/common';
import { CONTEXT } from '@nestjs/graphql';
import { plainToClass } from 'class-transformer';
import { validate, ValidationError } from 'class-validator';
import { checkRestricted } from '../decorators/restricted.decorator';
import { Context } from '../helpers/context.helper';

/**
 * The CheckInputPipe checks the permissibility of individual properties of inputs for the resolvers
 * in relation to the current user
 */
@Injectable({ scope: Scope.REQUEST })
export class CheckInputPipe implements PipeTransform<any> {

  /**
   * Constructor to inject context
   */
  constructor(@Inject(CONTEXT) private readonly context) {}

  /**
   * Check input
   */
  async transform(value: any, { metatype }: ArgumentMetadata) {

    // Return value if it is only a basic type
    if (!metatype || this.isBasicType(metatype)) {
      return value;
    }

    // Remove restricted values if roles are missing
    const { user }: any = Context.getData(this.context);
    value = checkRestricted(value, user);

    // Validate value
    const plainValue = JSON.parse(JSON.stringify(value));
    const object = plainToClass(metatype, plainValue);
    const errors: ValidationError[] = await validate(object);

    // Check errors
    if (errors.length > 0) {
      throw new BadRequestException('Validation failed');
    }

    // Everything is ok
    return value;
  }

  /**
   * Checks if it is a basic type
   */
  private isBasicType(metatype: any): boolean {
    const types = [String, Boolean, Number, Array, Object, Buffer, ArrayBuffer];
    return types.includes(metatype);
  }
}

Environment


Nest version: 6.5.2
 
For Tooling issues:
- Node version: 12.4.0
- Platform:  Mac

Others:
The error has occurred since version 6.5.0.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:8
  • Comments:17 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
jmcdo29commented, Nov 21, 2020

For anyone coming to this issue at the moment, request scoping an interceptor or guard doesn’t make much sense because they already have access to the request object. What can be done, is inject the ModuleRef class and get the request scoped instance of the class. A sample of this would look something like

@Injectable()
export class InterceptorUsingReqScopedProvider implements NestInterceptor {
  constructor(private readonly modRef: ModuleRef) {}

  async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<unknown>> {
    const req = this.getRequest(context);
    const contextId = ContextIdFactory.getByRequest(req);
    const service = await modRef.resolve(ServiceName, contextId);
    // do something with the service
    return next.handle();
    // can also work in the `.pipe` of the observable
  }

  getRequest(context: ExecutionContext) {
    // this can have added logic to take care of REST and other contexts 
    const gql = GqlExecutionContext.create(context);
    return gql.getContext().req;
  }
}

To make sure this works, you should also make sure to set up the context properly from the GraphqlModule like so

GraphqlModule.forRoot({
  context: ({ req }) => ({ req }),
  // other options
})
4reactions
lnmunhozcommented, Aug 12, 2019

The intercept method is also not being called in case of an Interceptor. I think for the graphql package in general the request scoped providers are not being invoked.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Enhancement Properties - Apache Stanbol
Globally defined properties use ' enhancer. ... Regardless of the defined data type Enhancement Engines that support a property MUST support to parse...
Read more >
Testing | NestJS - A progressive Node.js framework
Let's introduce some more advanced capabilities that help you test applications ... to dynamically resolve scoped providers (transient or request-scoped).
Read more >
NestJS inject service in guard - Stack Overflow
When now trying to inject a service, let's say AuthService ... No it is neither REQUEST scoped nor does anything inject REQUEST.
Read more >
Using Hibernate ORM and JPA - Quarkus
quarkus.hibernate-orm.database.globally-quoted-identifiers ... If Hibernate ORM should create the schemas automatically (for databases supporting them).
Read more >
RequestScoped (Java EE 6 ) - Oracle Help Center
Specifies that a bean is request scoped. The request scope is active: during the service() method of any servlet in the web application, ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found