Crea una cuenta o inicia sesión

¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera

No se trata de lo que quieres comprar, sino de quién quieres ser. Aprovecha el precio especial.

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

14 Días
1 Hrs
9 Min
27 Seg

Usando un decorador

5/22
Recursos

Aportes 3

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Comando para crear decorators:

nest g d auth/decorators/nombre --flat

Lo que hicimos

Esto aplica para ambos proyectos

Para proteger todo un controlador en lugar de solo una ruta en especifico, podemos asignarle el guard al controlador.

// src\app.controller.ts
...
@UseGuards(ApiKeyGuard)
@Controller()
...

Podemos crear un decorador para volver publico alguna ruta protegida.
Para ello, modificamos nuestro controlador

...
const isPublic = this.reflector.get('isPublic', context.getHandler());
    if (isPublic) {
      return true;
    }
const request = context.switchToHttp().getRequest<Request>();
    const authHeader = request.header('Auth');
    return authHeader === '1234';
  }

Creamos un decorador que nos facilite el envió de metadata a la request

// src\auth\decorators\public.decortator.ts
import { SetMetadata } from '@nestjs/common'
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);

Ahora podemos declara como publico alguna ruta protegida

@Public() // usando el decorador
  @Get('nuevo')
  newEndpoint() {
    return 'yo soy nuevo';
  }

Usando un decorador

Una funcionalidad muy útil a la hora de trabajar con nuestros guardianes es que en vez de nosotros tener que programar cual es la condición que debe cumplir el contexto que necesitamos, lo que podemos hacer es usar decoradores que validen esta información por nosotros:

Para nuestro ejemplo, lo que vamos a hacer es que vamos a proteger todos los Endpoints de nuestro controlador:

  • **src\app.controller.ts**:
// importamos el "SetMetadata"
import { Controller, Get, SetMetadata } from '@nestjs/common';

/* para que todos los enpoints de el controlador esten protegidos colocamos el 
decodador arriba del controlador */
// todos los endpoints estarán protegidos
@UseGuards(ApiKeyGuard)
@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  // SetMetadata nos permite enviar metadatos que podemos recibir en el contexto del guardian
  @SetMetadata('isPublic', true)
  getHello(): string {
    return this.appService.getHello();
  }

  // ...
}

La forma en la que vamos a utilizar este metadato que estamos enviando al contexto del guardián, en este caso va a ser para que con esa configuración protejamos todos los Endpoints del controlador, menos, el Endpoint que tenga el metadato **‘isPiblic’** en **true**.

Veamos como:

  • **src/auth/guards/api-key.guard.ts**:
// importamos al reflector
import { Reflector } from '@nestjs/core';

@Injectable()
export class ApiKeyGuard implements CanActivate {
  // debemos inyectar el reflector en nuestro guardian
  constructor(private reflector: Reflector) {}

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    // con un método del reflector, nos traemos la metadata de "isPublic"
    // con el contexto, le indicamos que recibimos un manejador
    const isPublic = this.reflector.get('isPublic', context.getHandler());

    // el parámetro tiene la propiedad "isPublic" como verdadera?
    if (isPublic) {
      // no hacemos validación
      return true;
    }

    // si en la metadata, indica que no es publico, hacemos la validación
    // ...
  }
}

De esta forma, si un parámetro tiene en sus metadatos que es publico, no se realizará la validación, pero si en sus metadatos no lo tienen, re debe realizar la validación.

Creando nuestros decoradores con metadatos

El crear nuestros propios decoradores con la metadata que necesitamos es útil para que no caigamos en errores de Typos, y también tanto para agilizar la experiencia de desarrollo, como hacer el código mucho más verboso.

Para realizar esto, vamos a crear este decorador de la siguiente forma:

  • **src\auth\decorators\public.decortator.ts**:
import { SetMetadata } from '@nestjs/common';

// instanciamos como queremos que se va a llamar la metadata
// lo exportamos por si lo queremos reutilizar en otro decodador y en el guardian
export const IS_PUBLIC_KEY = 'isPublic';

// creamos el decorador primero como una función flecha
// va a ser igual al decodador "SetMetadata", pero con el metadato "isPublic" como "true"
export const IsPublic = () => SetMetadata(IS_PUBLIC_KEY, true);

Y ahora solo tendríamos que usar este decorador de la siguiente forma:

  • **src\app.controller.ts**:
// importamos nuestro decoador
import { IsPublic } from './auth/decorators/public.decorator';

@UseGuards(ApiKeyGuard)
@Controller()
export class AppController {

  @Get()
  // lo usamos en el parámetro deseado
  @IsPublic()
  getHello(): string {
    return this.appService.getHello();
  }
}

Y listo, ahora tenemos un decorador un poco más flexible y personalizado.