You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestJS混入类(Mixin)守卫中注入PrismaService?

解决NestJS带参数守卫中注入PrismaService的问题

方法一:为动态混入类添加@Injectable()装饰器

这是最直接的解决方案,通过给动态生成的守卫类添加@Injectable()装饰器,让Nest的依赖注入容器识别并管理这个类,从而自动注入PrismaService。

修改后的完整代码:

import { Injectable, mixin, CanActivate, ExecutionContext } from '@nestjs/common';
import { PrismaService } from './prisma.service'; // 替换为你的PrismaService实际路径

export const UserGuard = (table: Prisma.ModelName, field: string) => {
  @Injectable()
  class RoleGuardMixin implements CanActivate {
    // 通过构造函数注入PrismaService,并使用private readonly确保可访问
    constructor(private readonly prismaService: PrismaService) {}

    async canActivate(context: ExecutionContext) {
      // 示例逻辑:从请求中获取用户ID,查询对应表的记录
      const request = context.switchToHttp().getRequest();
      const userId = request.user.id; // 假设请求对象中携带用户信息

      const subject = await this.prismaService[table].findUnique({
        where: { [field]: userId },
      });

      // 根据查询结果返回权限验证结果,这里示例为存在则通过
      return !!subject;
    }
  }

  return mixin(RoleGuardMixin);
};

关键说明

  • @Injectable()是核心:它标记动态类为Nest DI容器的管理对象,确保PrismaService能被自动注入。
  • 构造函数中必须使用private readonly:否则this.prismaService无法在canActivate方法中访问。

方法二:使用ModuleRef手动获取服务

如果某些场景下自动注入不生效,可以通过ModuleRef手动从DI容器中获取PrismaService,适合更复杂的动态场景。

代码示例:

import { Injectable, mixin, CanActivate, ExecutionContext, ModuleRef } from '@nestjs/common';
import { PrismaService } from './prisma.service';

export const UserGuard = (table: Prisma.ModelName, field: string) => {
  @Injectable()
  class RoleGuardMixin implements CanActivate {
    private readonly prismaService: PrismaService;

    constructor(private readonly moduleRef: ModuleRef) {
      // 从模块引用中获取PrismaService,strict: false允许获取全局注册的服务
      this.prismaService = moduleRef.get(PrismaService, { strict: false });
    }

    async canActivate(context: ExecutionContext) {
      const request = context.switchToHttp().getRequest();
      const userId = request.user.id;

      const subject = await this.prismaService[table].findUnique({
        where: { [field]: userId },
      });

      return !!subject;
    }
  }

  return mixin(RoleGuardMixin);
};

使用方式

在控制器中直接调用带参数的守卫工厂函数即可:

import { Controller, Get, UseGuards } from '@nestjs/common';
import { UserGuard } from './user.guard';

@Controller('users')
export class UsersController {
  @UseGuards(UserGuard('User', 'id'))
  @Get()
  async getCurrentUser() {
    // 控制器逻辑
  }
}

前置条件

确保PrismaService已正确注册:

  • 要么在PrismaModule上添加@Global()装饰器,使其成为全局服务;
  • 要么在使用守卫的模块中导入PrismaModule。

内容的提问来源于stack exchange,提问作者Tevon Strand-Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:35:17