DEV Community

Stanislav Karol
Stanislav Karol

Posted on

NestJS: Получить текущего пользователя когда не подключён AuthGuard

Я хочу, чтобы GET-запрос работал для всех пользователей: авторизованных и анонимных. Но мне бы хотелось, чтобы ответ авторизованному пользователю ещё дополнялся некоей дополнительной информацией. Например, заметку может получить анонимный пользователь, а зарегистрированный пользователь ещё получит информацию о статусе этой заметке: Она в избранном, автор у пользователя в друзьях и т.п.
На момент написания этой заметки у NestJS для этого функционала нет настроек. Но их можно написать самому. Я предлагаю на мой взгляд простое решение.
Сперва вводная часть: Авторизация у меня проходит при помощи jwt, поэтому в проекте обязательно должны быть сделаны рекомендованные шаги (переписывать их сюда я не стал). Вот только AuthGuard (по ссылке это класс JwtAuthGuard) должен быть другим. В поставленной задаче нам не нужно выбрасывать ошибку, так что если пользователь не авторизован, то вместо его id, email или что там у Вас в токене зашифровано, можно вернуть null.
Вот реализация этого:
jwt.guard.ts

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

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

/**
 * Неавторизованные пользователи могут воспользоваться службой.
 * При этом user будет равен null
 */
@Injectable()
export class AllowNullUserGuard extends AuthGuard('jwt') {
  handleRequest(err, user) {
    // Если пользователь на авторизован, то user = null
    return user || null;
  }
}
Enter fullscreen mode Exit fullscreen mode
  • JwtAuthGuard - это обычный guard, который следит за тем, чтобы неавторизованный пользователь не прошёл.
  • AllowNullUserGuard - это кастомный guard, который не будет выбрасывать ошибку, если пользователь не авторизовался, а будет выдавать null. Использование его в деле может быть например таким:
  @Get(':slug')
  @UseGuards(AllowNullUserGuard)
  async getSingleArticle(
    @Param('slug') slug: string,
    @User() currentUser: UserEntity | null,
  ) {
    return currentUser;
  }
Enter fullscreen mode Exit fullscreen mode

Здесь используется декоратор @User :

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

import { ExpressRequest } from '@app/types/expressRequest.interface';

export const User = createParamDecorator((data: any, ctx: ExecutionContext) => {
  const request = ctx.switchToHttp().getRequest<ExpressRequest>();
  if (!request.user) return null;

  if (data) {
    return request.user[data];
  }
  return request.user;
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)