Nest не может разрешить зависимости JwtStrategy - PullRequest
2 голосов
/ 01 августа 2020

Я новичок ie в мире Nest Js. Насколько мне известно, я импортировал все необходимое в JwtStrategy. Я не знаю, где что-то пошло не так. Может ли кто-нибудь помочь мне в этом?

Что касается документации, всякий раз, когда мы хотим использовать какую-либо сущность в модуле, мы должны импортировать эту сущность в поле импорта в декораторе @Module (). Я сделал это.

jwt.strategy.ts

import { Injectable, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { Strategy, ExtractJwt } from "passport-jwt";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { UserEntity } from "src/entities/user.entity";
import { AuthPayload } from "src/common/dtos/user.dto";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(
        @InjectRepository(UserEntity)
        private userRepo: Repository<UserEntity>
    ) {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            secretOrKey: process.env.SECRETKEY
        });
    }

    async validate(payload: AuthPayload): Promise<UserEntity> {
        const { username } = payload;
        const user = this.userRepo.findOne({ where: { username: username } });
        if(!user) {
            throw new UnauthorizedException();
        }
        return user;
    }
}

auth.module.ts

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserEntity } from 'src/entities/user.entity';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './jwt.strategy';

@Module({
  imports: [
    TypeOrmModule.forFeature([UserEntity]),
    JwtModule.register({
      secret: process.env.SECRETKEY,
    }),
    PassportModule.register({
      defaultStrategy: 'jwt'
    })
  ],
  providers: [AuthService, JwtStrategy],
  controllers: [AuthController],
  exports: [PassportModule, JwtStrategy]
})
export class AuthModule {}

user.entity.ts

import { Entity, Column, OneToMany, JoinTable, BeforeInsert } from "typeorm";
import { AbstractEntity } from "./abstract-entity.abstract";
import { IsEmail } from "class-validator";
import { Exclude, classToPlain } from "class-transformer";
import * as bcrypt from "bcryptjs";
import { CategoryEntity } from "./category.entity";
import { ArticleEntity } from "./article.entity";

@Entity('User')
export class UserEntity extends AbstractEntity {
    @Column({
        type: "varchar",
        length: 80
    })
    fullName: string;

    @Column({
        type: "varchar",
        unique: true
    })
    @IsEmail()
    email: string;

    @Column({
        type: "varchar",
        unique: true
    })
    username: string;

    @Column({
        type: "varchar"
    })
    @Exclude()
    password: string;

    @Column({
        default: null,
        nullable: true
    })
    avatar: string | null;

    @Column({
        type: "varchar",
        unique: true
    })
    phoneNumber: string;

    @Column({
        type: "boolean",
        default: false
    })
    isAdmin: boolean;

    @Column({
        type: "boolean",
        default: false
    })
    isStaff: boolean;

    @Column({
        type: "boolean",
        default: false
    })
    isEmailVerified: boolean;

    @OneToMany(type => CategoryEntity, category => category.createdBy)
    @JoinTable()
    categories: CategoryEntity[];

    @OneToMany(type => ArticleEntity, article => article.createdBy)
    @JoinTable()
    articles: ArticleEntity[];

    @BeforeInsert()
    async hashPassword() {
        this.password = await bcrypt.hash(this.password, 10);
    }

    async comparePassword(attempt: string): Promise<boolean> {
        return await bcrypt.compare(attempt, this.password);
    }

    toJSON(): any {
        return classToPlain(this);
    }
}

app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from "@nestjs/typeorm";
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
import { 
  DatabaseConnectionService
 } from "./utils/database-connection.service";
import { AuthModule } from './auth/auth.module';
import { UsersModule } from './users/users.module';
import { ArticlesModule } from './articles/articles.module';
import { HttpExceptionFilter } from './common/exception-filters/http-exception.filter';
import { ResponseInterceptor } from './common/interceptors/response.interceptor';
import { CategoryModule } from './category/category.module';

@Module({
  imports: [
    TypeOrmModule.forRootAsync({
      useClass: DatabaseConnectionService
    }),
    AuthModule,
    UsersModule,
    ArticlesModule,
    CategoryModule,
  ],
  controllers: [AppController],
  providers: [
    // {
    //   provide: APP_INTERCEPTOR,
    //   useClass: ResponseInterceptor
    // },
    {
      provide: APP_FILTER,
      useClass: HttpExceptionFilter
    },
    AppService
  ],
})
export class AppModule {}

database-connection.service.ts

import { Injectable } from "@nestjs/common";
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from "@nestjs/typeorm";
import { truncate } from "fs";

@Injectable()
export class DatabaseConnectionService implements TypeOrmOptionsFactory {
    createTypeOrmOptions(): TypeOrmModuleOptions {
        return {
            type: "mysql",
            host: process.env.HOST,
            port: parseInt(process.env.PORT),
            username: process.env.DB_USERNAME,
            password: process.env.DB_PASSWORD,
            database: process.env.DATABASE, 
            entities: [__dirname + '/**/*.entity{.ts,.js}'],
            synchronize: true,
            dropSchema: true,
            autoLoadEntities: true,
            logger: "simple-console"
        };
    }
}

Ошибка выглядит следующим образом: введите описание изображения здесь

Ответы [ 2 ]

2 голосов
/ 01 августа 2020

Исходя из вашей ошибки, где-то у вас есть JwtStrategy в массиве imports. Если вам нужен JwtStrategy, вы должны вместо этого импортировать AuthModule, поскольку поставщики должны быть только в массиве providers и никогда не должны быть в imports.

2 голосов
/ 01 августа 2020

Рассмотрите возможность перехода на шаблон Active Record. Все, что вам нужно сделать, это просто позволить вашему AbstractEntity расширять BaseEntity TypeOrm.

Вы можете удалить все импортированные функции typeorm, такие как:

TypeOrmModule.forFeature([UserEntity])

и все инъекции зависимостей для репозиторий, например:

@InjectRepository(UserEntity)
private userRepo: Repository<UserEntity>

Просто используйте класс сущности для запроса:

const user = await UserEntity.findOne({ where: { username: username } });
...