feat(fix) 脚本模版补充权限

This commit is contained in:
bwcx_jzy 2022-02-24 13:36:27 +08:00
parent 502fadf8de
commit f4b9a3eb21
No known key found for this signature in database
GPG Key ID: 5E48E9372088B9E5
9 changed files with 806 additions and 793 deletions

View File

@ -15,6 +15,8 @@
5. 【server】日志弹窗新增行号
6. 【server】在线升级执行脚本、脚本模版等兼容 `debian` (感谢@wxyShine [Gitee issues I4UQBD](https://gitee.com/dromara/Jpom/issues/I4UQBD)
7. 【agent】修复 windows 环境,节点首页进程列表切换不生效问题(感谢@neoch [Gitee issues I4UZA7](https://gitee.com/dromara/Jpom/issues/I4UZA7)
8. 【server】脚本模版补充权限
------

View File

@ -37,6 +37,7 @@ import io.jpom.model.data.UserModel;
import io.jpom.model.script.ScriptModel;
import io.jpom.plugin.ClassFeature;
import io.jpom.plugin.Feature;
import io.jpom.plugin.MethodFeature;
import io.jpom.service.node.script.NodeScriptServer;
import io.jpom.service.script.ScriptExecuteLogServer;
import io.jpom.service.script.ScriptServer;
@ -60,114 +61,117 @@ import java.util.List;
@Feature(cls = ClassFeature.SCRIPT)
public class ScriptController extends BaseServerController {
private final ScriptServer scriptServer;
private final NodeScriptServer nodeScriptServer;
private final ScriptExecuteLogServer scriptExecuteLogServer;
private final ScriptServer scriptServer;
private final NodeScriptServer nodeScriptServer;
private final ScriptExecuteLogServer scriptExecuteLogServer;
public ScriptController(ScriptServer scriptServer,
NodeScriptServer nodeScriptServer,
ScriptExecuteLogServer scriptExecuteLogServer) {
this.scriptServer = scriptServer;
this.nodeScriptServer = nodeScriptServer;
this.scriptExecuteLogServer = scriptExecuteLogServer;
}
public ScriptController(ScriptServer scriptServer,
NodeScriptServer nodeScriptServer,
ScriptExecuteLogServer scriptExecuteLogServer) {
this.scriptServer = scriptServer;
this.nodeScriptServer = nodeScriptServer;
this.scriptExecuteLogServer = scriptExecuteLogServer;
}
/**
* get script list
*
* @return json
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String scriptList() {
PageResultDto<ScriptModel> pageResultDto = scriptServer.listPage(getRequest());
return JsonMessage.getString(200, "success", pageResultDto);
}
/**
* get script list
*
* @return json
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public String scriptList() {
PageResultDto<ScriptModel> pageResultDto = scriptServer.listPage(getRequest());
return JsonMessage.getString(200, "success", pageResultDto);
}
@RequestMapping(value = "save.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String save(String id,
@ValidatorItem String context,
@ValidatorItem String name,
String autoExecCron,
String defArgs,
String description, String nodeIds) {
ScriptModel scriptModel = new ScriptModel();
scriptModel.setId(id);
scriptModel.setContext(context);
scriptModel.setName(name);
scriptModel.setNodeIds(nodeIds);
scriptModel.setDescription(description);
scriptModel.setDefArgs(defArgs);
@RequestMapping(value = "save.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public String save(String id,
@ValidatorItem String context,
@ValidatorItem String name,
String autoExecCron,
String defArgs,
String description, String nodeIds) {
ScriptModel scriptModel = new ScriptModel();
scriptModel.setId(id);
scriptModel.setContext(context);
scriptModel.setName(name);
scriptModel.setNodeIds(nodeIds);
scriptModel.setDescription(description);
scriptModel.setDefArgs(defArgs);
Assert.hasText(scriptModel.getContext(), "内容为空");
//
scriptModel.setAutoExecCron(this.checkCron(autoExecCron));
//
String oldNodeIds = null;
if (StrUtil.isEmpty(id)) {
scriptServer.insert(scriptModel);
} else {
HttpServletRequest request = getRequest();
ScriptModel byKey = scriptServer.getByKey(id, request);
Assert.notNull(byKey, "没有对应的数据");
oldNodeIds = byKey.getNodeIds();
scriptServer.updateById(scriptModel, request);
}
this.syncNodeScript(scriptModel, oldNodeIds);
return JsonMessage.getString(200, "修改成功");
}
Assert.hasText(scriptModel.getContext(), "内容为空");
//
scriptModel.setAutoExecCron(this.checkCron(autoExecCron));
//
String oldNodeIds = null;
if (StrUtil.isEmpty(id)) {
scriptServer.insert(scriptModel);
} else {
HttpServletRequest request = getRequest();
ScriptModel byKey = scriptServer.getByKey(id, request);
Assert.notNull(byKey, "没有对应的数据");
oldNodeIds = byKey.getNodeIds();
scriptServer.updateById(scriptModel, request);
}
this.syncNodeScript(scriptModel, oldNodeIds);
return JsonMessage.getString(200, "修改成功");
}
private void syncDelNodeScript(ScriptModel scriptModel, UserModel user, Collection<String> delNode) {
for (String s : delNode) {
NodeModel byKey = nodeService.getByKey(s, getRequest());
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", scriptModel.getId());
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Del, user, jsonObject);
Assert.state(request.getCode() == 200, "处理 " + byKey.getName() + " 节点删除脚本失败" + request.getMsg());
nodeScriptServer.syncNode(byKey);
}
}
private void syncDelNodeScript(ScriptModel scriptModel, UserModel user, Collection<String> delNode) {
for (String s : delNode) {
NodeModel byKey = nodeService.getByKey(s, getRequest());
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", scriptModel.getId());
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Del, user, jsonObject);
Assert.state(request.getCode() == 200, "处理 " + byKey.getName() + " 节点删除脚本失败" + request.getMsg());
nodeScriptServer.syncNode(byKey);
}
}
private void syncNodeScript(ScriptModel scriptModel, String oldNode) {
List<String> oldNodeIds = StrUtil.splitTrim(oldNode, StrUtil.COMMA);
List<String> newNodeIds = StrUtil.splitTrim(scriptModel.getNodeIds(), StrUtil.COMMA);
Collection<String> delNode = CollUtil.subtract(oldNodeIds, newNodeIds);
UserModel user = getUser();
// 删除
this.syncDelNodeScript(scriptModel, user, delNode);
// 更新
for (String newNodeId : newNodeIds) {
NodeModel byKey = nodeService.getByKey(newNodeId, getRequest());
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", scriptModel.getId());
jsonObject.put("type", "sync");
jsonObject.put("context", scriptModel.getContext());
jsonObject.put("autoExecCron", scriptModel.getAutoExecCron());
jsonObject.put("defArgs", scriptModel.getDefArgs());
jsonObject.put("description", scriptModel.getDescription());
jsonObject.put("name", scriptModel.getName());
jsonObject.put("workspaceId", scriptModel.getWorkspaceId());
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Save, user, jsonObject);
Assert.state(request.getCode() == 200, "处理 " + byKey.getName() + " 节点同步脚本失败" + request.getMsg());
nodeScriptServer.syncNode(byKey);
}
}
private void syncNodeScript(ScriptModel scriptModel, String oldNode) {
List<String> oldNodeIds = StrUtil.splitTrim(oldNode, StrUtil.COMMA);
List<String> newNodeIds = StrUtil.splitTrim(scriptModel.getNodeIds(), StrUtil.COMMA);
Collection<String> delNode = CollUtil.subtract(oldNodeIds, newNodeIds);
UserModel user = getUser();
// 删除
this.syncDelNodeScript(scriptModel, user, delNode);
// 更新
for (String newNodeId : newNodeIds) {
NodeModel byKey = nodeService.getByKey(newNodeId, getRequest());
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", scriptModel.getId());
jsonObject.put("type", "sync");
jsonObject.put("context", scriptModel.getContext());
jsonObject.put("autoExecCron", scriptModel.getAutoExecCron());
jsonObject.put("defArgs", scriptModel.getDefArgs());
jsonObject.put("description", scriptModel.getDescription());
jsonObject.put("name", scriptModel.getName());
jsonObject.put("workspaceId", scriptModel.getWorkspaceId());
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Save, user, jsonObject);
Assert.state(request.getCode() == 200, "处理 " + byKey.getName() + " 节点同步脚本失败" + request.getMsg());
nodeScriptServer.syncNode(byKey);
}
}
@RequestMapping(value = "del.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String del(String id) {
HttpServletRequest request = getRequest();
ScriptModel server = scriptServer.getByKey(id, request);
if (server != null) {
File file = server.scriptPath();
boolean del = FileUtil.del(file);
Assert.state(del, "清理脚本文件失败");
// 删除节点中的脚本
String nodeIds = server.getNodeIds();
List<String> delNode = StrUtil.splitTrim(nodeIds, StrUtil.COMMA);
this.syncDelNodeScript(server, getUser(), delNode);
scriptServer.delByKey(id, request);
//
scriptExecuteLogServer.delByWorkspace(request, entity -> entity.set("scriptId", id));
}
return JsonMessage.getString(200, "删除成功");
}
@RequestMapping(value = "del.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public String del(String id) {
HttpServletRequest request = getRequest();
ScriptModel server = scriptServer.getByKey(id, request);
if (server != null) {
File file = server.scriptPath();
boolean del = FileUtil.del(file);
Assert.state(del, "清理脚本文件失败");
// 删除节点中的脚本
String nodeIds = server.getNodeIds();
List<String> delNode = StrUtil.splitTrim(nodeIds, StrUtil.COMMA);
this.syncDelNodeScript(server, getUser(), delNode);
scriptServer.delByKey(id, request);
//
scriptExecuteLogServer.delByWorkspace(request, entity -> entity.set("scriptId", id));
}
return JsonMessage.getString(200, "删除成功");
}
}

View File

@ -33,6 +33,7 @@ import io.jpom.model.script.ScriptExecuteLogModel;
import io.jpom.model.script.ScriptModel;
import io.jpom.plugin.ClassFeature;
import io.jpom.plugin.Feature;
import io.jpom.plugin.MethodFeature;
import io.jpom.service.script.ScriptExecuteLogServer;
import io.jpom.service.script.ScriptServer;
import io.jpom.socket.ScriptProcessBuilder;
@ -56,64 +57,67 @@ import java.io.File;
@Feature(cls = ClassFeature.SCRIPT_LOG)
public class ScriptLogController extends BaseServerController {
private final ScriptExecuteLogServer scriptExecuteLogServer;
private final ScriptServer scriptServer;
private final ScriptExecuteLogServer scriptExecuteLogServer;
private final ScriptServer scriptServer;
public ScriptLogController(ScriptExecuteLogServer scriptExecuteLogServer,
ScriptServer scriptServer) {
this.scriptExecuteLogServer = scriptExecuteLogServer;
this.scriptServer = scriptServer;
}
public ScriptLogController(ScriptExecuteLogServer scriptExecuteLogServer,
ScriptServer scriptServer) {
this.scriptExecuteLogServer = scriptExecuteLogServer;
this.scriptServer = scriptServer;
}
/**
* get script log list
*
* @return json
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String scriptList() {
PageResultDto<ScriptExecuteLogModel> pageResultDto = scriptExecuteLogServer.listPage(getRequest());
return JsonMessage.getString(200, "success", pageResultDto);
}
/**
* get script log list
*
* @return json
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public String scriptList() {
PageResultDto<ScriptExecuteLogModel> pageResultDto = scriptExecuteLogServer.listPage(getRequest());
return JsonMessage.getString(200, "success", pageResultDto);
}
/**
* 删除日志
*
* @param id id
* @param executeId 执行ID
* @return json
*/
@RequestMapping(value = "del_log", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String delLog(@ValidatorItem() String id,
@ValidatorItem() String executeId) {
ScriptModel item = scriptServer.getByKey(id, getRequest());
Assert.notNull(item, "没有对应数据");
File logFile = item.logFile(executeId);
boolean fastDel = CommandUtil.systemFastDel(logFile);
Assert.state(!fastDel, "删除日志文件失败");
scriptExecuteLogServer.delByKey(executeId);
return JsonMessage.getString(200, "删除成功");
}
/**
* 删除日志
*
* @param id id
* @param executeId 执行ID
* @return json
*/
@RequestMapping(value = "del_log", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public String delLog(@ValidatorItem() String id,
@ValidatorItem() String executeId) {
ScriptModel item = scriptServer.getByKey(id, getRequest());
Assert.notNull(item, "没有对应数据");
File logFile = item.logFile(executeId);
boolean fastDel = CommandUtil.systemFastDel(logFile);
Assert.state(!fastDel, "删除日志文件失败");
scriptExecuteLogServer.delByKey(executeId);
return JsonMessage.getString(200, "删除成功");
}
/**
* 获取的日志
*
* @param id id
* @param executeId 执行ID
* @param line 需要获取的行号
* @return json
*/
@RequestMapping(value = "log", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String getNowLog(@ValidatorItem() String id,
@ValidatorItem() String executeId,
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "line") int line) {
ScriptModel item = scriptServer.getByKey(id, getRequest());
Assert.notNull(item, "没有对应数据");
File logFile = item.logFile(executeId);
Assert.state(FileUtil.isFile(logFile), "日志文件错误");
JSONObject data = FileUtils.readLogFile(logFile, line);
// 运行中
data.put("run", ScriptProcessBuilder.isRun(executeId));
return JsonMessage.getString(200, "ok", data);
}
/**
* 获取的日志
*
* @param id id
* @param executeId 执行ID
* @param line 需要获取的行号
* @return json
*/
@RequestMapping(value = "log", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public String getNowLog(@ValidatorItem() String id,
@ValidatorItem() String executeId,
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "line") int line) {
ScriptModel item = scriptServer.getByKey(id, getRequest());
Assert.notNull(item, "没有对应数据");
File logFile = item.logFile(executeId);
Assert.state(FileUtil.isFile(logFile), "日志文件错误");
JSONObject data = FileUtils.readLogFile(logFile, line);
// 运行中
data.put("run", ScriptProcessBuilder.isRun(executeId));
return JsonMessage.getString(200, "ok", data);
}
}

View File

@ -67,151 +67,151 @@ import java.util.Map;
@Service
public class DbUserOperateLogService extends BaseWorkspaceService<UserOperateLogV1> {
private static final Map<ClassFeature, Class<? extends BaseDbCommonService<?>>> CLASS_FEATURE_SERVICE = new HashMap<>();
private static final Map<ClassFeature, Class<? extends BaseDbCommonService<?>>> CLASS_FEATURE_SERVICE = new HashMap<>();
static {
CLASS_FEATURE_SERVICE.put(ClassFeature.NODE, NodeService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.SSH, SshService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.OUTGIVING, SshService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.MONITOR, MonitorService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.OPT_MONITOR, MonitorUserOptService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.PROJECT, ProjectInfoCacheService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.BUILD_REPOSITORY, RepositoryService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.BUILD, BuildInfoService.class);
}
static {
CLASS_FEATURE_SERVICE.put(ClassFeature.NODE, NodeService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.SSH, SshService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.OUTGIVING, SshService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.MONITOR, MonitorService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.OPT_MONITOR, MonitorUserOptService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.PROJECT, ProjectInfoCacheService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.BUILD_REPOSITORY, RepositoryService.class);
CLASS_FEATURE_SERVICE.put(ClassFeature.BUILD, BuildInfoService.class);
}
private final MonitorUserOptService monitorUserOptService;
private final UserService userService;
private final WorkspaceService workspaceService;
private final MonitorUserOptService monitorUserOptService;
private final UserService userService;
private final WorkspaceService workspaceService;
public DbUserOperateLogService(MonitorUserOptService monitorUserOptService,
UserService userService,
WorkspaceService workspaceService) {
this.monitorUserOptService = monitorUserOptService;
this.userService = userService;
this.workspaceService = workspaceService;
}
public DbUserOperateLogService(MonitorUserOptService monitorUserOptService,
UserService userService,
WorkspaceService workspaceService) {
this.monitorUserOptService = monitorUserOptService;
this.userService = userService;
this.workspaceService = workspaceService;
}
private void checkMonitor(UserOperateLogV1 userOperateLogV1) {
ClassFeature classFeature = EnumUtil.fromString(ClassFeature.class, userOperateLogV1.getClassFeature(), null);
MethodFeature methodFeature = EnumUtil.fromString(MethodFeature.class, userOperateLogV1.getMethodFeature(), null);
UserModel optUserItem = userService.getByKey(userOperateLogV1.getUserId());
if (classFeature == null || methodFeature == null || optUserItem == null) {
return;
}
String otherMsg = "";
Class<? extends BaseDbCommonService<?>> aClass = CLASS_FEATURE_SERVICE.get(classFeature);
if (aClass != null) {
BaseDbCommonService<?> baseDbCommonService = SpringUtil.getBean(aClass);
Object data = baseDbCommonService.getByKey(userOperateLogV1.getNodeId());
if (data != null) {
Object name = BeanUtil.getProperty(data, "name");
otherMsg = name == null ? StrUtil.EMPTY : StrUtil.format("操作的数据名称:{}\n", name);
}
}
WorkspaceModel workspaceModel = workspaceService.getByKey(userOperateLogV1.getWorkspaceId());
private void checkMonitor(UserOperateLogV1 userOperateLogV1) {
ClassFeature classFeature = EnumUtil.fromString(ClassFeature.class, userOperateLogV1.getClassFeature(), null);
MethodFeature methodFeature = EnumUtil.fromString(MethodFeature.class, userOperateLogV1.getMethodFeature(), null);
UserModel optUserItem = userService.getByKey(userOperateLogV1.getUserId());
if (classFeature == null || methodFeature == null || optUserItem == null) {
return;
}
String otherMsg = "";
Class<? extends BaseDbCommonService<?>> aClass = CLASS_FEATURE_SERVICE.get(classFeature);
if (aClass != null) {
BaseDbCommonService<?> baseDbCommonService = SpringUtil.getBean(aClass);
Object data = baseDbCommonService.getByKey(userOperateLogV1.getNodeId());
if (data != null) {
Object name = BeanUtil.getProperty(data, "name");
otherMsg = name == null ? StrUtil.EMPTY : StrUtil.format("操作的数据名称:{}\n", name);
}
}
WorkspaceModel workspaceModel = workspaceService.getByKey(userOperateLogV1.getWorkspaceId());
String optTypeMsg = StrUtil.format(" 【{}】->【{}】", classFeature.getName(), methodFeature.getName());
List<MonitorUserOptModel> monitorUserOptModels = monitorUserOptService.listByType(userOperateLogV1.getWorkspaceId(),
classFeature,
methodFeature,
userOperateLogV1.getUserId());
if (CollUtil.isEmpty(monitorUserOptModels)) {
return;
}
for (MonitorUserOptModel monitorUserOptModel : monitorUserOptModels) {
List<String> notifyUser = monitorUserOptModel.notifyUser();
if (CollUtil.isEmpty(notifyUser)) {
continue;
}
for (String userId : notifyUser) {
UserModel item = userService.getByKey(userId);
if (item == null) {
continue;
}
//
String context = StrUtil.format("操作用户:{}\n操作状态{}\n操作类型{}\n所属工作空间{}\n操作节点{}\n 操作数据id: {}\n操作IP: {}\n{}",
optUserItem.getName(),
userOperateLogV1.getOptStatusMsg(),
optTypeMsg,
workspaceModel.getName(),
userOperateLogV1.getNodeId(), userOperateLogV1.getDataId(), userOperateLogV1.getIp(), otherMsg);
// 邮箱
String email = item.getEmail();
if (StrUtil.isNotEmpty(email)) {
MonitorModel.Notify notify1 = new MonitorModel.Notify(MonitorModel.NotifyType.mail, email);
ThreadUtil.execute(() -> {
try {
NotifyUtil.send(notify1, "用户操作报警", context);
} catch (Exception e) {
DefaultSystemLog.getLog().error("发送报警信息错误", e);
}
});
String optTypeMsg = StrUtil.format(" 【{}】->【{}】", classFeature.getName(), methodFeature.getName());
List<MonitorUserOptModel> monitorUserOptModels = monitorUserOptService.listByType(userOperateLogV1.getWorkspaceId(),
classFeature,
methodFeature,
userOperateLogV1.getUserId());
if (CollUtil.isEmpty(monitorUserOptModels)) {
return;
}
for (MonitorUserOptModel monitorUserOptModel : monitorUserOptModels) {
List<String> notifyUser = monitorUserOptModel.notifyUser();
if (CollUtil.isEmpty(notifyUser)) {
continue;
}
for (String userId : notifyUser) {
UserModel item = userService.getByKey(userId);
if (item == null) {
continue;
}
//
String context = StrUtil.format("操作用户:{}\n操作状态{}\n操作类型{}\n所属工作空间{}\n操作节点{}\n 操作数据id: {}\n操作IP: {}\n{}",
optUserItem.getName(),
userOperateLogV1.getOptStatusMsg(),
optTypeMsg,
workspaceModel == null ? StrUtil.EMPTY : workspaceModel.getName(),
userOperateLogV1.getNodeId(), userOperateLogV1.getDataId(), userOperateLogV1.getIp(), otherMsg);
// 邮箱
String email = item.getEmail();
if (StrUtil.isNotEmpty(email)) {
MonitorModel.Notify notify1 = new MonitorModel.Notify(MonitorModel.NotifyType.mail, email);
ThreadUtil.execute(() -> {
try {
NotifyUtil.send(notify1, "用户操作报警", context);
} catch (Exception e) {
DefaultSystemLog.getLog().error("发送报警信息错误", e);
}
});
}
// dingding
String dingDing = item.getDingDing();
if (StrUtil.isNotEmpty(dingDing)) {
MonitorModel.Notify notify1 = new MonitorModel.Notify(MonitorModel.NotifyType.dingding, dingDing);
ThreadUtil.execute(() -> {
try {
NotifyUtil.send(notify1, "用户操作报警", context);
} catch (Exception e) {
DefaultSystemLog.getLog().error("发送报警信息错误", e);
}
});
}
// 企业微信
String workWx = item.getWorkWx();
if (StrUtil.isNotEmpty(workWx)) {
MonitorModel.Notify notify1 = new MonitorModel.Notify(MonitorModel.NotifyType.workWx, workWx);
ThreadUtil.execute(() -> {
try {
NotifyUtil.send(notify1, "用户操作报警", context);
} catch (Exception e) {
DefaultSystemLog.getLog().error("发送报警信息错误", e);
}
});
}
}
}
}
}
// dingding
String dingDing = item.getDingDing();
if (StrUtil.isNotEmpty(dingDing)) {
MonitorModel.Notify notify1 = new MonitorModel.Notify(MonitorModel.NotifyType.dingding, dingDing);
ThreadUtil.execute(() -> {
try {
NotifyUtil.send(notify1, "用户操作报警", context);
} catch (Exception e) {
DefaultSystemLog.getLog().error("发送报警信息错误", e);
}
});
}
// 企业微信
String workWx = item.getWorkWx();
if (StrUtil.isNotEmpty(workWx)) {
MonitorModel.Notify notify1 = new MonitorModel.Notify(MonitorModel.NotifyType.workWx, workWx);
ThreadUtil.execute(() -> {
try {
NotifyUtil.send(notify1, "用户操作报警", context);
} catch (Exception e) {
DefaultSystemLog.getLog().error("发送报警信息错误", e);
}
});
}
}
}
}
@Override
public void insert(UserOperateLogV1 userOperateLogV1) {
super.insert(userOperateLogV1);
ThreadUtil.execute(() -> {
try {
this.checkMonitor(userOperateLogV1);
} catch (Exception e) {
DefaultSystemLog.getLog().error("执行操作监控错误", e);
}
});
}
@Override
public void insert(UserOperateLogV1 userOperateLogV1) {
super.insert(userOperateLogV1);
ThreadUtil.execute(() -> {
try {
this.checkMonitor(userOperateLogV1);
} catch (Exception e) {
DefaultSystemLog.getLog().error("执行操作监控错误", e);
}
});
}
@Override
public PageResultDto<UserOperateLogV1> listPage(HttpServletRequest request) {
// 验证工作空间权限
Map<String, String> paramMap = ServletUtil.getParamMap(request);
String workspaceId = this.getCheckUserWorkspace(request);
paramMap.put("workspaceId:in", workspaceId + StrUtil.COMMA + StrUtil.EMPTY);
return super.listPage(paramMap);
}
@Override
public PageResultDto<UserOperateLogV1> listPage(HttpServletRequest request) {
// 验证工作空间权限
Map<String, String> paramMap = ServletUtil.getParamMap(request);
String workspaceId = this.getCheckUserWorkspace(request);
paramMap.put("workspaceId:in", workspaceId + StrUtil.COMMA + StrUtil.EMPTY);
return super.listPage(paramMap);
}
@Override
public String getCheckUserWorkspace(HttpServletRequest request) {
// 忽略检查
String header = ServletUtil.getHeader(request, Const.WORKSPACEID_REQ_HEADER, CharsetUtil.CHARSET_UTF_8);
return ObjectUtil.defaultIfNull(header, StrUtil.EMPTY);
}
@Override
public String getCheckUserWorkspace(HttpServletRequest request) {
// 忽略检查
String header = ServletUtil.getHeader(request, Const.WORKSPACEID_REQ_HEADER, CharsetUtil.CHARSET_UTF_8);
return ObjectUtil.defaultIfNull(header, StrUtil.EMPTY);
}
@Override
protected void checkUserWorkspace(String workspaceId, UserModel userModel) {
// 忽略检查
}
@Override
protected void checkUserWorkspace(String workspaceId, UserModel userModel) {
// 忽略检查
}
@Override
protected String[] clearTimeColumns() {
return new String[]{"optTime", "createTimeMillis"};
}
@Override
protected String[] clearTimeColumns() {
return new String[]{"optTime", "createTimeMillis"};
}
}

View File

@ -23,6 +23,7 @@
package io.jpom.service.monitor;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import io.jpom.model.data.MonitorUserOptModel;
import io.jpom.plugin.ClassFeature;
import io.jpom.plugin.MethodFeature;
@ -50,7 +51,10 @@ public class MonitorUserOptService extends BaseWorkspaceService<MonitorUserOptMo
*/
public List<MonitorUserOptModel> listByType(String workspaceId, ClassFeature classFeature, MethodFeature methodFeature, String userId) {
MonitorUserOptModel where = new MonitorUserOptModel();
where.setWorkspaceId(workspaceId);
if (StrUtil.isNotEmpty(workspaceId)) {
// 没有工作空间查询全部
where.setWorkspaceId(workspaceId);
}
where.setStatus(true);
List<MonitorUserOptModel> list = super.listByBean(where);
if (CollUtil.isEmpty(list)) {

View File

@ -26,7 +26,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.LineHandler;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.*;
import cn.hutool.crypto.SecureUtil;
@ -34,17 +33,18 @@ import cn.hutool.extra.ssh.ChannelType;
import cn.hutool.extra.ssh.JschUtil;
import cn.hutool.extra.ssh.Sftp;
import cn.jiangzeyin.common.spring.SpringUtil;
import com.jcraft.jsch.*;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import io.jpom.model.data.SshModel;
import io.jpom.service.h2db.BaseWorkspaceService;
import io.jpom.system.ConfigBean;
import io.jpom.system.ServerExtConfigBean;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@ -57,314 +57,313 @@ import java.util.function.BiFunction;
@Service
public class SshService extends BaseWorkspaceService<SshModel> {
@Override
protected void fillSelectResult(SshModel data) {
if (data == null) {
return;
}
data.setPassword(null);
data.setPrivateKey(null);
}
@Override
protected void fillSelectResult(SshModel data) {
if (data == null) {
return;
}
data.setPassword(null);
data.setPrivateKey(null);
}
/**
* 获取 ssh 回话
*
* @param sshId id
* @return session
*/
public static Session getSession(String sshId) {
SshModel sshModel = SpringUtil.getBean(SshService.class).getByKey(sshId, false);
return getSessionByModel(sshModel);
}
/**
* 获取 ssh 回话
*
* @param sshId id
* @return session
*/
public static Session getSession(String sshId) {
SshModel sshModel = SpringUtil.getBean(SshService.class).getByKey(sshId, false);
return getSessionByModel(sshModel);
}
/**
* 获取 ssh 回话
*
* @param sshModel sshModel
* @return session
*/
public static Session getSessionByModel(SshModel sshModel) {
Session session;
SshModel.ConnectType connectType = sshModel.connectType();
if (connectType == SshModel.ConnectType.PASS) {
session = JschUtil.openSession(sshModel.getHost(), sshModel.getPort(), sshModel.getUser(), sshModel.getPassword());
/**
* 获取 ssh 回话
*
* @param sshModel sshModel
* @return session
*/
public static Session getSessionByModel(SshModel sshModel) {
Session session;
SshModel.ConnectType connectType = sshModel.connectType();
if (connectType == SshModel.ConnectType.PASS) {
session = JschUtil.openSession(sshModel.getHost(), sshModel.getPort(), sshModel.getUser(), sshModel.getPassword());
} else if (connectType == SshModel.ConnectType.PUBKEY) {
File rsaFile;
String privateKey = sshModel.getPrivateKey();
if (StrUtil.startWith(privateKey, URLUtil.FILE_URL_PREFIX)) {
String rsaPath = StrUtil.removePrefix(privateKey, URLUtil.FILE_URL_PREFIX);
rsaFile = FileUtil.file(rsaPath);
} else if (StrUtil.isEmpty(privateKey)) {
File home = FileUtil.getUserHomeDir();
Assert.notNull(home, "用户目录没有找到");
File identity = FileUtil.file(home, ".ssh", "identity");
rsaFile = FileUtil.isFile(identity) ? identity : null;
File idRsa = FileUtil.file(home, ".ssh", "id_rsa");
rsaFile = FileUtil.isFile(idRsa) ? idRsa : rsaFile;
File idDsa = FileUtil.file(home, ".ssh", "id_dsa");
rsaFile = FileUtil.isFile(idDsa) ? idDsa : rsaFile;
Assert.notNull(rsaFile, "用户目录没有找到私钥信息");
} else {
File tempPath = ConfigBean.getInstance().getTempPath();
String sshFile = StrUtil.emptyToDefault(sshModel.getId(), IdUtil.fastSimpleUUID());
rsaFile = FileUtil.file(tempPath, "ssh", sshFile);
FileUtil.writeString(privateKey, rsaFile, CharsetUtil.UTF_8);
}
Assert.state(FileUtil.isFile(rsaFile), "私钥文件不存在:" + FileUtil.getAbsolutePath(rsaFile));
byte[] pas = null;
if (StrUtil.isNotEmpty(sshModel.getPassword())) {
pas = sshModel.getPassword().getBytes();
}
session = JschUtil.openSession(sshModel.getHost(), sshModel.getPort(), sshModel.getUser(), FileUtil.getAbsolutePath(rsaFile), pas);
} else {
throw new IllegalArgumentException("不支持的模式");
}
try {
session.setServerAliveInterval((int) TimeUnit.SECONDS.toMillis(5));
session.setServerAliveCountMax(5);
} catch (JSchException ignored) {
}
return session;
}
} else if (connectType == SshModel.ConnectType.PUBKEY) {
File rsaFile;
String privateKey = sshModel.getPrivateKey();
if (StrUtil.startWith(privateKey, URLUtil.FILE_URL_PREFIX)) {
String rsaPath = StrUtil.removePrefix(privateKey, URLUtil.FILE_URL_PREFIX);
rsaFile = FileUtil.file(rsaPath);
} else if (StrUtil.isEmpty(privateKey)) {
File home = FileUtil.getUserHomeDir();
Assert.notNull(home, "用户目录没有找到");
File identity = FileUtil.file(home, ".ssh", "identity");
rsaFile = FileUtil.isFile(identity) ? identity : null;
File idRsa = FileUtil.file(home, ".ssh", "id_rsa");
rsaFile = FileUtil.isFile(idRsa) ? idRsa : rsaFile;
File idDsa = FileUtil.file(home, ".ssh", "id_dsa");
rsaFile = FileUtil.isFile(idDsa) ? idDsa : rsaFile;
Assert.notNull(rsaFile, "用户目录没有找到私钥信息");
} else {
File tempPath = ConfigBean.getInstance().getTempPath();
String sshFile = StrUtil.emptyToDefault(sshModel.getId(), IdUtil.fastSimpleUUID());
rsaFile = FileUtil.file(tempPath, "ssh", sshFile);
FileUtil.writeString(privateKey, rsaFile, CharsetUtil.UTF_8);
}
Assert.state(FileUtil.isFile(rsaFile), "私钥文件不存在:" + FileUtil.getAbsolutePath(rsaFile));
byte[] pas = null;
if (StrUtil.isNotEmpty(sshModel.getPassword())) {
pas = sshModel.getPassword().getBytes();
}
session = JschUtil.openSession(sshModel.getHost(), sshModel.getPort(), sshModel.getUser(), FileUtil.getAbsolutePath(rsaFile), pas);
} else {
throw new IllegalArgumentException("不支持的模式");
}
try {
session.setServerAliveInterval((int) TimeUnit.SECONDS.toMillis(5));
session.setServerAliveCountMax(5);
} catch (JSchException ignored) {
}
return session;
}
/**
* 检查是否存在正在运行的进程
*
* @param sshModel ssh
* @param tag 标识
* @return true 存在运行中的
* @throws IOException IO
* @throws JSchException jsch
*/
public boolean checkSshRun(SshModel sshModel, String tag) throws IOException, JSchException {
return this.checkSshRunPid(sshModel, tag) != null;
}
/**
* 检查是否存在正在运行的进程
*
* @param sshModel ssh
* @param tag 标识
* @return true 存在运行中的
* @throws IOException IO
* @throws JSchException jsch
*/
public boolean checkSshRun(SshModel sshModel, String tag) throws IOException, JSchException {
return this.checkSshRunPid(sshModel, tag) != null;
}
/**
* 获取 ssh 中的 环境 版本
*
* @param sshModel ssh
* @return 返回
* @throws IOException IO
* @throws JSchException jsch
*/
public String checkCommand(SshModel sshModel, String command) throws IOException, JSchException {
// 检查 环境
List<String> commandResult = this.execCommand(sshModel, "command -v " + command);
return CollUtil.join(commandResult, StrUtil.COMMA);
}
/**
* 获取 ssh 中的 环境 版本
*
* @param sshModel ssh
* @return 返回
* @throws IOException IO
*/
public String checkCommand(SshModel sshModel, String command) throws IOException {
// 检查 环境
return this.exec(sshModel, "command -v " + command);
// return CollUtil.join(commandResult, StrUtil.COMMA);
}
/**
* 检查是否存在正在运行的进程
*
* @param sshModel ssh
* @param tag 标识
* @return true 存在运行中的
* @throws IOException IO
* @throws JSchException jsch
*/
public Integer checkSshRunPid(SshModel sshModel, String tag) throws IOException, JSchException {
String ps = StrUtil.format("ps -ef | grep -v 'grep' | egrep {}", tag);
// 运行中
List<String> result = this.execCommand(sshModel, ps);
return result.stream().map(s -> {
List<String> split = StrUtil.splitTrim(s, StrUtil.SPACE);
return Convert.toInt(CollUtil.get(split, 1));
}).filter(Objects::nonNull).findAny().orElse(null);
}
/**
* 检查是否存在正在运行的进程
*
* @param sshModel ssh
* @param tag 标识
* @return true 存在运行中的
* @throws IOException IO
*/
public Integer checkSshRunPid(SshModel sshModel, String tag) throws IOException {
String ps = StrUtil.format("ps -ef | grep -v 'grep' | egrep {}", tag);
// 运行中
String exec = this.exec(sshModel, ps);
List<String> result = StrUtil.splitTrim(exec, StrUtil.LF);
return result.stream().map(s -> {
List<String> split = StrUtil.splitTrim(s, StrUtil.SPACE);
return Convert.toInt(CollUtil.get(split, 1));
}).filter(Objects::nonNull).findAny().orElse(null);
}
/**
* ssh 执行模版命令
*
* @param sshModel ssh
* @param command 命令
* @return 执行结果
* @throws IOException io
*/
public String exec(SshModel sshModel, String... command) throws IOException {
Charset charset = sshModel.getCharsetT();
return this.exec(sshModel, (s, session) -> {
// 执行命令
String exec, error;
try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
exec = JschUtil.exec(session, s, charset, stream);
error = new String(stream.toByteArray(), charset);
if (StrUtil.isNotEmpty(error)) {
error = " 错误:" + error;
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
return exec + error;
}, command);
}
/**
* ssh 执行模版命令
*
* @param sshModel ssh
* @param command 命令
* @return 执行结果
* @throws IOException io
*/
public String exec(SshModel sshModel, String... command) throws IOException {
Charset charset = sshModel.getCharsetT();
return this.exec(sshModel, (s, session) -> {
// 执行命令
String exec, error;
try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
exec = JschUtil.exec(session, s, charset, stream);
error = new String(stream.toByteArray(), charset);
if (StrUtil.isNotEmpty(error)) {
error = " 错误:" + error;
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
return exec + error;
}, command);
}
/**
* ssh 执行模版命令
*
* @param sshModel ssh
* @param command 命令
* @return 执行结果
* @throws IOException io
*/
public String exec(SshModel sshModel, BiFunction<String, Session, String> function, String... command) throws IOException {
if (ArrayUtil.isEmpty(command)) {
return "没有任何命令";
}
Session session = null;
InputStream sshExecTemplateInputStream = null;
Sftp sftp = null;
try {
String tempId = SecureUtil.sha1(sshModel.getId() + ArrayUtil.join(command, StrUtil.COMMA));
File buildSsh = FileUtil.file(ConfigBean.getInstance().getTempPath(), "ssh_temp", tempId + ".sh");
String sshExecTemplate;
if (ArrayUtil.contains(command, "#disabled-template-auto-evn")) {
sshExecTemplate = StrUtil.EMPTY;
} else {
sshExecTemplateInputStream = ResourceUtil.getStream("classpath:/bin/execTemplate.sh");
sshExecTemplate = IoUtil.readUtf8(sshExecTemplateInputStream);
}
StringBuilder stringBuilder = new StringBuilder(sshExecTemplate);
for (String s : command) {
stringBuilder.append(s).append(StrUtil.LF);
}
Charset charset = sshModel.getCharsetT();
FileUtil.writeString(stringBuilder.toString(), buildSsh, charset);
//
session = getSessionByModel(sshModel);
// 上传文件
sftp = new Sftp(session);
String home = sftp.home();
String path = home + "/.jpom/";
String destFile = path + IdUtil.fastSimpleUUID() + ".sh";
sftp.mkDirs(path);
sftp.upload(destFile, buildSsh);
// 执行命令
try {
String commandSh = "bash " + destFile;
return function.apply(commandSh, session);
} finally {
try {
// 删除 ssh 中临时文件
sftp.delFile(destFile);
} catch (Exception ignored) {
}
// 删除临时文件
FileUtil.del(buildSsh);
}
} finally {
IoUtil.close(sftp);
IoUtil.close(sshExecTemplateInputStream);
JschUtil.close(session);
}
}
/**
* ssh 执行模版命令
*
* @param sshModel ssh
* @param command 命令
* @return 执行结果
* @throws IOException io
*/
public String exec(SshModel sshModel, BiFunction<String, Session, String> function, String... command) throws IOException {
if (ArrayUtil.isEmpty(command)) {
return "没有任何命令";
}
Session session = null;
InputStream sshExecTemplateInputStream = null;
Sftp sftp = null;
try {
String tempId = SecureUtil.sha1(sshModel.getId() + ArrayUtil.join(command, StrUtil.COMMA));
File buildSsh = FileUtil.file(ConfigBean.getInstance().getTempPath(), "ssh_temp", tempId + ".sh");
String sshExecTemplate;
if (ArrayUtil.contains(command, "#disabled-template-auto-evn")) {
sshExecTemplate = StrUtil.EMPTY;
} else {
sshExecTemplateInputStream = ResourceUtil.getStream("classpath:/bin/execTemplate.sh");
sshExecTemplate = IoUtil.readUtf8(sshExecTemplateInputStream);
}
StringBuilder stringBuilder = new StringBuilder(sshExecTemplate);
for (String s : command) {
stringBuilder.append(s).append(StrUtil.LF);
}
Charset charset = sshModel.getCharsetT();
FileUtil.writeString(stringBuilder.toString(), buildSsh, charset);
//
session = getSessionByModel(sshModel);
// 上传文件
sftp = new Sftp(session);
String home = sftp.home();
String path = home + "/.jpom/";
String destFile = path + IdUtil.fastSimpleUUID() + ".sh";
sftp.mkDirs(path);
sftp.upload(destFile, buildSsh);
// 执行命令
try {
String commandSh = "bash " + destFile;
return function.apply(commandSh, session);
} finally {
try {
// 删除 ssh 中临时文件
sftp.delFile(destFile);
} catch (Exception ignored) {
}
// 删除临时文件
FileUtil.del(buildSsh);
}
} finally {
IoUtil.close(sftp);
IoUtil.close(sshExecTemplateInputStream);
JschUtil.close(session);
}
}
/**
* 执行命令
*
* @param sshModel ssh
* @param command 命令
* @return 结果
* @throws IOException io
* @throws JSchException jsch
*/
public String exec(SshModel sshModel, String command) throws IOException, JSchException {
Session session = null;
try {
session = getSessionByModel(sshModel);
return exec(session, sshModel.getCharsetT(), command);
} finally {
JschUtil.close(session);
}
}
// /**
// * 执行命令
// *
// * @param sshModel ssh
// * @param command 命令
// * @return 结果
// * @throws IOException io
// * @throws JSchException jsch
// */
// public String exec(SshModel sshModel, String command) throws IOException, JSchException {
// Session session = null;
// try {
// session = getSessionByModel(sshModel);
// return exec(session, sshModel.getCharsetT(), command);
// } finally {
// JschUtil.close(session);
// }
// }
//
// private String exec(Session session, Charset charset, String command) throws IOException, JSchException {
// ChannelExec channel = null;
// try {
// channel = (ChannelExec) JschUtil.createChannel(session, ChannelType.EXEC);
// // 添加环境变量
// channel.setCommand(ServerExtConfigBean.getInstance().getSshInitEnv() + " && " + command);
// InputStream inputStream = channel.getInputStream();
// InputStream errStream = channel.getErrStream();
// channel.connect();
// // 读取结果
// String result = IoUtil.read(inputStream, charset);
// //
// String error = IoUtil.read(errStream, charset);
// return result + error;
// } finally {
// JschUtil.close(channel);
// }
// }
private String exec(Session session, Charset charset, String command) throws IOException, JSchException {
ChannelExec channel = null;
try {
channel = (ChannelExec) JschUtil.createChannel(session, ChannelType.EXEC);
// 添加环境变量
channel.setCommand(ServerExtConfigBean.getInstance().getSshInitEnv() + " && " + command);
InputStream inputStream = channel.getInputStream();
InputStream errStream = channel.getErrStream();
channel.connect();
// 读取结果
String result = IoUtil.read(inputStream, charset);
//
String error = IoUtil.read(errStream, charset);
return result + error;
} finally {
JschUtil.close(channel);
}
}
// private List<String> execCommand(SshModel sshModel, String command) throws IOException, JSchException {
// Session session = null;
// ChannelExec channel = null;
// try {
// session = getSessionByModel(sshModel);
// channel = (ChannelExec) JschUtil.createChannel(session, ChannelType.EXEC);
// // 添加环境变量
// channel.setCommand(ServerExtConfigBean.getInstance().getSshInitEnv() + " && " + command);
// InputStream inputStream = channel.getInputStream();
// InputStream errStream = channel.getErrStream();
// channel.connect();
// Charset charset = sshModel.getCharsetT();
// // 运行中
// List<String> result = new ArrayList<>();
// IoUtil.readLines(inputStream, charset, (LineHandler) result::add);
// IoUtil.readLines(errStream, charset, (LineHandler) result::add);
// return result;
// } finally {
// JschUtil.close(channel);
// JschUtil.close(session);
// }
// }
private List<String> execCommand(SshModel sshModel, String command) throws IOException, JSchException {
Session session = null;
ChannelExec channel = null;
try {
session = getSessionByModel(sshModel);
channel = (ChannelExec) JschUtil.createChannel(session, ChannelType.EXEC);
// 添加环境变量
channel.setCommand(ServerExtConfigBean.getInstance().getSshInitEnv() + " && " + command);
InputStream inputStream = channel.getInputStream();
InputStream errStream = channel.getErrStream();
channel.connect();
Charset charset = sshModel.getCharsetT();
// 运行中
List<String> result = new ArrayList<>();
IoUtil.readLines(inputStream, charset, (LineHandler) result::add);
IoUtil.readLines(errStream, charset, (LineHandler) result::add);
return result;
} finally {
JschUtil.close(channel);
JschUtil.close(session);
}
}
/**
* 上传文件
*
* @param sshModel ssh
* @param remotePath 远程路径
* @param desc 文件夹或者文件
*/
public void uploadDir(SshModel sshModel, String remotePath, File desc) {
Session session = null;
ChannelSftp channel = null;
try {
session = getSessionByModel(sshModel);
channel = (ChannelSftp) JschUtil.openChannel(session, ChannelType.SFTP);
Sftp sftp = new Sftp(channel, sshModel.getCharsetT());
sftp.syncUpload(desc, remotePath);
//uploadDir(channel, remotePath, desc, sshModel.getCharsetT());
} finally {
JschUtil.close(channel);
JschUtil.close(session);
}
}
/**
* 上传文件
*
* @param sshModel ssh
* @param remotePath 远程路径
* @param desc 文件夹或者文件
*/
public void uploadDir(SshModel sshModel, String remotePath, File desc) {
Session session = null;
ChannelSftp channel = null;
try {
session = getSessionByModel(sshModel);
channel = (ChannelSftp) JschUtil.openChannel(session, ChannelType.SFTP);
Sftp sftp = new Sftp(channel, sshModel.getCharsetT());
sftp.syncUpload(desc, remotePath);
//uploadDir(channel, remotePath, desc, sshModel.getCharsetT());
} finally {
JschUtil.close(channel);
JschUtil.close(session);
}
}
/**
* 下载文件
*
* @param sshModel 实体
* @param remoteFile 远程文件
* @param save 文件对象
* @throws FileNotFoundException io
* @throws SftpException sftp
*/
public void download(SshModel sshModel, String remoteFile, File save) throws FileNotFoundException, SftpException {
Session session = null;
ChannelSftp channel = null;
OutputStream output = null;
try {
session = getSessionByModel(sshModel);
channel = (ChannelSftp) JschUtil.openChannel(session, ChannelType.SFTP);
output = new FileOutputStream(save);
channel.get(remoteFile, output);
} finally {
IoUtil.close(output);
JschUtil.close(channel);
JschUtil.close(session);
}
}
/**
* 下载文件
*
* @param sshModel 实体
* @param remoteFile 远程文件
* @param save 文件对象
* @throws FileNotFoundException io
* @throws SftpException sftp
*/
public void download(SshModel sshModel, String remoteFile, File save) throws FileNotFoundException, SftpException {
Session session = null;
ChannelSftp channel = null;
OutputStream output = null;
try {
session = getSessionByModel(sshModel);
channel = (ChannelSftp) JschUtil.openChannel(session, ChannelType.SFTP);
output = new FileOutputStream(save);
channel.get(remoteFile, output);
} finally {
IoUtil.close(output);
JschUtil.close(channel);
JschUtil.close(session);
}
}
}

View File

@ -67,205 +67,205 @@ import java.util.Set;
*/
@PreLoadClass
public class OperateLogController implements AopLogInterface {
private static final ThreadLocal<CacheInfo> CACHE_INFO_THREAD_LOCAL = new ThreadLocal<>();
private static final ThreadLocal<CacheInfo> CACHE_INFO_THREAD_LOCAL = new ThreadLocal<>();
@PreLoadMethod
private static void init() {
WebAopLog.setAopLogInterface(SpringUtil.getBean(OperateLogController.class));
}
@PreLoadMethod
private static void init() {
WebAopLog.setAopLogInterface(SpringUtil.getBean(OperateLogController.class));
}
private CacheInfo createCacheInfo(Method method) {
Feature feature = method.getAnnotation(Feature.class);
if (feature == null) {
return null;
}
Class<?> declaringClass = method.getDeclaringClass();
MethodFeature methodFeature = feature.method();
if (methodFeature == MethodFeature.NULL) {
DefaultSystemLog.getLog().error("权限分发配置错误:{} {}", declaringClass, method.getName());
return null;
}
ClassFeature classFeature = feature.cls();
if (classFeature == ClassFeature.NULL) {
Feature feature1 = declaringClass.getAnnotation(Feature.class);
if (feature1 == null || feature1.cls() == ClassFeature.NULL) {
DefaultSystemLog.getLog().error("权限分发配置错误:{} {} class not find", declaringClass, method.getName());
return null;
}
classFeature = feature1.cls();
}
CacheInfo cacheInfo = new CacheInfo();
cacheInfo.setClassFeature(classFeature);
cacheInfo.setMethodFeature(methodFeature);
cacheInfo.setOptTime(SystemClock.now());
cacheInfo.setResultCode(feature.resultCode());
cacheInfo.setLogResponse(feature.logResponse());
return cacheInfo;
}
private CacheInfo createCacheInfo(Method method) {
Feature feature = method.getAnnotation(Feature.class);
if (feature == null) {
return null;
}
Class<?> declaringClass = method.getDeclaringClass();
MethodFeature methodFeature = feature.method();
if (methodFeature == MethodFeature.NULL) {
DefaultSystemLog.getLog().error("权限分发配置错误:{} {}", declaringClass, method.getName());
return null;
}
ClassFeature classFeature = feature.cls();
if (classFeature == ClassFeature.NULL) {
Feature feature1 = declaringClass.getAnnotation(Feature.class);
if (feature1 == null || feature1.cls() == ClassFeature.NULL) {
DefaultSystemLog.getLog().error("权限分发配置错误:{} {} class not find", declaringClass, method.getName());
return null;
}
classFeature = feature1.cls();
}
CacheInfo cacheInfo = new CacheInfo();
cacheInfo.setClassFeature(classFeature);
cacheInfo.setMethodFeature(methodFeature);
cacheInfo.setOptTime(SystemClock.now());
cacheInfo.setResultCode(feature.resultCode());
cacheInfo.setLogResponse(feature.logResponse());
return cacheInfo;
}
@Override
public void before(ProceedingJoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
if (signature instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
CacheInfo cacheInfo = this.createCacheInfo(method);
if (cacheInfo == null) {
return;
}
//
ServletRequestAttributes servletRequestAttributes = BaseServerController.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
// 获取ip地址
cacheInfo.ip = ServletUtil.getClientIP(request);
// 获取节点
cacheInfo.nodeModel = (NodeModel) request.getAttribute("node");
//
cacheInfo.dataId = request.getParameter("id");
//
cacheInfo.userAgent = ServletUtil.getHeaderIgnoreCase(request, HttpHeaders.USER_AGENT);
cacheInfo.workspaceId = ServletUtil.getHeaderIgnoreCase(request, Const.WORKSPACEID_REQ_HEADER);
//
Map<String, String> map = ServletUtil.getParamMap(request);
// 过滤密码字段
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
if (StrUtil.containsAnyIgnoreCase(key, "pwd", "password")) {
entry.setValue("***");
}
}
map.put("request_url", request.getRequestURI());
cacheInfo.reqData = JSONObject.toJSONString(map);
CACHE_INFO_THREAD_LOCAL.set(cacheInfo);
}
}
@Override
public void before(ProceedingJoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
if (signature instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
CacheInfo cacheInfo = this.createCacheInfo(method);
if (cacheInfo == null) {
return;
}
//
ServletRequestAttributes servletRequestAttributes = BaseServerController.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
// 获取ip地址
cacheInfo.ip = ServletUtil.getClientIP(request);
// 获取节点
cacheInfo.nodeModel = (NodeModel) request.getAttribute("node");
//
cacheInfo.dataId = request.getParameter("id");
//
cacheInfo.userAgent = ServletUtil.getHeaderIgnoreCase(request, HttpHeaders.USER_AGENT);
cacheInfo.workspaceId = ServletUtil.getHeaderIgnoreCase(request, Const.WORKSPACEID_REQ_HEADER);
//
Map<String, String> map = ServletUtil.getParamMap(request);
// 过滤密码字段
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
if (StrUtil.containsAnyIgnoreCase(key, "pwd", "password")) {
entry.setValue("***");
}
}
map.put("request_url", request.getRequestURI());
cacheInfo.reqData = JSONObject.toJSONString(map);
CACHE_INFO_THREAD_LOCAL.set(cacheInfo);
}
}
@Override
public void afterReturning(Object value) {
try {
CacheInfo cacheInfo = CACHE_INFO_THREAD_LOCAL.get();
if (cacheInfo == null || cacheInfo.methodFeature == MethodFeature.LIST) {
return;
}
if (cacheInfo.classFeature == null || cacheInfo.methodFeature == null) {
new RuntimeException("权限功能没有配置正确").printStackTrace();
return;
}
UserModel userModel = BaseServerController.getUserByThreadLocal();
userModel = userModel == null ? BaseServerController.getUserModel() : userModel;
// 没有对应的用户
if (userModel == null) {
return;
}
this.log(userModel, value, cacheInfo);
} finally {
CACHE_INFO_THREAD_LOCAL.remove();
}
}
@Override
public void afterReturning(Object value) {
try {
CacheInfo cacheInfo = CACHE_INFO_THREAD_LOCAL.get();
if (cacheInfo == null || cacheInfo.methodFeature == MethodFeature.LIST) {
return;
}
if (cacheInfo.classFeature == null || cacheInfo.methodFeature == null) {
new RuntimeException("权限功能没有配置正确").printStackTrace();
return;
}
UserModel userModel = BaseServerController.getUserByThreadLocal();
userModel = userModel == null ? BaseServerController.getUserModel() : userModel;
// 没有对应的用户
if (userModel == null) {
return;
}
this.log(userModel, value, cacheInfo);
} finally {
CACHE_INFO_THREAD_LOCAL.remove();
}
}
/**
* 记录操作日志
*
* @param userModel 用户
* @param value 返回执行
* @param cacheInfo 请求信息
*/
public void log(UserModel userModel, Object value, CacheInfo cacheInfo) {
UserOperateLogV1 userOperateLogV1 = new UserOperateLogV1();
userOperateLogV1.setWorkspaceId(cacheInfo.workspaceId);
userOperateLogV1.setClassFeature(cacheInfo.classFeature.name());
userOperateLogV1.setMethodFeature(cacheInfo.methodFeature.name());
userOperateLogV1.setDataId(cacheInfo.dataId);
userOperateLogV1.setUserId(userModel.getId());
userOperateLogV1.setIp(cacheInfo.ip);
userOperateLogV1.setUserAgent(cacheInfo.userAgent);
userOperateLogV1.setReqData(cacheInfo.reqData);
userOperateLogV1.setOptTime(ObjectUtil.defaultIfNull(cacheInfo.optTime, SystemClock.now()));
if (value != null) {
// 解析结果
if (value instanceof Throwable) {
// 发生异常
Throwable throwable = (Throwable) value;
userOperateLogV1.setResultMsg(ExceptionUtil.stacktraceToString(throwable));
userOperateLogV1.setOptStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
} else {
String json = value.toString();
userOperateLogV1.setResultMsg(json);
try {
JsonMessage<String> jsonMessage = JSONObject.parseObject(json, JsonMessage.class);
int code = jsonMessage.getCode();
int[] resultCode = cacheInfo.getResultCode();
if (ArrayUtil.isNotEmpty(resultCode) && !ArrayUtil.contains(resultCode, code)) {
// 忽略
return;
}
userOperateLogV1.setOptStatus(code);
} catch (Exception ignored) {
}
}
// 判断是否记录响应日志
Boolean logResponse = cacheInfo.getLogResponse();
if (logResponse != null && !logResponse) {
userOperateLogV1.setResultMsg("*****");
}
}
//
if (cacheInfo.nodeModel != null) {
userOperateLogV1.setNodeId(cacheInfo.nodeModel.getId());
if (StrUtil.isEmpty(cacheInfo.workspaceId)) {
userOperateLogV1.setWorkspaceId(cacheInfo.nodeModel.getWorkspaceId());
}
}
//
try {
BaseServerController.resetInfo(UserModel.EMPTY);
DbUserOperateLogService dbUserOperateLogService = SpringUtil.getBean(DbUserOperateLogService.class);
dbUserOperateLogService.insert(userOperateLogV1);
} finally {
BaseServerController.removeEmpty();
}
}
/**
* 记录操作日志
*
* @param userModel 用户
* @param value 返回执行
* @param cacheInfo 请求信息
*/
public void log(UserModel userModel, Object value, CacheInfo cacheInfo) {
UserOperateLogV1 userOperateLogV1 = new UserOperateLogV1();
userOperateLogV1.setWorkspaceId(cacheInfo.workspaceId);
userOperateLogV1.setClassFeature(cacheInfo.classFeature.name());
userOperateLogV1.setMethodFeature(cacheInfo.methodFeature.name());
userOperateLogV1.setDataId(cacheInfo.dataId);
userOperateLogV1.setUserId(userModel.getId());
userOperateLogV1.setIp(cacheInfo.ip);
userOperateLogV1.setUserAgent(cacheInfo.userAgent);
userOperateLogV1.setReqData(cacheInfo.reqData);
userOperateLogV1.setOptTime(ObjectUtil.defaultIfNull(cacheInfo.optTime, SystemClock.now()));
if (value != null) {
// 解析结果
if (value instanceof Throwable) {
// 发生异常
Throwable throwable = (Throwable) value;
userOperateLogV1.setResultMsg(ExceptionUtil.stacktraceToString(throwable));
userOperateLogV1.setOptStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
} else {
String json = value.toString();
userOperateLogV1.setResultMsg(json);
try {
JsonMessage<?> jsonMessage = JSONObject.parseObject(json, JsonMessage.class);
int code = jsonMessage.getCode();
int[] resultCode = cacheInfo.getResultCode();
if (ArrayUtil.isNotEmpty(resultCode) && !ArrayUtil.contains(resultCode, code)) {
// 忽略
return;
}
userOperateLogV1.setOptStatus(code);
} catch (Exception ignored) {
}
}
// 判断是否记录响应日志
Boolean logResponse = cacheInfo.getLogResponse();
if (logResponse != null && !logResponse) {
userOperateLogV1.setResultMsg(new cn.hutool.json.JSONObject().putOpt("hide", "*****").toString());
}
}
//
if (cacheInfo.nodeModel != null) {
userOperateLogV1.setNodeId(cacheInfo.nodeModel.getId());
if (StrUtil.isEmpty(cacheInfo.workspaceId)) {
userOperateLogV1.setWorkspaceId(cacheInfo.nodeModel.getWorkspaceId());
}
}
//
try {
BaseServerController.resetInfo(UserModel.EMPTY);
DbUserOperateLogService dbUserOperateLogService = SpringUtil.getBean(DbUserOperateLogService.class);
dbUserOperateLogService.insert(userOperateLogV1);
} finally {
BaseServerController.removeEmpty();
}
}
/**
* 修改执行结果
*
* @param reqId 请求id
* @param val 结果
*/
public void updateLog(String reqId, String val) {
DbUserOperateLogService dbUserOperateLogService = SpringUtil.getBean(DbUserOperateLogService.class);
/**
* 修改执行结果
*
* @param reqId 请求id
* @param val 结果
*/
public void updateLog(String reqId, String val) {
DbUserOperateLogService dbUserOperateLogService = SpringUtil.getBean(DbUserOperateLogService.class);
Entity entity = new Entity();
entity.set("resultMsg", val);
try {
JsonMessage<?> jsonMessage = JSONObject.parseObject(val, JsonMessage.class);
entity.set("optStatus", jsonMessage.getCode());
} catch (Exception ignored) {
}
//
Entity where = new Entity();
where.set("reqId", reqId);
dbUserOperateLogService.update(entity, where);
}
Entity entity = new Entity();
entity.set("resultMsg", val);
try {
JsonMessage<?> jsonMessage = JSONObject.parseObject(val, JsonMessage.class);
entity.set("optStatus", jsonMessage.getCode());
} catch (Exception ignored) {
}
//
Entity where = new Entity();
where.set("reqId", reqId);
dbUserOperateLogService.update(entity, where);
}
/**
* 临时缓存
*/
@Data
public static class CacheInfo {
private Long optTime;
private String workspaceId;
private ClassFeature classFeature;
private MethodFeature methodFeature;
private String ip;
private NodeModel nodeModel;
private String dataId;
private String userAgent;
private String reqData;
private int[] resultCode;
private Boolean logResponse;
}
/**
* 临时缓存
*/
@Data
public static class CacheInfo {
private Long optTime;
private String workspaceId;
private ClassFeature classFeature;
private MethodFeature methodFeature;
private String ip;
private NodeModel nodeModel;
private String dataId;
private String userAgent;
private String reqData;
private int[] resultCode;
private Boolean logResponse;
}
}

View File

@ -411,11 +411,11 @@ export default {
this.$store.dispatch("toggleFullScreenFlag").then((flag) => {
if (flag) {
this.$notification.success({
message: "页面内容自动撑开出现滚动条",
message: "页面内容自动撑开出现屏幕滚动条",
});
} else {
this.$notification.success({
message: "页面全屏,高度 100%",
message: "页面全屏,高度 100%。局部区域可以滚动",
});
}
});

View File

@ -1,7 +1,7 @@
<template>
<div class="node-full-content">
<!-- 数据表格 -->
<a-table :data-source="list" :columns="columns" @change="changePage" :pagination="this.listQuery.total / this.listQuery.limit > 1 ? (this, pagination) : false" bordered rowKey="id">
<a-table :data-source="list" size="middle" :columns="columns" @change="changePage" :pagination="this.listQuery.total / this.listQuery.limit > 1 ? (this, pagination) : false" bordered rowKey="id">
<template slot="title">
<a-space>
<a-select v-model="listQuery.nodeId" allowClear placeholder="请选择节点" class="search-input-item">
@ -154,7 +154,7 @@ export default {
{ title: "修改时间", dataIndex: "modifyTimeMillis", width: 170, sorter: true, ellipsis: true, scopedSlots: { customRender: "modifyTimeMillis" } },
{ title: "修改人", dataIndex: "modifyUser", ellipsis: true, scopedSlots: { customRender: "modifyUser" }, width: 120 },
{ title: "最后操作人", dataIndex: "lastRunUser", ellipsis: true, scopedSlots: { customRender: "lastRunUser" } },
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 240 },
{ title: "操作", dataIndex: "operation", align: "center", scopedSlots: { customRender: "operation" }, width: 220 },
],
rules: {
name: [{ required: true, message: "Please input Script name", trigger: "blur" }],