Пользовательский декоратор NestJS возвращает undefined
Доброе утро,
Я пытаюсь создать собственный декоратор:user.decorator.ts
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const User = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
return data ? user && user[data] : user;
},
);
user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, BeforeInsert } from "typeorm";
import * as bcrypt from 'bcryptjs';
import * as jwt from 'jsonwebtoken';
import { UserRO } from "./user.dto";
@Entity("user")
export class UserEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({
type: 'varchar',
length: 50,
unique: true,
})
username: string;
@Column('text')
password: string;
@Column('text')
role: string;
(...)
}
И наконец, user.controller.ts
(только полезная часть):
(...)
@Post('login')
@UsePipes(new ValidationPipe())
login(@Body() data: UserDTO, @User('role') role: string) {
console.log(`hello ${role}`);
return this.userService.login(data);
(...)
}
Моя проблема: console.log(...) возвращает мне hello undefined
, когда ожидаемый ответ должен быть hello admin
(поскольку администратор - это роль пользователя в базе данных)
РЕДАКТИРОВАТЬ: я также пытался console.log(user)
в моем декораторе, и он тоже не определен.
EDIT2: Мой HttpErrorFilter также говорит: Cannot read property 'role' of undefined
Я внимательно следил за документацией и не могу понять, в чем проблема ( https://docs.nestjs.com/custom-decorators).
Спасибо за ваше время.
4 ответа
Я тоже был смущен этим. Я обновился до NestJS 7 и, следуя руководству по миграции, пытался обновить свой пользовательский декоратор.
Часть, которую я не мог заставить работать, это const request = ctx.switchToHttp().getRequest();
. По какой-то причинеgetRequest()
возвращался неопределенным.
Что сработало для меня:
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const CurrentUser = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
return ctx.getArgByIndex(2).req.user;
}
);
Документы по контексту выполнения не рекомендуютgetArgByIndex()
, поэтому я уверен, что делаю что-то простое неправильно. Интересно, что скажут другие ответы и комментарии.
Я нашел решение.
В user.decorator.ts
:
+ Изменить const user = request.user;
с const user = request.body;
Согласно документу nestjs, это должно быть .user
но когда я более подробно изучил запрос, я заметил, что там не было "пользователя", а было "тело" со всей информацией. ( https://docs.nestjs.com/custom-decorators)
Не могу сказать, ошибся ли я раньше или документ просто устарел.
Проблема решена вообще!
РЕДАКТИРОВАТЬ: 2-е решение:
Я забыл использовать @UseGuards(new AuthGuard())
сверху, а request.user
создается с помощью AuthGuard..
Если вы используете один и тот же декоратор для HTTP(REST) и graphql
if (ctx.getType() == 'http') {
return ctx.switchToHttp().getRequest().user;
} else {
const gqlContext = GqlExecutionContext.create(ctx);
return gqlContext.getContext().user;
}
Я был зол на этот пустой / неопределенный запрос. Потому что эта информация в документации (кастомные декораторы) у меня не работала. Я использую graphql + typescript. Тогда волшебство было таким:
export const CurrentUser = createParamDecorator(
(data: unknown, context: ExecutionContext) => {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext().req.user;
},
);