es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

No se puede recuperar al usuario en AuthGuard pero sí en Decorator en NestJS.

Implementé una API Graphql en NestJS con un guardia para evitar que algunos roles accedan a ciertas rutas. Hasta ahora, puedo obtener al usuario en el decorador CurrentUser a través de GQLExecutionContext. Pero no en el Guardia.

A continuación se muestra el guardia:

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { GqlExecutionContext } from '@nestjs/graphql';

@Injectable()
export class AdminGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const roles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!roles) {
      return true;
    }
    const ctx = GqlExecutionContext.create(context);
    console.log('adminguard', ctx.getContext().req.user);
    const request = ctx.getContext().req;
    const user = request.user;
    return roles.includes(user?.role);
  }
}

y aquí está el Decorador:

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';

export const CurrentUser = createParamDecorator(
  (data: unknown, context: ExecutionContext) => {
    const ctx = GqlExecutionContext.create(context);
    console.log('current user', ctx.getContext().req.user);
    return ctx.getContext().req.user;
  },
);

Todo junto:

@Resolver(() => User)
export class UsersResolver {
  constructor(private readonly usersService: UsersService) {}

  @Roles('admin')
  @UseGuards(GqlAuthGuard)
  @Query(() => [User], { name: 'users' })
  findAll(@CurrentUser() user: User) {
    return this.usersService.findAll();
  }
}

Mi módulo de la aplicación implementa Graphql de esta manera:

GraphQLModule.forRoot({
  autoSchemaFile: './schema.gql',
  context: ({ req }) => ({ req }),
  debug: true,
  playground: true,
}),

Quiero poder obtener al usuario en el Guardia de la misma manera que lo hago con el decorador. Gracias por tu ayuda.</string[]>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Descripción del problema

    El autor implementó una API de Graphql en NestJS con un guardia para impedir que algunos roles accedieran a determinadas rutas. El autor puede obtener el usuario en el decorador CurrentUser a través de GQLExecutionContext. Sin embargo, el autor no ha podido obtener el usuario en el guardia.

    Solución

    GqlExecutionContext es una función de utilidad. Crea un contexto de ejecución (un contenedor alrededor de los argumentos de ejecución) para las operaciones de GraphQL que se están ejecutando dentro de la aplicación Nest. La función create() acepta un objeto ExecutionContext y devuelve un objeto específico de GraphQL, que proporciona métodos para obtener aspectos específicos de GraphQL de la solicitud.

    GQLExecutionContext solo se inyecta en el decorador CurrentUser. Por lo tanto, para obtener el usuario en el guardia AdminGuard, primero debemos crear un contexto de ejecución utilizando GqlExecutionContext.create() y utilizar el método getContext() para obtener la solicitud.

    Aquí está el AdminGuard actualizado para obtener el usuario utilizando GqlExecutionContext:

    @Injectable()
    export class AdminGuard implements CanActivate {
      constructor(private reflector: Reflector) {}
    
      canActivate(
        context: ExecutionContext,
      ): boolean | Promise<boolean> | Observable<boolean> {
        const roles = this.reflector.get<string[]>('roles', context.getHandler());
        if (!roles) {
          return true;
        }
        const ctx = GqlExecutionContext.create(context);
        const user = ctx.getContext().req.user;
        return roles.includes(user?.role);
      }
    }
    

    Esto debería permitirte obtener el usuario en el guardia AdminGuard utilizando GqlExecutionContext.</string[]>

Comments are closed.