Пользовательский декоратор 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;
    },
);
Другие вопросы по тегам