rentease-backend-new/middleware/tenant.js

131 lines
3.0 KiB
JavaScript
Raw Normal View History

2026-04-20 06:43:09 +00:00
const Tenant = require('../models/Tenant');
/**
* 租户上下文中间件
* 从请求头或JWT令牌中提取租户信息并设置到请求上下文中
*/
const tenantContextMiddleware = async (req, res, next) => {
try {
let tenantId = null;
// 1. 尝试从请求头获取租户ID
const headerTenantId = req.headers['x-tenant-id'];
if (headerTenantId) {
tenantId = parseInt(headerTenantId, 10);
}
// 2. 如果请求头中没有尝试从JWT令牌中获取
if (!tenantId && req.user && req.user.tenantId) {
tenantId = req.user.tenantId;
}
// 3. 系统管理员可以指定任意租户
if (req.user && req.user.userType === 'super_admin' && headerTenantId) {
tenantId = parseInt(headerTenantId, 10);
}
// 4. 如果没有租户ID返回错误
if (!tenantId) {
return res.status(400).json({
code: 400,
message: '缺少租户标识'
});
}
// 5. 验证租户是否存在且状态正常
const tenant = await Tenant.findOne({
where: {
id: tenantId,
status: 'active',
isDeleted: 0
}
});
if (!tenant) {
return res.status(403).json({
code: 403,
message: '租户不存在或已被禁用'
});
}
// 6. 检查租户是否过期(使用 currentPeriodEnd 判断)
if (tenant.currentPeriodEnd && new Date(tenant.currentPeriodEnd) < new Date()) {
return res.status(403).json({
code: 403,
message: '租户服务已过期'
});
}
// 7. 将租户信息附加到请求对象
req.tenantId = tenantId;
req.tenant = tenant;
next();
} catch (error) {
console.error('租户上下文中间件错误:', error);
return res.status(500).json({
code: 500,
message: '租户验证失败',
error: error.message
});
}
};
/**
* 可选租户中间件
* 用于一些不需要强制租户隔离的接口
*/
const optionalTenantMiddleware = async (req, res, next) => {
try {
let tenantId = null;
const headerTenantId = req.headers['x-tenant-id'];
if (headerTenantId) {
tenantId = parseInt(headerTenantId, 10);
}
if (!tenantId && req.user && req.user.tenantId) {
tenantId = req.user.tenantId;
}
if (tenantId) {
const tenant = await Tenant.findOne({
where: {
id: tenantId,
status: 'active',
isDeleted: 0
}
});
if (tenant) {
req.tenantId = tenantId;
req.tenant = tenant;
}
}
next();
} catch (error) {
console.error('可选租户中间件错误:', error);
next();
}
};
/**
* 系统管理员权限检查中间件
*/
const superAdminMiddleware = (req, res, next) => {
if (!req.user || req.user.userType !== 'super_admin') {
return res.status(403).json({
code: 403,
message: '需要系统管理员权限'
});
}
next();
};
module.exports = {
tenantContextMiddleware,
optionalTenantMiddleware,
superAdminMiddleware
};