chore: src/modules/base/db/tenant.ts

This commit is contained in:
2026-07-01 17:55:54 +08:00
parent e1e7d2de3e
commit 83c9fdf65b
+213
View File
@@ -0,0 +1,213 @@
import { EventSubscriberModel } from '@midwayjs/typeorm';
import {
DeleteQueryBuilder,
EntitySubscriberInterface,
InsertQueryBuilder,
SelectQueryBuilder,
UpdateQueryBuilder,
} from 'typeorm';
import * as _ from 'lodash';
import {
App,
ASYNC_CONTEXT_KEY,
ASYNC_CONTEXT_MANAGER_KEY,
AsyncContextManager,
Config,
IMidwayApplication,
IMidwayContext,
Inject,
} from '@midwayjs/core';
import { Utils } from '../../../comm/utils';
import { CoolUrlTagData, TagTypes } from '@cool-midway/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<any> {
@App()
app: IMidwayApplication;
@Inject()
ctx: IMidwayContext;
@Inject()
coolUrlTagData: CoolUrlTagData;
@Config('cool.tenant')
tenant: {
// 是否开启多租户
enable: boolean;
// 需要过滤多租户的url
urls: string[];
};
// 系统接口不过滤
ignoreUrls = [
'/admin/base/open/login',
'/admin/base/comm/person',
'/admin/base/comm/permmenu',
'/admin/dict/info/data',
];
// 不进行租户过滤的用户
ignoreUsername = [];
@Inject()
utils: Utils;
/**
* 获取所有忽略的url
*/
getAllIgnoreUrls() {
const adminIgnoreUrls = this.coolUrlTagData.byKey(
TagTypes.IGNORE_TOKEN,
'admin'
);
const appIgnoreUrls = this.coolUrlTagData.byKey(
TagTypes.IGNORE_TOKEN,
'app'
);
this.ignoreUrls = [
...this.ignoreUrls,
...adminIgnoreUrls,
...appIgnoreUrls,
];
// 去重
this.ignoreUrls = _.uniq(this.ignoreUrls);
return this.ignoreUrls;
}
/**
* 检查是否需要租户
*/
checkHandler() {
const ctx = this.getCtx();
if (!ctx) return false;
const url = ctx?.url;
if (!url) return false;
if (this.tenant?.enable) {
const isNeedTenant = this.tenant.urls.some(pattern =>
this.utils.matchUrl(pattern, url)
);
return isNeedTenant;
}
return false;
}
/**
* 获取ctx
*/
getCtx(): any {
try {
const contextManager: AsyncContextManager = this.app
.getApplicationContext()
.get(ASYNC_CONTEXT_MANAGER_KEY);
return contextManager.active().getValue(ASYNC_CONTEXT_KEY);
} catch (error) {
return null;
}
}
/**
* 从登录的用户中获取租户ID
* @returns string | undefined
*/
getTenantId(): number | undefined {
let ctx, url, tenantId;
ctx = this.getCtx();
if (!ctx || !this.checkHandler()) return undefined;
url = ctx?.url;
// 忽略用户
if (this.ignoreUsername.includes(ctx?.admin?.username)) {
return undefined;
}
// 忽略系统接口
if (
this.getAllIgnoreUrls().some(pattern => this.utils.matchUrl(pattern, url))
) {
return undefined;
}
if (_.startsWith(url, '/admin/')) {
tenantId = ctx?.admin?.tenantId;
} else if (_.startsWith(url, '/app/')) {
tenantId = ctx?.user?.tenantId;
}
if (tenantId && url) {
return tenantId;
}
return undefined;
}
/**
* 查询时添加租户ID条件
* @param queryBuilder
*/
afterSelectQueryBuilder(queryBuilder: SelectQueryBuilder<any>) {
if (!this.tenant?.enable) return;
const tenantId = this.getTenantId();
if (tenantId) {
queryBuilder.andWhere(
`${
queryBuilder.alias ? queryBuilder.alias + '.' : ''
}tenantId = '${tenantId}'`
);
}
}
/**
* 插入时添加租户ID
* @param queryBuilder
*/
afterInsertQueryBuilder(queryBuilder: InsertQueryBuilder<any>) {
if (!this.tenant?.enable) return;
const tenantId = this.getTenantId();
if (tenantId) {
const values = queryBuilder.expressionMap.valuesSet;
if (Array.isArray(values)) {
queryBuilder.values(values.map(item => ({ ...item, tenantId })));
} else if (typeof values === 'object') {
queryBuilder.values({ ...values, tenantId });
}
}
}
/**
* 更新时添加租户ID和条件
* @param queryBuilder
*/
afterUpdateQueryBuilder(queryBuilder: UpdateQueryBuilder<any>) {
if (!this.tenant?.enable) return;
const tenantId = this.getTenantId();
if (tenantId) {
queryBuilder.andWhere(`tenantId = '${tenantId}'`);
}
}
/**
* 删除时添加租户ID和条件
* @param queryBuilder
*/
afterDeleteQueryBuilder(queryBuilder: DeleteQueryBuilder<any>) {
if (!this.tenant?.enable) return;
const tenantId = this.getTenantId();
if (tenantId) {
queryBuilder.andWhere(`tenantId = '${tenantId}'`);
}
}
}