Stanislav Karol
Posted on July 17, 2021
Я хочу, чтобы 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;
}
}
- JwtAuthGuard - это обычный guard, который следит за тем, чтобы неавторизованный пользователь не прошёл.
- AllowNullUserGuard - это кастомный guard, который не будет выбрасывать ошибку, если пользователь не авторизовался, а будет выдавать null. Использование его в деле может быть например таким:
@Get(':slug')
@UseGuards(AllowNullUserGuard)
async getSingleArticle(
@Param('slug') slug: string,
@User() currentUser: UserEntity | null,
) {
return currentUser;
}
Здесь используется декоратор @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;
});
Posted on July 17, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.