From b165e97500df927e7942e0991155e581f824bb81 Mon Sep 17 00:00:00 2001 From: COOL Date: Sat, 18 Jan 2025 21:43:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E7=A7=9F=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/config/config.default.ts | 4 + src/config/config.local.ts | 4 +- src/modules/base/config.ts | 2 +- src/modules/base/db/tenant.ts | 113 +++++++++++++++++---- src/modules/base/entity/base.ts | 7 +- src/modules/base/middleware/authority.ts | 1 + src/modules/base/service/sys/login.ts | 1 + src/modules/demo/controller/admin/goods.ts | 13 ++- src/modules/demo/controller/open/goods.ts | 8 +- src/modules/demo/service/goods.ts | 16 ++- src/modules/swagger/config.ts | 2 +- 12 files changed, 141 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 1bc2d00..894fe4a 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "private": true, "dependencies": { "@cool-midway/core": "file:/Users/ap/Documents/src/admin/midway-packages/core", - "@cool-midway/task": "file:/Users/ap/Documents/src/admin/midway-packages/task", "@cool-midway/rpc": "file:/Users/ap/Documents/src/admin/midway-packages/rpc", + "@cool-midway/task": "file:/Users/ap/Documents/src/admin/midway-packages/task", "@midwayjs/bootstrap": "^3.20.0", "@midwayjs/cache-manager": "^3.20.0", "@midwayjs/core": "^3.20.0", diff --git a/src/config/config.default.ts b/src/config/config.default.ts index 7ca802e..405c970 100644 --- a/src/config/config.default.ts +++ b/src/config/config.default.ts @@ -13,6 +13,10 @@ export default { koa: { port: 8001, }, + // 开启异步上下文管理 + asyncContextManager: { + enable: true, + }, // 静态文件配置 staticFile: { buffer: true, diff --git a/src/config/config.local.ts b/src/config/config.local.ts index bb22421..5597964 100644 --- a/src/config/config.local.ts +++ b/src/config/config.local.ts @@ -28,10 +28,10 @@ export default { // 实体与路径,跟生成代码、前端请求、swagger文档相关 注意:线上不建议开启,以免暴露敏感信息 eps: true, // 是否自动导入模块数据库 - initDB: true, + initDB: false, // 判断是否初始化的方式 initJudge: 'db', // 是否自动导入模块菜单 - initMenu: true, + initMenu: false, } as CoolConfig, } as MidwayConfig; diff --git a/src/modules/base/config.ts b/src/modules/base/config.ts index 77d851a..6b920d0 100644 --- a/src/modules/base/config.ts +++ b/src/modules/base/config.ts @@ -12,7 +12,7 @@ export default () => { // 模块描述 description: '基础的权限管理功能,包括登录,权限校验', // 中间件 - globalMiddlewares: [BaseAuthorityMiddleware, BaseLogMiddleware], + globalMiddlewares: [BaseAuthorityMiddleware], // 模块加载顺序,默认为0,值越大越优先加载 order: 10, // app参数配置允许读取的key diff --git a/src/modules/base/db/tenant.ts b/src/modules/base/db/tenant.ts index 115b350..c5506a8 100644 --- a/src/modules/base/db/tenant.ts +++ b/src/modules/base/db/tenant.ts @@ -1,34 +1,105 @@ import { EventSubscriberModel } from '@midwayjs/typeorm'; -import { EntitySubscriberInterface, TransactionCommitEvent } from 'typeorm'; -import { BeforeQueryEvent } from 'typeorm/subscriber/event/QueryEvent'; +import { + DeleteQueryBuilder, + EntitySubscriberInterface, + InsertQueryBuilder, + SelectQueryBuilder, + UpdateQueryBuilder, +} from 'typeorm'; import * as _ from 'lodash'; -import { App, IMidwayApplication } from '@midwayjs/core'; +import { + App, + ASYNC_CONTEXT_KEY, + ASYNC_CONTEXT_MANAGER_KEY, + AsyncContextManager, + IMidwayApplication, + IMidwayContext, + Inject, +} from '@midwayjs/core'; + +/** + * 不操作租户 + * @param ctx + * @param func + */ +export const noTenant = async (ctx, func) => { + let result; + const tenantId = ctx?.admin?.tenantId; + if (tenantId) { + ctx.admin.tenantId = null; + result = await func(); + ctx.admin.tenantId = tenantId; + } else { + result = await func(); + } + return result; +}; @EventSubscriberModel() export class TenantSubscriber implements EntitySubscriberInterface { @App() app: IMidwayApplication; + @Inject() + ctx: IMidwayContext; + /** - * 查询前 - * @param event + * 从登录的用户中获取租户ID + * @returns string | undefined */ - // @ts-ignore - beforeQuery(event: BeforeQueryEvent, query: string, parameters: any[]) { - if (_.startsWith(event.query, 'SELECT')) { - console.log('event.query', this.app); - query = 'SELECT * FROM "tenant11"'; - // // 参数 - // const parameters = event.parameters; - // // 连接 - // const queryRunner = event.connection.createQueryRunner(); - // event.connection.destroy(); - // // // sql语句 - // // const query = event.query; - // // const queryRunner = connection.createQueryRunner(); - // // 原来的event.queryRunner 干掉 - // event.query = 'SELECT * FROM "tenant11"'; - // throw new Error('test'); + getTenantId(): number | undefined { + const contextManager: AsyncContextManager = this.app + .getApplicationContext() + .get(ASYNC_CONTEXT_MANAGER_KEY); + const ctx: any = contextManager.active().getValue(ASYNC_CONTEXT_KEY); + const url = ctx?.url; + if (_.startsWith(url, '/admin/')) { + return ctx?.admin?.tenantId; } } + + /** + * 查询时添加租户ID条件 + * @param queryBuilder + */ + afterSelectQueryBuilder(queryBuilder: SelectQueryBuilder) { + const tenantId = this.getTenantId(); + if (tenantId) { + queryBuilder.where('tenantId = :tenantId', { tenantId }); + } + } + + // /** + // * 插入时添加租户ID + // * @param queryBuilder + // */ + // async afterInsertQueryBuilder(queryBuilder: InsertQueryBuilder) { + // const tenantId = await this.getTenantId(); + // if (tenantId) { + // queryBuilder.values({ tenantId }); + // } + // } + + // /** + // * 更新时添加租户ID和条件 + // * @param queryBuilder + // */ + // async afterUpdateQueryBuilder(queryBuilder: UpdateQueryBuilder) { + // const tenantId = await this.getTenantId(); + // if (tenantId) { + // queryBuilder.set({ tenantId }); + // queryBuilder.where('tenantId = :tenantId', { tenantId }); + // } + // } + + // /** + // * 删除时添加租户ID和条件 + // * @param queryBuilder + // */ + // async afterDeleteQueryBuilder(queryBuilder: DeleteQueryBuilder) { + // const tenantId = await this.getTenantId(); + // if (tenantId) { + // queryBuilder.where('tenantId = :tenantId', { tenantId }); + // } + // } } diff --git a/src/modules/base/entity/base.ts b/src/modules/base/entity/base.ts index 1db5f2b..3b7506b 100644 --- a/src/modules/base/entity/base.ts +++ b/src/modules/base/entity/base.ts @@ -3,6 +3,7 @@ import { UpdateDateColumn, CreateDateColumn, PrimaryGeneratedColumn, + Column, } from 'typeorm'; import { CoolBaseEntity } from '@cool-midway/core'; @@ -24,7 +25,7 @@ export abstract class BaseEntity extends CoolBaseEntity { @UpdateDateColumn({ comment: '更新时间' }) updateTime: Date; - // @Index() - // @Column({ comment: '租户ID', nullable: true }) - // tenantId: number; + @Index() + @Column({ comment: '租户ID', nullable: true }) + tenantId: number; } diff --git a/src/modules/base/middleware/authority.ts b/src/modules/base/middleware/authority.ts index 939dca0..6f5e967 100644 --- a/src/modules/base/middleware/authority.ts +++ b/src/modules/base/middleware/authority.ts @@ -51,6 +51,7 @@ export class BaseAuthorityMiddleware if (_.startsWith(url, adminUrl)) { try { ctx.admin = jwt.verify(token, this.jwtConfig.jwt.secret); + ctx.admin.tenantId = 1; if (ctx.admin.isRefresh) { ctx.status = 401; ctx.body = { diff --git a/src/modules/base/service/sys/login.ts b/src/modules/base/service/sys/login.ts index 23a9a55..76de9a4 100644 --- a/src/modules/base/service/sys/login.ts +++ b/src/modules/base/service/sys/login.ts @@ -195,6 +195,7 @@ export class BaseSysLoginService extends BaseService { username: user.username, userId: user.id, passwordVersion: user.passwordV, + tenantId: user['tenantId'], }; if (isRefresh) { tokenInfo.isRefresh = true; diff --git a/src/modules/demo/controller/admin/goods.ts b/src/modules/demo/controller/admin/goods.ts index 2bf6fdb..5c60567 100644 --- a/src/modules/demo/controller/admin/goods.ts +++ b/src/modules/demo/controller/admin/goods.ts @@ -1,5 +1,7 @@ import { CoolController, BaseController } from '@cool-midway/core'; import { DemoGoodsEntity } from '../../entity/goods'; +import { Get, Inject } from '@midwayjs/core'; +import { DemoGoodsService } from '../../service/goods'; /** * 商品模块-商品信息 @@ -8,4 +10,13 @@ import { DemoGoodsEntity } from '../../entity/goods'; api: ['add', 'delete', 'update', 'info', 'list', 'page'], entity: DemoGoodsEntity, }) -export class AdminDemoGoodsController extends BaseController {} +export class AdminDemoGoodsController extends BaseController { + @Inject() + demoGoodsService: DemoGoodsService; + + @Get('/test', { summary: '测试' }) + async test() { + await this.demoGoodsService.test(); + return this.ok('test'); + } +} diff --git a/src/modules/demo/controller/open/goods.ts b/src/modules/demo/controller/open/goods.ts index 5d4ac71..ff02264 100644 --- a/src/modules/demo/controller/open/goods.ts +++ b/src/modules/demo/controller/open/goods.ts @@ -1,6 +1,6 @@ import { DemoGoodsService } from '../../service/goods'; import { DemoGoodsEntity } from '../../entity/goods'; -import { Body, Config, Inject, Post, Provide } from '@midwayjs/core'; +import { Body, Config, Get, Inject, Post, Provide } from '@midwayjs/core'; import { CoolController, BaseController } from '@cool-midway/core'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Repository } from 'typeorm'; @@ -29,4 +29,10 @@ export class OpenDemoGoodsController extends BaseController { async entityPage(@Body() query) { return this.ok(await this.demoGoodsService.entityPage(query)); } + + @Get('/test', { summary: '测试' }) + async test() { + await this.demoGoodsService.test(); + return this.ok('test'); + } } diff --git a/src/modules/demo/service/goods.ts b/src/modules/demo/service/goods.ts index bd0877e..66fec1e 100644 --- a/src/modules/demo/service/goods.ts +++ b/src/modules/demo/service/goods.ts @@ -1,8 +1,9 @@ import { DemoGoodsEntity } from './../entity/goods'; -import { Provide } from '@midwayjs/core'; +import { Inject, Provide } from '@midwayjs/core'; import { BaseService } from '@cool-midway/core'; import { InjectEntityModel } from '@midwayjs/typeorm'; import { Repository } from 'typeorm'; +import { noTenant } from '../../base/db/tenant'; /** * 商品示例 @@ -12,6 +13,9 @@ export class DemoGoodsService extends BaseService { @InjectEntityModel(DemoGoodsEntity) demoGoodsEntity: Repository; + @Inject() + ctx; + /** * 执行sql分页 */ @@ -37,4 +41,14 @@ export class DemoGoodsService extends BaseService { const find = this.demoGoodsEntity.createQueryBuilder(); return this.entityRenderPage(find, query); } + + async test() { + const a = await this.demoGoodsEntity.createQueryBuilder().getMany(); + await noTenant(this.ctx, async () => { + const b = await this.demoGoodsEntity.createQueryBuilder().getMany(); + console.log('b'); + }); + const c = await this.demoGoodsEntity.createQueryBuilder().getMany(); + console.log(a); + } } diff --git a/src/modules/swagger/config.ts b/src/modules/swagger/config.ts index 3cb591a..d0af1df 100644 --- a/src/modules/swagger/config.ts +++ b/src/modules/swagger/config.ts @@ -38,7 +38,7 @@ export default ({ app }) => { components: { schemas: {}, securitySchemes: { - Auth: { + ApiKeyAuth: { type: 'apiKey', name: 'Authorization', in: 'header',