187 lines
5.3 KiB
JavaScript
187 lines
5.3 KiB
JavaScript
const logger = require('../utils/logger').module('DangerousOperationsRoute');
|
|
const express = require('express');
|
|
const router = express.Router();
|
|
const { authMiddleware } = require('../middleware/auth');
|
|
const {
|
|
logDangerousOperation,
|
|
getDangerousOperationsLogs,
|
|
cleanOldLogs,
|
|
DANGEROUS_OPERATION_TYPES,
|
|
RISK_LEVELS,
|
|
calculateRiskLevel,
|
|
} = require('../utils/dangerousOperationLogger');
|
|
|
|
// 全局认证中间件
|
|
router.use(authMiddleware);
|
|
|
|
router.post('/log', async (req, res) => {
|
|
try {
|
|
const {
|
|
operationType,
|
|
operationName,
|
|
targetType,
|
|
targetId,
|
|
targetName,
|
|
beforeState,
|
|
metadata = {},
|
|
success = true,
|
|
errorMessage = null,
|
|
} = req.body;
|
|
|
|
if (!operationType || !operationName) {
|
|
return res.status(400).json({ error: '缺少必需参数 operationType 或 operationName' });
|
|
}
|
|
|
|
const riskLevel =
|
|
metadata.riskLevel ||
|
|
calculateRiskLevel(operationType, metadata.itemCount || 1, {
|
|
hasRelatedData: metadata.relatedDataCount > 0,
|
|
isSystemLevel: metadata.isSystemLevel,
|
|
});
|
|
|
|
await logDangerousOperation(req, {
|
|
operationType,
|
|
operationName,
|
|
targetType,
|
|
targetId,
|
|
targetName,
|
|
beforeState,
|
|
metadata: {
|
|
...metadata,
|
|
riskLevel,
|
|
},
|
|
success,
|
|
errorMessage,
|
|
});
|
|
|
|
res.json({ success: true, riskLevel });
|
|
} catch (error) {
|
|
logger.error('Failed to log dangerous operation', { error: error.message, stack: error.stack });
|
|
res.status(500).json({ error: '日志记录失败' });
|
|
}
|
|
});
|
|
|
|
router.get('/logs', async (req, res) => {
|
|
try {
|
|
const {
|
|
operationType,
|
|
targetType,
|
|
success,
|
|
startDate,
|
|
endDate,
|
|
username,
|
|
riskLevel,
|
|
page = 1,
|
|
pageSize = 50,
|
|
} = req.query;
|
|
|
|
const filters = {
|
|
operationType,
|
|
targetType,
|
|
success: success !== undefined ? success === 'true' : undefined,
|
|
startDate,
|
|
endDate,
|
|
username,
|
|
riskLevel,
|
|
};
|
|
|
|
const allLogs = getDangerousOperationsLogs(filters);
|
|
const total = allLogs.length;
|
|
const startIndex = (parseInt(page) - 1) * parseInt(pageSize);
|
|
const endIndex = startIndex + parseInt(pageSize);
|
|
const logs = allLogs.slice(startIndex, endIndex);
|
|
|
|
res.json({
|
|
logs,
|
|
total,
|
|
page: parseInt(page),
|
|
pageSize: parseInt(pageSize),
|
|
totalPages: Math.ceil(total / parseInt(pageSize)),
|
|
});
|
|
} catch (error) {
|
|
logger.error('Failed to get dangerous operations logs', { error: error.message, stack: error.stack });
|
|
res.status(500).json({ error: '获取日志失败' });
|
|
}
|
|
});
|
|
|
|
router.delete('/logs/clean', async (req, res) => {
|
|
try {
|
|
const { daysToKeep = 90 } = req.query;
|
|
|
|
// 通过关联表查询用户角色,判断是否为管理员
|
|
const UserRole = require('../models/UserRole');
|
|
const Role = require('../models/Role');
|
|
const userRole = await UserRole.findOne({
|
|
where: { UserId: req.user.userId },
|
|
include: [{ model: Role }],
|
|
});
|
|
const isAdmin = userRole && userRole.Role && userRole.Role.roleCode === 'admin';
|
|
|
|
if (!isAdmin) {
|
|
return res.status(403).json({ error: '只有管理员才能清理日志' });
|
|
}
|
|
|
|
const result = await cleanOldLogs(parseInt(daysToKeep));
|
|
|
|
await logDangerousOperation(req, {
|
|
operationType: DANGEROUS_OPERATION_TYPES.PURGE,
|
|
operationName: '清理危险操作日志',
|
|
targetType: 'operation_logs',
|
|
targetId: null,
|
|
targetName: `清理 ${daysToKeep} 天前的日志`,
|
|
metadata: {
|
|
riskLevel: RISK_LEVELS.MEDIUM,
|
|
deletedCount: result.deletedCount,
|
|
remainingCount: result.remainingCount,
|
|
daysToKeep: parseInt(daysToKeep),
|
|
},
|
|
success: true,
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
message: `已清理 ${result.deletedCount} 条过期日志,保留 ${result.remainingCount} 条日志`,
|
|
deletedCount: result.deletedCount,
|
|
remainingCount: result.remainingCount,
|
|
});
|
|
} catch (error) {
|
|
logger.error('Failed to clean logs', { error: error.message, stack: error.stack });
|
|
res.status(500).json({ error: '清理日志失败' });
|
|
}
|
|
});
|
|
|
|
router.get('/risk-assessment', async (req, res) => {
|
|
try {
|
|
const { operationType, itemCount, hasRelatedData, isSystemLevel } = req.query;
|
|
|
|
const riskLevel = calculateRiskLevel(operationType, parseInt(itemCount) || 1, {
|
|
hasRelatedData: hasRelatedData === 'true',
|
|
isSystemLevel: isSystemLevel === 'true',
|
|
});
|
|
|
|
const riskDescriptions = {
|
|
[RISK_LEVELS.EXTREME]: '极高风险操作,需要输入确认关键词才能执行',
|
|
[RISK_LEVELS.HIGH]: '高风险操作,需要详细确认信息',
|
|
[RISK_LEVELS.MEDIUM]: '中等风险操作,需要明确确认',
|
|
[RISK_LEVELS.LOW]: '低风险操作,使用标准确认即可',
|
|
};
|
|
|
|
res.json({
|
|
riskLevel,
|
|
description: riskDescriptions[riskLevel],
|
|
requiresKeyword: riskLevel === RISK_LEVELS.EXTREME,
|
|
confirmationLevel:
|
|
riskLevel === RISK_LEVELS.EXTREME
|
|
? 'KEYWORD'
|
|
: riskLevel === RISK_LEVELS.HIGH
|
|
? 'ENHANCED'
|
|
: 'STANDARD',
|
|
});
|
|
} catch (error) {
|
|
logger.error('Failed to assess risk', { error: error.message, stack: error.stack });
|
|
res.status(500).json({ error: '风险评估失败' });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|