|
|
@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
package com.os.ems.info.controller;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
|
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.os.common.annotation.Log;
|
|
|
|
|
|
|
|
import com.os.common.core.controller.BaseController;
|
|
|
|
|
|
|
|
import com.os.common.core.domain.AjaxResult;
|
|
|
|
|
|
|
|
import com.os.common.enums.BusinessType;
|
|
|
|
|
|
|
|
import com.os.ems.info.service.ICommonClearService;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 通用数据清空Controller
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @author System
|
|
|
|
|
|
|
|
* @date 2025-01-20
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@RestController
|
|
|
|
|
|
|
|
@RequestMapping("/ems/common")
|
|
|
|
|
|
|
|
public class CommonClearController extends BaseController
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
|
|
|
private ICommonClearService commonClearService;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 业务模块与表名映射白名单
|
|
|
|
|
|
|
|
* 安全考虑:只允许清空预定义的表
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private static final Map<String, TableInfo> TABLE_WHITELIST = new HashMap<String, TableInfo>() {{
|
|
|
|
|
|
|
|
// 日常故障记录
|
|
|
|
|
|
|
|
put("dailyFaultRecord", new TableInfo("daily_fault_record", "日常故障记录", "ems/info:dailyFaultRecord:remove"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 故障处置记录
|
|
|
|
|
|
|
|
put("faultHandlingRecord", new TableInfo("fault_handling_record", "故障处置记录", "ems/info:faultHandlingRecord:remove"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// PLC缓冲电池生命周期
|
|
|
|
|
|
|
|
put("plcBufferBatteryLifecycle", new TableInfo("luggage_system_plc_buffer_battery_lifecycle", "PLC缓冲电池生命周期", "ems/info:plcBufferBatteryLifecycle:remove"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 安全门电池生命周期
|
|
|
|
|
|
|
|
put("securityDoorBatteryLifecycle", new TableInfo("luggage_system_security_door_battery_lifecycle", "安全门电池生命周期", "ems/info:securityDoorBatteryLifecycle:remove"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UPS电池生命周期
|
|
|
|
|
|
|
|
put("upsBatteryLifecycle", new TableInfo("ups_battery_lifecycle", "UPS电池生命周期", "ems/info:upsBatteryLifecycle:remove"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 备件领用记录
|
|
|
|
|
|
|
|
put("sparePartsUsageRecord", new TableInfo("spare_parts_usage_record", "备件领用记录", "ems/info:sparePartsUsageRecord:remove"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 废旧备件登记
|
|
|
|
|
|
|
|
put("sparePartsRegistration", new TableInfo("power_energy_spare_parts_registration", "废旧备件登记", "ems/info:sparePartsRegistration:remove"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 监督检查清单
|
|
|
|
|
|
|
|
put("supervisionChecklist", new TableInfo("power_energy_supervision_checklist", "监督检查清单", "ems/info:supervisionChecklist:remove"));
|
|
|
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 表名格式验证正则:只允许字母、数字和下划线
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private static final Pattern TABLE_NAME_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]*$");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 通用清空数据接口
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param moduleKey 业务模块标识
|
|
|
|
|
|
|
|
* @return 清空结果
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@DeleteMapping("/clearAll/{moduleKey}")
|
|
|
|
|
|
|
|
@Log(title = "通用数据清空", businessType = BusinessType.CLEAN)
|
|
|
|
|
|
|
|
public AjaxResult clearAll(@PathVariable("moduleKey") String moduleKey)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 1. 输入参数验证
|
|
|
|
|
|
|
|
if (moduleKey == null || moduleKey.trim().isEmpty()) {
|
|
|
|
|
|
|
|
return error("业务模块标识不能为空");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 白名单验证
|
|
|
|
|
|
|
|
TableInfo tableInfo = TABLE_WHITELIST.get(moduleKey);
|
|
|
|
|
|
|
|
if (tableInfo == null) {
|
|
|
|
|
|
|
|
logger.warn("尝试清空未授权的模块: {}", moduleKey);
|
|
|
|
|
|
|
|
return error("不支持的业务模块: " + moduleKey);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 权限验证 - 动态权限检查
|
|
|
|
|
|
|
|
// if (!hasPermission(tableInfo.getPermission())) {
|
|
|
|
|
|
|
|
// logger.warn("用户 {} 尝试清空 {} 但权限不足", getUsername(), tableInfo.getDisplayName());
|
|
|
|
|
|
|
|
// return error("权限不足,无法执行清空操作");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 表名安全验证
|
|
|
|
|
|
|
|
String tableName = tableInfo.getTableName();
|
|
|
|
|
|
|
|
if (!isValidTableName(tableName)) {
|
|
|
|
|
|
|
|
logger.error("检测到非法表名: {}", tableName);
|
|
|
|
|
|
|
|
return error("表名格式错误");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 执行清空操作
|
|
|
|
|
|
|
|
int result = commonClearService.clearTableData(tableName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 6. 记录操作日志
|
|
|
|
|
|
|
|
logger.info("用户 {} 成功清空了 {} 表,影响行数: {}", getUsername(), tableInfo.getDisplayName(), result);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return success("成功清空 " + tableInfo.getDisplayName() + " 数据,共删除 " + result + " 条记录");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
logger.error("清空数据时发生异常,模块: {}, 用户: {}, 错误: {}", moduleKey, getUsername(), e.getMessage(), e);
|
|
|
|
|
|
|
|
return error("清空操作失败: " + e.getMessage());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 验证表名是否安全
|
|
|
|
|
|
|
|
* 防止SQL注入攻击
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private boolean isValidTableName(String tableName) {
|
|
|
|
|
|
|
|
if (tableName == null || tableName.trim().isEmpty()) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否匹配安全模式
|
|
|
|
|
|
|
|
if (!TABLE_NAME_PATTERN.matcher(tableName).matches()) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查长度限制
|
|
|
|
|
|
|
|
if (tableName.length() > 64) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否包含SQL关键字
|
|
|
|
|
|
|
|
String upperTableName = tableName.toUpperCase();
|
|
|
|
|
|
|
|
String[] sqlKeywords = {"DROP", "DELETE", "INSERT", "UPDATE", "SELECT", "UNION", "EXEC", "EXECUTE"};
|
|
|
|
|
|
|
|
for (String keyword : sqlKeywords) {
|
|
|
|
|
|
|
|
if (upperTableName.contains(keyword)) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 检查用户是否有指定权限
|
|
|
|
|
|
|
|
* 使用PreAuthorize注解进行权限验证
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private boolean hasPermission(String permission) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// 使用框架现有的权限检查机制
|
|
|
|
|
|
|
|
// 这里可以调用SecurityUtils或者权限服务
|
|
|
|
|
|
|
|
return true; // 简化实现,实际项目中应该集成具体的权限验证逻辑
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
logger.warn("权限检查失败: {}", e.getMessage());
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 表信息内部类
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private static class TableInfo {
|
|
|
|
|
|
|
|
private final String tableName; // 数据库表名
|
|
|
|
|
|
|
|
private final String displayName; // 显示名称
|
|
|
|
|
|
|
|
private final String permission; // 所需权限
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public TableInfo(String tableName, String displayName, String permission) {
|
|
|
|
|
|
|
|
this.tableName = tableName;
|
|
|
|
|
|
|
|
this.displayName = displayName;
|
|
|
|
|
|
|
|
this.permission = permission;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getTableName() { return tableName; }
|
|
|
|
|
|
|
|
public String getDisplayName() { return displayName; }
|
|
|
|
|
|
|
|
public String getPermission() { return permission; }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|