DEV Community

Stanislav Karol
Stanislav Karol

Posted on

1 1

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

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more