【问题标题】:Set role for all TypeORM connections through NestJS通过 NestJS 为所有 TypeORM 连接设置角色
【发布时间】:2021-12-24 04:33:18
【问题描述】:

我通过 NestJS 使用 TypeORM 连接到 PostgreSQL 数据库。对于我与数据库建立的每个连接,我都需要“SET ROLE my-service”,最好只在建立连接时进行一次。我有哪些选择?

我试图找到一种使用传递给 TypeOrmModule.forRoot() 的配置的方法。我已经考虑过我可以提前向 PostgreSQL 客户端发出指令的可能性,但我对如何做到这一点没有强烈的意识。

【问题讨论】:

    标签: nestjs typeorm


    【解决方案1】:

    请根据您未填写的问题滚动到更新 2。


    选项 1:作为injectable service

    您可以将服务SomeTypeOrmConfigService 创建为@Injectable(),然后像这样注入它。

    import { Injectable } from '@nestjs/common';
    import { ConfigService } from '@nestjs/config';
    import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
    
    
    // create your injectable here
    @Injectable()
    export class SomeTypeOrmConfigService implements TypeOrmOptionsFactory {
      constructor(private configService: ConfigService) {}
    
      createTypeOrmOptions(): TypeOrmModuleOptions {
        return {
          type: 'mysql',
          host: this.configService.get('DATABASE_HOST'),
          username: this.configService.get('DATABASE_USERNAME'),
          password: this.configService.get('DATABASE_PASSWORD'),
        };
      }
    }
    

    选项 2:将信息保存在通用 .env 中,或 b) 另一种方法 database.provider.ts 文件并将复制的 ans./credit 导出到 from here
    import { ConfigModule, ConfigService } from '@nestjs/config';
    import { TypeOrmModule } from '@nestjs/typeorm';
    
    export const databaseProviders = [
      TypeOrmModule.forRootAsync({
        imports: [ConfigModule],
        inject: [ConfigService],
        useFactory: (configService: ConfigService) => ({
          type: 'postgres',
          host: configService.get('PGHOST'),
          port: +configService.get<number>('PGPORT'),
          username: configService.get('PGUSER'),
          password: configService.get('PGPASSWORD'),
          database: configService.get('PGDATABASE'),
          entities: ['dist/**/*.entity{.ts,.js}'],
          synchronize: false,
          logging: true,
        }),
      }),
    ];
    

    然后在你的database.module.ts中导入它

    import { databaseProviders } from './database.provider';
    import { DatabaseService } from './database.service';
    import { Module } from '@nestjs/common';
    @Module({
      imports: [...databaseProviders],
      providers: [DatabaseService],
      exports: [...databaseProviders],
    })
    export class DatabaseModule {}

    仅此而已,您可以根据需要在 database.provider.ts 中添加多个连接,此外,不要忘记在根模块中创建 .env 并导入数据库模块。


    更新答案 (V2) 以更新问题

    简而言之.. 我认为你错过了 a) 像 nestjs-session 这样的会话模块,一旦你使用它,你就可以选择 b) 将它缓存在你的角色中与您的会话对象

    第一步:使用nestjs-session

    第 2 步:现在您可以在 requestsession 属性对象中访问/使用 role

    第 3 步:然后您可以在 NestSessionOptions 的帮助下将其设为可注射工厂或用户工厂


    我的谦虚建议,节省自己的时间,使用预卷包作为装饰器。试试这个package from here - 使用他们的示例参考。下面 ->

    npm i nestjs-roles

    1。创建您的角色

    // role.enum.ts
    
    export enum Role {
      ADMIN = 'ADMIN',
      USER = 'USER',
      MODERATOR = 'MODERATOR',
    }
    

    2。假设您使用nestjs-session 并在请求的会话属性对象中保留角色。那么使用 getRole 回调创建守卫

    // roles.guard.ts
    
    import { ExecutionContext } from '@nestjs/common';
    import { createRolesGuard } from 'nestjs-roles';
    import { Role } from './role.enum';
    
    function getRole(context: ExecutionContext) {
      const { session } = context.switchToHttp().getRequest();
      if (!session) {
        return;
      }
      return (session as { role?: Role }).role;
    }
    
    export const Roles = createRolesGuard<Role>(getRole);
    

    3。之后我们可以全局设置 Roles 守卫(不要忘记传递 Reflector 实例):

    // bootstrap.ts
    
    import { NestFactory, Reflector } from '@nestjs/core';
    import { Roles } from './roles.guard';
    
    const app = await NestFactory.create(AppModule);
    
    const reflector = app.get<Reflector>(Reflector);
    app.useGlobalGuards(new Roles(reflector));
    

    4。所有设置都完成了。现在您可以在控制器中设置访问权限:

    // secrets.controller.ts
    
    import { Roles } from './roles.guard';
    
    @Controller('secrets')
    @Roles.Params(true) // setup access on Controller for users with any existing role
    export class SecretsController {
    
      @Get('my')
      async readMy() {
        // ...
      }
    
      @Patch(':id')
      @Roles.Params(Role.ADMIN) // override access on certain handler
      async update() {
        // ...
      }
    }
    

    【讨论】:

    • 感谢您的回复。要么我误解了您的信息,要么我的问题描述不充分。我在建立联系时没有问题。事实上,我正在以与您非常相似的方式建立连接。我无法告诉 TypeORM “既然你已经为我建立了连接,请发出 'SET ROLE my-service'。”我不知道如何利用您发布的信息将该详细信息添加到创建连接的业务中。
    • 不用担心,一切都好,感谢您的澄清。您是否尝试过角色守卫服务,让我为您添加一些内容,也许一些链接可以帮助您。
    • 感谢您的努力。谢谢你。但是,您仍然没有解决问题。我需要在每个数据库连接上设置一个角色。考虑使用数据库管理工具或某种工具连接到数据库,然后执行“SET ROLE myrole”。您将更改数据库响应该连接上的请求的方式。我需要对 TypeORM 进行的所有连接都这样做。
    猜你喜欢
    • 2020-12-20
    • 2018-12-25
    • 2020-09-13
    • 2019-08-13
    • 2022-01-21
    • 2021-08-05
    • 2019-08-02
    • 2021-09-08
    • 2021-12-03
    相关资源
    最近更新 更多