mirror of
https://github.com/cool-team-official/cool-admin-midway.git
synced 2025-12-11 00:22:49 +00:00
多租户
This commit is contained in:
parent
95f7218d9e
commit
b165e97500
@ -5,8 +5,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cool-midway/core": "file:/Users/ap/Documents/src/admin/midway-packages/core",
|
"@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/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/bootstrap": "^3.20.0",
|
||||||
"@midwayjs/cache-manager": "^3.20.0",
|
"@midwayjs/cache-manager": "^3.20.0",
|
||||||
"@midwayjs/core": "^3.20.0",
|
"@midwayjs/core": "^3.20.0",
|
||||||
|
|||||||
@ -13,6 +13,10 @@ export default {
|
|||||||
koa: {
|
koa: {
|
||||||
port: 8001,
|
port: 8001,
|
||||||
},
|
},
|
||||||
|
// 开启异步上下文管理
|
||||||
|
asyncContextManager: {
|
||||||
|
enable: true,
|
||||||
|
},
|
||||||
// 静态文件配置
|
// 静态文件配置
|
||||||
staticFile: {
|
staticFile: {
|
||||||
buffer: true,
|
buffer: true,
|
||||||
|
|||||||
@ -28,10 +28,10 @@ export default {
|
|||||||
// 实体与路径,跟生成代码、前端请求、swagger文档相关 注意:线上不建议开启,以免暴露敏感信息
|
// 实体与路径,跟生成代码、前端请求、swagger文档相关 注意:线上不建议开启,以免暴露敏感信息
|
||||||
eps: true,
|
eps: true,
|
||||||
// 是否自动导入模块数据库
|
// 是否自动导入模块数据库
|
||||||
initDB: true,
|
initDB: false,
|
||||||
// 判断是否初始化的方式
|
// 判断是否初始化的方式
|
||||||
initJudge: 'db',
|
initJudge: 'db',
|
||||||
// 是否自动导入模块菜单
|
// 是否自动导入模块菜单
|
||||||
initMenu: true,
|
initMenu: false,
|
||||||
} as CoolConfig,
|
} as CoolConfig,
|
||||||
} as MidwayConfig;
|
} as MidwayConfig;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export default () => {
|
|||||||
// 模块描述
|
// 模块描述
|
||||||
description: '基础的权限管理功能,包括登录,权限校验',
|
description: '基础的权限管理功能,包括登录,权限校验',
|
||||||
// 中间件
|
// 中间件
|
||||||
globalMiddlewares: [BaseAuthorityMiddleware, BaseLogMiddleware],
|
globalMiddlewares: [BaseAuthorityMiddleware],
|
||||||
// 模块加载顺序,默认为0,值越大越优先加载
|
// 模块加载顺序,默认为0,值越大越优先加载
|
||||||
order: 10,
|
order: 10,
|
||||||
// app参数配置允许读取的key
|
// app参数配置允许读取的key
|
||||||
|
|||||||
@ -1,34 +1,105 @@
|
|||||||
import { EventSubscriberModel } from '@midwayjs/typeorm';
|
import { EventSubscriberModel } from '@midwayjs/typeorm';
|
||||||
import { EntitySubscriberInterface, TransactionCommitEvent } from 'typeorm';
|
import {
|
||||||
import { BeforeQueryEvent } from 'typeorm/subscriber/event/QueryEvent';
|
DeleteQueryBuilder,
|
||||||
|
EntitySubscriberInterface,
|
||||||
|
InsertQueryBuilder,
|
||||||
|
SelectQueryBuilder,
|
||||||
|
UpdateQueryBuilder,
|
||||||
|
} from 'typeorm';
|
||||||
import * as _ from 'lodash';
|
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()
|
@EventSubscriberModel()
|
||||||
export class TenantSubscriber implements EntitySubscriberInterface<any> {
|
export class TenantSubscriber implements EntitySubscriberInterface<any> {
|
||||||
@App()
|
@App()
|
||||||
app: IMidwayApplication;
|
app: IMidwayApplication;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
ctx: IMidwayContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询前
|
* 从登录的用户中获取租户ID
|
||||||
* @param event
|
* @returns string | undefined
|
||||||
*/
|
*/
|
||||||
// @ts-ignore
|
getTenantId(): number | undefined {
|
||||||
beforeQuery(event: BeforeQueryEvent<any>, query: string, parameters: any[]) {
|
const contextManager: AsyncContextManager = this.app
|
||||||
if (_.startsWith(event.query, 'SELECT')) {
|
.getApplicationContext()
|
||||||
console.log('event.query', this.app);
|
.get(ASYNC_CONTEXT_MANAGER_KEY);
|
||||||
query = 'SELECT * FROM "tenant11"';
|
const ctx: any = contextManager.active().getValue(ASYNC_CONTEXT_KEY);
|
||||||
// // 参数
|
const url = ctx?.url;
|
||||||
// const parameters = event.parameters;
|
if (_.startsWith(url, '/admin/')) {
|
||||||
// // 连接
|
return ctx?.admin?.tenantId;
|
||||||
// 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');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询时添加租户ID条件
|
||||||
|
* @param queryBuilder
|
||||||
|
*/
|
||||||
|
afterSelectQueryBuilder(queryBuilder: SelectQueryBuilder<any>) {
|
||||||
|
const tenantId = this.getTenantId();
|
||||||
|
if (tenantId) {
|
||||||
|
queryBuilder.where('tenantId = :tenantId', { tenantId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 插入时添加租户ID
|
||||||
|
// * @param queryBuilder
|
||||||
|
// */
|
||||||
|
// async afterInsertQueryBuilder(queryBuilder: InsertQueryBuilder<any>) {
|
||||||
|
// const tenantId = await this.getTenantId();
|
||||||
|
// if (tenantId) {
|
||||||
|
// queryBuilder.values({ tenantId });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 更新时添加租户ID和条件
|
||||||
|
// * @param queryBuilder
|
||||||
|
// */
|
||||||
|
// async afterUpdateQueryBuilder(queryBuilder: UpdateQueryBuilder<any>) {
|
||||||
|
// const tenantId = await this.getTenantId();
|
||||||
|
// if (tenantId) {
|
||||||
|
// queryBuilder.set({ tenantId });
|
||||||
|
// queryBuilder.where('tenantId = :tenantId', { tenantId });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 删除时添加租户ID和条件
|
||||||
|
// * @param queryBuilder
|
||||||
|
// */
|
||||||
|
// async afterDeleteQueryBuilder(queryBuilder: DeleteQueryBuilder<any>) {
|
||||||
|
// const tenantId = await this.getTenantId();
|
||||||
|
// if (tenantId) {
|
||||||
|
// queryBuilder.where('tenantId = :tenantId', { tenantId });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {
|
|||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { CoolBaseEntity } from '@cool-midway/core';
|
import { CoolBaseEntity } from '@cool-midway/core';
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ export abstract class BaseEntity extends CoolBaseEntity {
|
|||||||
@UpdateDateColumn({ comment: '更新时间' })
|
@UpdateDateColumn({ comment: '更新时间' })
|
||||||
updateTime: Date;
|
updateTime: Date;
|
||||||
|
|
||||||
// @Index()
|
@Index()
|
||||||
// @Column({ comment: '租户ID', nullable: true })
|
@Column({ comment: '租户ID', nullable: true })
|
||||||
// tenantId: number;
|
tenantId: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,6 +51,7 @@ export class BaseAuthorityMiddleware
|
|||||||
if (_.startsWith(url, adminUrl)) {
|
if (_.startsWith(url, adminUrl)) {
|
||||||
try {
|
try {
|
||||||
ctx.admin = jwt.verify(token, this.jwtConfig.jwt.secret);
|
ctx.admin = jwt.verify(token, this.jwtConfig.jwt.secret);
|
||||||
|
ctx.admin.tenantId = 1;
|
||||||
if (ctx.admin.isRefresh) {
|
if (ctx.admin.isRefresh) {
|
||||||
ctx.status = 401;
|
ctx.status = 401;
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
|
|||||||
@ -195,6 +195,7 @@ export class BaseSysLoginService extends BaseService {
|
|||||||
username: user.username,
|
username: user.username,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
passwordVersion: user.passwordV,
|
passwordVersion: user.passwordV,
|
||||||
|
tenantId: user['tenantId'],
|
||||||
};
|
};
|
||||||
if (isRefresh) {
|
if (isRefresh) {
|
||||||
tokenInfo.isRefresh = true;
|
tokenInfo.isRefresh = true;
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { CoolController, BaseController } from '@cool-midway/core';
|
import { CoolController, BaseController } from '@cool-midway/core';
|
||||||
import { DemoGoodsEntity } from '../../entity/goods';
|
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'],
|
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
|
||||||
entity: DemoGoodsEntity,
|
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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { DemoGoodsService } from '../../service/goods';
|
import { DemoGoodsService } from '../../service/goods';
|
||||||
import { DemoGoodsEntity } from '../../entity/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 { CoolController, BaseController } from '@cool-midway/core';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
@ -29,4 +29,10 @@ export class OpenDemoGoodsController extends BaseController {
|
|||||||
async entityPage(@Body() query) {
|
async entityPage(@Body() query) {
|
||||||
return this.ok(await this.demoGoodsService.entityPage(query));
|
return this.ok(await this.demoGoodsService.entityPage(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('/test', { summary: '测试' })
|
||||||
|
async test() {
|
||||||
|
await this.demoGoodsService.test();
|
||||||
|
return this.ok('test');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { DemoGoodsEntity } from './../entity/goods';
|
import { DemoGoodsEntity } from './../entity/goods';
|
||||||
import { Provide } from '@midwayjs/core';
|
import { Inject, Provide } from '@midwayjs/core';
|
||||||
import { BaseService } from '@cool-midway/core';
|
import { BaseService } from '@cool-midway/core';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
import { noTenant } from '../../base/db/tenant';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品示例
|
* 商品示例
|
||||||
@ -12,6 +13,9 @@ export class DemoGoodsService extends BaseService {
|
|||||||
@InjectEntityModel(DemoGoodsEntity)
|
@InjectEntityModel(DemoGoodsEntity)
|
||||||
demoGoodsEntity: Repository<DemoGoodsEntity>;
|
demoGoodsEntity: Repository<DemoGoodsEntity>;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
ctx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行sql分页
|
* 执行sql分页
|
||||||
*/
|
*/
|
||||||
@ -37,4 +41,14 @@ export class DemoGoodsService extends BaseService {
|
|||||||
const find = this.demoGoodsEntity.createQueryBuilder();
|
const find = this.demoGoodsEntity.createQueryBuilder();
|
||||||
return this.entityRenderPage(find, query);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export default ({ app }) => {
|
|||||||
components: {
|
components: {
|
||||||
schemas: {},
|
schemas: {},
|
||||||
securitySchemes: {
|
securitySchemes: {
|
||||||
Auth: {
|
ApiKeyAuth: {
|
||||||
type: 'apiKey',
|
type: 'apiKey',
|
||||||
name: 'Authorization',
|
name: 'Authorization',
|
||||||
in: 'header',
|
in: 'header',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user