完善保险前后端、养殖端小程序

This commit is contained in:
xuqiuyun
2025-09-25 19:09:51 +08:00
parent 76b5393182
commit 852adbcfff
199 changed files with 8642 additions and 52333 deletions

View File

@@ -17,11 +17,15 @@ app.use(cors({
credentials: true
}));
// 速率限制
// 速率限制 - 开发环境下放宽限制
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 限制每个IP每15分钟最多100个请求
message: '请求过于频繁,请稍后再试'
windowMs: 1 * 60 * 1000, // 1分钟
max: 1000, // 限制每个IP每1分钟最多1000个请求
message: '请求过于频繁,请稍后再试',
skip: (req) => {
// 在开发环境下跳过限流
return process.env.NODE_ENV === 'development';
}
});
app.use(limiter);
@@ -56,6 +60,7 @@ app.use('/api/insurance-types', require('../routes/insuranceTypes'));
app.use('/api/policies', require('../routes/policies'));
app.use('/api/claims', require('../routes/claims'));
app.use('/api/system', require('../routes/system'));
app.use('/api/dashboard', require('../routes/dashboard'));
app.use('/api/operation-logs', require('../routes/operationLogs'));
app.use('/api/menus', require('../routes/menus'));
app.use('/api/data-warehouse', require('../routes/dataWarehouse'));
@@ -73,6 +78,10 @@ app.use('/api/livestock-claims', require('../routes/livestockClaims'));
app.use('/api/devices', require('../routes/devices'));
app.use('/api/device-alerts', require('../routes/deviceAlerts'));
// 权限管理相关路由
app.use('/api/permissions', require('../routes/permissions'));
app.use('/api/role-permissions', require('../routes/rolePermissions'));
// API文档路由
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, {
explorer: true,

View File

@@ -0,0 +1,191 @@
const PermissionService = require('../services/permissionService');
const jwt = require('jsonwebtoken');
/**
* 权限检查中间件
* @param {string|string[]} requiredPermissions - 必需的权限代码(单个或数组)
* @param {string} checkType - 检查类型:'any'(任意一个)或 'all'(全部)
* @returns {Function} Express中间件函数
*/
const requirePermission = (requiredPermissions, checkType = 'any') => {
return async (req, res, next) => {
try {
// 从请求头获取token
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
success: false,
message: '未提供认证令牌'
});
}
// 验证token并获取用户信息
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const userId = decoded.userId;
if (!userId) {
return res.status(401).json({
success: false,
message: '无效的认证令牌'
});
}
// 确保权限是数组格式
const permissions = Array.isArray(requiredPermissions)
? requiredPermissions
: [requiredPermissions];
let hasPermission = false;
// 根据检查类型进行权限验证
if (checkType === 'all') {
hasPermission = await PermissionService.checkUserAllPermissions(userId, permissions);
} else {
hasPermission = await PermissionService.checkUserAnyPermission(userId, permissions);
}
if (!hasPermission) {
return res.status(403).json({
success: false,
message: '权限不足,无法访问此资源',
requiredPermissions: permissions
});
}
// 将用户ID添加到请求对象中供后续使用
req.userId = userId;
next();
} catch (error) {
console.error('权限检查中间件错误:', error);
if (error.name === 'JsonWebTokenError') {
return res.status(401).json({
success: false,
message: '无效的认证令牌'
});
}
if (error.name === 'TokenExpiredError') {
return res.status(401).json({
success: false,
message: '认证令牌已过期'
});
}
return res.status(500).json({
success: false,
message: '权限检查失败'
});
}
};
};
/**
* 检查单个权限的中间件
* @param {string} permission - 权限代码
* @returns {Function} Express中间件函数
*/
const requireSinglePermission = (permission) => {
return requirePermission(permission, 'any');
};
/**
* 检查多个权限中任意一个的中间件
* @param {string[]} permissions - 权限代码数组
* @returns {Function} Express中间件函数
*/
const requireAnyPermission = (permissions) => {
return requirePermission(permissions, 'any');
};
/**
* 检查多个权限全部具备的中间件
* @param {string[]} permissions - 权限代码数组
* @returns {Function} Express中间件函数
*/
const requireAllPermissions = (permissions) => {
return requirePermission(permissions, 'all');
};
/**
* 管理员权限检查中间件
* @returns {Function} Express中间件函数
*/
const requireAdmin = () => {
return requireSinglePermission('system:admin');
};
/**
* 超级管理员权限检查中间件
* @returns {Function} Express中间件函数
*/
const requireSuperAdmin = () => {
return requireSinglePermission('system:super_admin');
};
/**
* 权限检查装饰器(用于控制器方法)
* @param {string|string[]} permissions - 权限代码
* @param {string} checkType - 检查类型
* @returns {Function} 装饰器函数
*/
const withPermission = (permissions, checkType = 'any') => {
return (target, propertyKey, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = async function(req, res, next) {
try {
const middleware = requirePermission(permissions, checkType);
await new Promise((resolve, reject) => {
middleware(req, res, (err) => {
if (err) reject(err);
else resolve();
});
});
return originalMethod.call(this, req, res, next);
} catch (error) {
return res.status(403).json({
success: false,
message: '权限不足'
});
}
};
return descriptor;
};
};
/**
* 动态权限检查中间件
* 根据请求参数动态确定所需权限
* @param {Function} permissionResolver - 权限解析函数
* @returns {Function} Express中间件函数
*/
const requireDynamicPermission = (permissionResolver) => {
return async (req, res, next) => {
try {
const requiredPermissions = await permissionResolver(req);
const middleware = requirePermission(requiredPermissions);
return middleware(req, res, next);
} catch (error) {
console.error('动态权限检查失败:', error);
return res.status(500).json({
success: false,
message: '权限检查失败'
});
}
};
};
module.exports = {
requirePermission,
requireSinglePermission,
requireAnyPermission,
requireAllPermissions,
requireAdmin,
requireSuperAdmin,
withPermission,
requireDynamicPermission
};

View File

@@ -0,0 +1,254 @@
const { User, Role, Permission, RolePermission } = require('../models');
/**
* 权限服务类 - 提供动态权限检查和管理功能
*/
class PermissionService {
/**
* 检查用户是否具有指定权限
* @param {number} userId - 用户ID
* @param {string} permissionCode - 权限代码
* @returns {Promise<boolean>} 是否具有权限
*/
static async checkUserPermission(userId, permissionCode) {
try {
const user = await User.findByPk(userId, {
include: [{
model: Role,
as: 'role',
include: [{
model: Permission,
as: 'permissions',
where: { code: permissionCode },
required: false
}]
}]
});
if (!user || !user.role) {
return false;
}
return user.role.permissions && user.role.permissions.length > 0;
} catch (error) {
console.error('检查用户权限失败:', error);
return false;
}
}
/**
* 检查用户是否具有多个权限中的任意一个
* @param {number} userId - 用户ID
* @param {string[]} permissionCodes - 权限代码数组
* @returns {Promise<boolean>} 是否具有任意一个权限
*/
static async checkUserAnyPermission(userId, permissionCodes) {
try {
const user = await User.findByPk(userId, {
include: [{
model: Role,
as: 'role',
include: [{
model: Permission,
as: 'permissions',
where: { code: permissionCodes },
required: false
}]
}]
});
if (!user || !user.role) {
return false;
}
return user.role.permissions && user.role.permissions.length > 0;
} catch (error) {
console.error('检查用户权限失败:', error);
return false;
}
}
/**
* 检查用户是否具有所有指定权限
* @param {number} userId - 用户ID
* @param {string[]} permissionCodes - 权限代码数组
* @returns {Promise<boolean>} 是否具有所有权限
*/
static async checkUserAllPermissions(userId, permissionCodes) {
try {
const user = await User.findByPk(userId, {
include: [{
model: Role,
as: 'role',
include: [{
model: Permission,
as: 'permissions',
where: { code: permissionCodes },
required: false
}]
}]
});
if (!user || !user.role) {
return false;
}
const userPermissions = user.role.permissions || [];
return permissionCodes.every(code =>
userPermissions.some(permission => permission.code === code)
);
} catch (error) {
console.error('检查用户权限失败:', error);
return false;
}
}
/**
* 获取用户的所有权限
* @param {number} userId - 用户ID
* @returns {Promise<string[]>} 用户权限代码数组
*/
static async getUserPermissions(userId) {
try {
const user = await User.findByPk(userId, {
include: [{
model: Role,
as: 'role',
include: [{
model: Permission,
as: 'permissions'
}]
}]
});
if (!user || !user.role || !user.role.permissions) {
return [];
}
return user.role.permissions.map(permission => permission.code);
} catch (error) {
console.error('获取用户权限失败:', error);
return [];
}
}
/**
* 获取角色的所有权限
* @param {number} roleId - 角色ID
* @returns {Promise<Permission[]>} 权限对象数组
*/
static async getRolePermissions(roleId) {
try {
const role = await Role.findByPk(roleId, {
include: [{
model: Permission,
as: 'permissions'
}]
});
return role ? role.permissions || [] : [];
} catch (error) {
console.error('获取角色权限失败:', error);
return [];
}
}
/**
* 检查权限是否存在
* @param {string} permissionCode - 权限代码
* @returns {Promise<boolean>} 权限是否存在
*/
static async permissionExists(permissionCode) {
try {
const permission = await Permission.findOne({
where: { code: permissionCode }
});
return !!permission;
} catch (error) {
console.error('检查权限存在性失败:', error);
return false;
}
}
/**
* 获取权限树结构
* @returns {Promise<Object[]>} 权限树
*/
static async getPermissionTree() {
try {
const permissions = await Permission.findAll({
order: [['module', 'ASC'], ['type', 'ASC'], ['code', 'ASC']]
});
// 按模块分组
const modules = {};
permissions.forEach(permission => {
if (!modules[permission.module]) {
modules[permission.module] = {
module: permission.module,
permissions: []
};
}
modules[permission.module].permissions.push(permission);
});
return Object.values(modules);
} catch (error) {
console.error('获取权限树失败:', error);
return [];
}
}
/**
* 批量检查用户权限
* @param {number} userId - 用户ID
* @param {string[]} permissionCodes - 权限代码数组
* @returns {Promise<Object>} 权限检查结果对象
*/
static async batchCheckUserPermissions(userId, permissionCodes) {
try {
const userPermissions = await this.getUserPermissions(userId);
const result = {};
permissionCodes.forEach(code => {
result[code] = userPermissions.includes(code);
});
return result;
} catch (error) {
console.error('批量检查用户权限失败:', error);
return {};
}
}
/**
* 获取用户可访问的菜单
* @param {number} userId - 用户ID
* @returns {Promise<Object[]>} 可访问的菜单数组
*/
static async getUserAccessibleMenus(userId) {
try {
const userPermissions = await this.getUserPermissions(userId);
// 这里可以根据权限过滤菜单
// 示例:假设菜单与权限有对应关系
const allMenus = [
{ id: 1, name: '用户管理', permission: 'user:view', path: '/users' },
{ id: 2, name: '角色管理', permission: 'role:view', path: '/roles' },
{ id: 3, name: '权限管理', permission: 'permission:view', path: '/permissions' },
{ id: 4, name: '保单管理', permission: 'policy:view', path: '/policies' },
{ id: 5, name: '理赔管理', permission: 'claim:view', path: '/claims' },
{ id: 6, name: '系统设置', permission: 'system:view', path: '/system' }
];
return allMenus.filter(menu =>
userPermissions.includes(menu.permission)
);
} catch (error) {
console.error('获取用户可访问菜单失败:', error);
return [];
}
}
}
module.exports = PermissionService;