Files
backmanager-server/middleware/permissions.js
2026-06-29 11:32:59 +08:00

101 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// middleware/permissions.js —— 接口权限 + 数据范围 + 合同类型校验
/**
* 检查当前用户是否拥有指定权限
* @param {string} resource - 资源名,如 'customer'
* @param {string} action - 操作名,如 'read'
*/
function checkPermission(resource, action) {
return (req, res, next) => {
const permName = `${resource}:${action}`
if (!req.user || !req.user.permissions || !req.user.permissions.includes(permName)) {
return res.status(403).json({ code: 403, message: '权限不足' })
}
next()
}
}
/**
* 根据用户部门计算数据范围,挂到 req.scope
* @param {string} resource - 资源名customers / contracts / after_sales / employees
*/
function dataScope(resource) {
return (req, res, next) => {
const deptName = req.user.departmentName // 如 'franchise_manager'
// 信息技术部和总经理办公室:全量数据
if (deptName === 'admin' || deptName === 'general_manager') {
return next()
}
let sql = null, params = []
switch (resource) {
case 'customers':
// 过渡期:招商部和运营部也能看全量加盟商
break
case 'contracts':
if (deptName === 'franchise_manager') {
sql = 'AND type = ?'
params = ['franchise']
} else if (deptName === 'procurement_manager') {
sql = 'AND type = ?'
params = ['supply']
}
// finance 全量看operations_manager 无合同权限checkPermission 已拦截)
break
case 'after_sales':
// 过渡期:运营部看全量售后
break
case 'employees':
if (deptName === 'hr') {
// 人力资源部可查看全量员工
break
}
if (['franchise_manager', 'operations_manager', 'procurement_manager'].includes(deptName)) {
sql = 'AND department = ?'
params = [req.user.departmentDesc] // 如 '招商部'
}
// admin / general_manager / finance 全量看员工
break
}
if (sql) {
req.scope = { sql, params }
}
next()
}
}
/**
* 合同创建/修改时校验类型是否匹配部门
* 招商部只能操作加盟合同,采购部只能操作采购合同
*/
function validateContractType(req, res, next) {
const deptName = req.user.departmentName
const type = req.body.type
// 未传 type 则跳过(路由会默认 'franchise'
if (type === undefined) return next()
// 管理员/总经理/财务不限制
if (['admin', 'general_manager', 'finance'].includes(deptName)) return next()
// 采购部只能操作采购合同
if (deptName === 'procurement_manager' && type !== 'supply') {
return res.status(403).json({ code: 403, message: '采购部只能操作采购合同' })
}
// 招商部只能操作加盟合同
if (deptName === 'franchise_manager' && type !== 'franchise') {
return res.status(403).json({ code: 403, message: '招商部只能操作加盟合同' })
}
next()
}
module.exports = { checkPermission, dataScope, validateContractType }