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 };