Получить текущего пользователя в гнезде js на маршруте без AuthGuard - PullRequest
1 голос
/ 05 августа 2020

Я использую гнездо js с паспортом со стратегией jwt. И я хочу получить текущего пользователя по некоторым из моих запросов. В настоящее время у меня есть декоратор, который выглядит так:

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

export const CurrentUser = createParamDecorator(
  (data: string, ctx: ExecutionContext) => {
    const user = ctx.switchToHttp().getRequest().user;

    if (!user) {
      return null;
    }

    return data ? user[data] : user; // extract a specific property only if specified or get a user object
  },
);

Он работает как задумано, когда я использую его на маршруте с AuthGuard:

@Get('test')
  @UseGuards(AuthGuard())
  testRoute(@CurrentUser() user: User) {
    console.log('Current User: ', user);
    return { user };
  }

Но как мне заставить его работать (получить текущего пользователя) на неохраняемых маршрутах? Мне нужно, чтобы пользователи могли публиковать свои комментарии независимо от того, авторизованы они или нет, однако, когда они вошли в систему, мне нужно узнать их имя.

В основном, мне нужен способ распространить req. пользователь для каждого (или, по крайней мере, для некоторых запросов, не связанных с AuthGuard), это действительно просто сделать в express, применив промежуточное ПО для паспорта, но я не уверен, как это сделать с помощью @ nestjs / паспорт.

[РЕДАКТИРОВАТЬ] Благодаря vpdiongzon за то, что он указал мне в правильном направлении, я решил создать охрану на основе его ответа, который просто заполняет req.user либо пользователем, либо нулем:

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class ApplyUser extends AuthGuard('jwt') {
  handleRequest(err: any, user: any) {
    if (user) return user;
    return null;
  }
}

И теперь я мог бы просто использовать его на любом незащищенном маршруте, который должен получить текущего пользователя

@Get('me')
@UseGuards(ApplyUser)
me(@CurrentUser() user: User) {
  return { user };
}

1 Ответ

3 голосов
/ 05 августа 2020

Вам необходимо применить AuthGuard к каждому маршруту независимо от того, но если у вас есть маршрут, не требующий аутентификации, просто добавьте собственный декоратор, например:

Auth Guard

export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(private readonly reflector: Reflector) {
    super();
  }

  handleRequest(err, user, info, context) {
    const request = context.switchToHttp().getRequest();       

    const allowAny = this.reflector.get<string[]>('allow-any', context.getHandler());
    if (user) return user;
    if (allowAny) return true;
    throw new UnauthorizedException();
  }
}

Применить глобально AuthGuard в app.module. js

import { APP_GUARD, Reflector } from '@nestjs/core';
import { AppController } from './app.controller';
import { JwtAuthGuard } from './app.guard';



@Module({
  imports: ],
  controllers: [AppController],
  providers: [
    {
      provide: APP_GUARD,
      useFactory: ref => new JwtAuthGuard(ref),
      inject: [Reflector],
    },
    AppService,
  ],
})
export class AppModule {
}

Пользовательский декоратор для разрешения маршрута без аутентификации

import { SetMetadata } from '@nestjs/common';

export const AllowAny = () => SetMetadata('allow-any', true);

Применить AllowAny в маршруте, если декоратор AllowAny не привязан к маршруту контроллера, для него потребуется пользователь.

  @Post('testPost')
  @AllowAny()
  async testPost(@Req() request) {
    console.log(request.user)
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...