feat 项目支持软链其他项目(代替项目副本)

This commit is contained in:
bwcx_jzy 2023-12-31 21:43:25 +08:00
parent 3492510832
commit 8b996c02cd
No known key found for this signature in database
GPG Key ID: E187D6E9DDDE8C53
69 changed files with 1212 additions and 1496 deletions

View File

@ -4,6 +4,8 @@
### 🐣 新增功能
1. 【all】新增 项目支持软链其他项目(代替项目副本)
### 🐞 解决BUG、优化功能
@ -16,10 +18,13 @@
7. 【agent】取消 插件端授权目录关闭包含判断(`jpom.whitelist.check-starts-with`)
8. 【server】优化 触发器清理优化、删除用户主动删除关联触发器
9. 【server】优化 DSL 项目控制台支持快捷编辑节点脚本(查看流程信息)
10. 【server】修复 项目触发器无法调用
### ⚠️ 注意
1. 如果您配置了授权目录但是保存项目报错您可以尝试重新报错一下授权目录来自动修复授权目录配置数据
2. 项目控制台日志默认路径调整为插件端数据目录下`project-log/${projectId}/${projectId}.log`
3. 项目控制台日志备份默认路径调整为插件端数据目录下`project-log/${projectId}/back/${projectId}-xxxxxxx.log`
------

View File

@ -35,6 +35,7 @@ import cn.hutool.core.map.SafeConcurrentHashMap;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.system.SystemUtil;
import cn.keepbx.jpom.plugins.IPlugin;
@ -65,6 +66,7 @@ import java.util.function.BiFunction;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
/**
* 项目命令执行基类
@ -116,6 +118,14 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
*/
public abstract String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel);
/**
* 生成可以执行的命令
*
* @param nodeProjectInfoModel 项目
* @return null 是条件不足
*/
public abstract String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel);
protected String getRunJavaPath(NodeProjectInfoModel nodeProjectInfoModel, boolean w) {
// if (StrUtil.isEmpty(nodeProjectInfoModel.getJdkId())) {
// return w ? "javaw" : "java";
@ -131,16 +141,6 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
// return jdkJavaPath;
}
/**
* 启动
*
* @param nodeProjectInfoModel 项目
* @return 结果
*/
protected CommandOpResult start(NodeProjectInfoModel nodeProjectInfoModel) {
return this.start(nodeProjectInfoModel, false);
}
/**
* 启动
*
@ -148,18 +148,18 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param sync dsl 是否同步执行
* @return 结果
*/
protected CommandOpResult start(NodeProjectInfoModel nodeProjectInfoModel, boolean sync) {
String msg = checkStart(nodeProjectInfoModel);
protected CommandOpResult start(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, boolean sync) {
String msg = this.checkStart(nodeProjectInfoModel, originalModel);
if (msg != null) {
return CommandOpResult.of(false, msg);
}
RunMode runMode = nodeProjectInfoModel.getRunMode();
RunMode runMode = originalModel.getRunMode();
if (runMode == RunMode.Dsl) {
//
this.runDsl(nodeProjectInfoModel, ConsoleCommandOp.start.name(), (baseProcess, action) -> {
String log = nodeProjectInfoModel.absoluteLog();
this.runDsl(originalModel, ConsoleCommandOp.start.name(), (baseProcess, action) -> {
String log = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
try {
dslScriptServer.run(baseProcess, nodeProjectInfoModel, action, log, sync);
dslScriptServer.run(baseProcess, nodeProjectInfoModel, originalModel, action, log, sync);
} catch (Exception e) {
throw Lombok.sneakyThrow(e);
}
@ -167,14 +167,14 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
});
} else {
String command = this.buildRunCommand(nodeProjectInfoModel);
String command = this.buildRunCommand(nodeProjectInfoModel, originalModel);
if (command == null) {
return CommandOpResult.of(false, "没有需要执行的命令");
}
// 执行命令
ThreadUtil.execute(() -> {
try {
File file = FileUtil.file(nodeProjectInfoModel.allLib());
File file = projectInfoService.resolveLibFile(nodeProjectInfoModel);
if (SystemUtil.getOsInfo().isWindows()) {
CommandUtil.execSystemCommand(command, file);
} else {
@ -186,9 +186,9 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
});
}
//
this.loopCheckRun(nodeProjectInfoModel, true);
CommandOpResult status = this.status(nodeProjectInfoModel);
this.asyncWebHooks(nodeProjectInfoModel, "start", "result", status.msgStr());
this.loopCheckRun(nodeProjectInfoModel, originalModel, true);
CommandOpResult status = this.status(nodeProjectInfoModel, originalModel);
this.asyncWebHooks(nodeProjectInfoModel, originalModel, "start", "result", status.msgStr());
return status;
}
@ -206,15 +206,6 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
*/
protected abstract List<NetstatModel> listNetstat(int pid, boolean listening);
/**
* 停止
*
* @param nodeProjectInfoModel 项目
* @return 结果
*/
protected CommandOpResult stop(NodeProjectInfoModel nodeProjectInfoModel) {
return this.stop(nodeProjectInfoModel, false);
}
/**
* 停止
@ -223,40 +214,39 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param sync dsl 是否同步执行
* @return 结果
*/
protected CommandOpResult stop(NodeProjectInfoModel nodeProjectInfoModel, boolean sync) {
protected CommandOpResult stop(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, boolean sync) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
if (runMode == RunMode.File) {
return CommandOpResult.of(true, "file 类型项目没有 stop");
}
Tuple tuple = this.stopBefore(nodeProjectInfoModel);
Tuple tuple = this.stopBefore(nodeProjectInfoModel, originalModel);
CommandOpResult status = tuple.get(1);
String webHook = tuple.get(0);
if (status.isSuccess()) {
// 运行中
if (runMode == RunMode.Dsl) {
//
this.runDsl(nodeProjectInfoModel, ConsoleCommandOp.stop.name(), (process, action) -> {
String log = nodeProjectInfoModel.absoluteLog();
this.runDsl(originalModel, ConsoleCommandOp.stop.name(), (process, action) -> {
String log = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
try {
dslScriptServer.run(process, nodeProjectInfoModel, action, log, sync);
dslScriptServer.run(process, nodeProjectInfoModel, originalModel, action, log, sync);
} catch (Exception e) {
throw Lombok.sneakyThrow(e);
}
return null;
});
boolean checkRun = this.loopCheckRun(nodeProjectInfoModel, false);
boolean checkRun = this.loopCheckRun(nodeProjectInfoModel, originalModel, false);
return CommandOpResult.of(checkRun, checkRun ? "stop done" : "stop done,but unsuccessful")
.appendMsg(status.getMsgs())
.appendMsg(webHook);
} else {
//
return this.stopJava(nodeProjectInfoModel, status.getPid()).appendMsg(status.getMsgs()).appendMsg(webHook);
return this.stopJava(nodeProjectInfoModel, originalModel, status.getPid()).appendMsg(status.getMsgs()).appendMsg(webHook);
}
}
return CommandOpResult.of(true).
appendMsg(status.getMsgs()).
appendMsg(webHook);
}
@ -267,7 +257,7 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param pid 进程ID
* @return 结果
*/
protected abstract CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, int pid);
protected abstract CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int pid);
/**
* 停止之前
@ -275,15 +265,15 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param nodeProjectInfoModel 项目
* @return 结果
*/
private Tuple stopBefore(NodeProjectInfoModel nodeProjectInfoModel) {
String beforeStop = this.webHooks(nodeProjectInfoModel, "beforeStop");
private Tuple stopBefore(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
String beforeStop = this.webHooks(nodeProjectInfoModel.token(), nodeProjectInfoModel, "beforeStop");
// 再次查看进程信息
CommandOpResult result = this.status(nodeProjectInfoModel);
CommandOpResult result = this.status(nodeProjectInfoModel, originalModel);
if (result.isSuccess()) {
// 端口号缓存
PID_PORT.remove(result.getPid());
}
this.asyncWebHooks(nodeProjectInfoModel, "stop", "result", result);
this.asyncWebHooks(nodeProjectInfoModel, originalModel, "stop", "result", result);
return new Tuple(StrUtil.emptyToDefault(beforeStop, StrUtil.EMPTY), result);
}
@ -295,13 +285,29 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param other 其他参数
*/
public void asyncWebHooks(NodeProjectInfoModel nodeProjectInfoModel,
String type, Object... other) {
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
this.asyncWebHooks(nodeProjectInfoModel, infoModel, type, other);
}
/**
* 执行 webhooks 通知
*
* @param nodeProjectInfoModel 项目信息
* @param type 类型
* @param other 其他参数
*/
public void asyncWebHooks(NodeProjectInfoModel nodeProjectInfoModel,
NodeProjectInfoModel originalModel,
String type, Object... other) {
// webhook 通知
Opt.ofBlankAble(nodeProjectInfoModel.token())
.ifPresent(s ->
ThreadUtil.execute(() -> {
try {
this.webHooks(nodeProjectInfoModel, type, other);
String result = this.webHooks(s, nodeProjectInfoModel, type, other);
Optional.ofNullable(result).ifPresent(s1 -> log.debug("[{}]-{}触发器结果:{}", nodeProjectInfoModel.getId(), type, s1));
} catch (Exception e) {
log.error("project webhook", e);
}
@ -309,9 +315,9 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
);
// 判断文件变动
if (StrUtil.equals(type, "fileChange")) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
RunMode runMode = originalModel.getRunMode();
if (runMode == RunMode.Dsl) {
DslYmlDto dslYmlDto = nodeProjectInfoModel.mustDslConfig();
DslYmlDto dslYmlDto = originalModel.mustDslConfig();
if (dslYmlDto.hasRunProcess(ConsoleCommandOp.reload.name())) {
DslYmlDto.Run run = dslYmlDto.getRun();
Boolean fileChangeReload = run.getFileChangeReload();
@ -319,7 +325,7 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
// 需要执行重载事件
ThreadUtil.execute(() -> {
try {
CommandOpResult reload = this.reload(nodeProjectInfoModel);
CommandOpResult reload = this.reload(nodeProjectInfoModel, originalModel);
log.info("触发项目 reload 事件:{}", reload);
} catch (Exception e) {
log.error("重载项目异常", e);
@ -339,8 +345,7 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param other 其他参数
* @return 结果
*/
private String webHooks(NodeProjectInfoModel nodeProjectInfoModel, String type, Object... other) {
String token = nodeProjectInfoModel.token();
private String webHooks(String token, NodeProjectInfoModel nodeProjectInfoModel, String type, Object... other) {
if (StrUtil.isEmpty(token)) {
return null;
}
@ -367,39 +372,39 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param nodeProjectInfoModel 项目
* @return 结果
*/
protected CommandOpResult restart(NodeProjectInfoModel nodeProjectInfoModel) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
protected CommandOpResult restart(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
RunMode runMode = originalModel.getRunMode();
if (runMode == RunMode.File) {
return CommandOpResult.of(true, "file 类型项目没有 restart");
}
this.asyncWebHooks(nodeProjectInfoModel, "beforeRestart");
this.asyncWebHooks(nodeProjectInfoModel, originalModel, "beforeRestart");
if (runMode == RunMode.Dsl) {
DslYmlDto.BaseProcess dslProcess = nodeProjectInfoModel.tryDslProcess(ConsoleCommandOp.restart.name());
DslYmlDto.BaseProcess dslProcess = originalModel.tryDslProcess(ConsoleCommandOp.restart.name());
if (dslProcess != null) {
// 如果存在自定义 restart 流程
//
this.runDsl(nodeProjectInfoModel, ConsoleCommandOp.restart.name(), (process, action) -> {
String log = nodeProjectInfoModel.absoluteLog();
this.runDsl(originalModel, ConsoleCommandOp.restart.name(), (process, action) -> {
String log = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
try {
dslScriptServer.run(process, nodeProjectInfoModel, action, log, false);
dslScriptServer.run(process, nodeProjectInfoModel, originalModel, action, log, false);
} catch (Exception e) {
throw Lombok.sneakyThrow(e);
}
return null;
});
// 等待 状态成功
boolean run = this.loopCheckRun(nodeProjectInfoModel, true);
boolean run = this.loopCheckRun(nodeProjectInfoModel, originalModel, true);
return CommandOpResult.of(run, run ? "restart done" : "restart done,but unsuccessful");
//return new Tuple(run ? "restart done,but unsuccessful" : "restart done", resultMsg);
}
}
boolean run = this.isRun(nodeProjectInfoModel);
boolean run = this.isRun(nodeProjectInfoModel, originalModel);
CommandOpResult stopMsg = null;
if (run) {
stopMsg = this.stop(nodeProjectInfoModel, true);
stopMsg = this.stop(nodeProjectInfoModel, originalModel, true);
}
CommandOpResult startMsg = this.start(nodeProjectInfoModel);
CommandOpResult startMsg = this.start(nodeProjectInfoModel, originalModel, false);
if (stopMsg != null) {
startMsg.appendMsg(stopMsg.getMsgs());
}
@ -412,25 +417,25 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param nodeProjectInfoModel 项目
* @return null 检查一切正常
*/
private String checkStart(NodeProjectInfoModel nodeProjectInfoModel) {
CommandOpResult status = this.status(nodeProjectInfoModel);
private String checkStart(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
CommandOpResult status = this.status(nodeProjectInfoModel, originalModel);
if (status.isSuccess()) {
return "当前程序正在运行中,不能重复启动,PID:" + status.getPid();
}
String lib = nodeProjectInfoModel.allLib();
File fileLib = new File(lib);
File fileLib = projectInfoService.resolveLibFile(nodeProjectInfoModel);
File[] files = fileLib.listFiles();
if (files == null || files.length == 0) {
return "项目目录没有任何文件,请先到项目文件管理中上传文件";
}
//
RunMode runMode = nodeProjectInfoModel.getRunMode();
if (runMode == RunMode.Dsl) {
RunMode checkRunMode = originalModel.getRunMode();
if (checkRunMode == RunMode.Dsl) {
//
String dslContent = nodeProjectInfoModel.getDslContent();
} else if (runMode == RunMode.ClassPath || runMode == RunMode.JavaExtDirsCp) {
originalModel.mustDslConfig();
} else if (checkRunMode == RunMode.ClassPath || checkRunMode == RunMode.JavaExtDirsCp) {
// 判断主类
String mainClass = nodeProjectInfoModel.mainClass();
String mainClass = originalModel.mainClass();
try (JarClassLoader jarClassLoader = JarClassLoader.load(fileLib)) {
jarClassLoader.loadClass(mainClass);
} catch (ClassNotFoundException notFound) {
@ -438,10 +443,11 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
} catch (IOException io) {
throw Lombok.sneakyThrow(io);
}
} else if (runMode == RunMode.Jar || runMode == RunMode.JarWar) {
List<File> fileList = NodeProjectInfoModel.listJars(nodeProjectInfoModel);
} else if (checkRunMode == RunMode.Jar || checkRunMode == RunMode.JarWar) {
List<File> fileList = this.listJars(checkRunMode, fileLib);
if (fileList.isEmpty()) {
return String.format("一级目录没有%s包,请先到文件管理中上传程序的%s", runMode.name(), runMode.name());
return String.format("一级目录没有%s包,请先到文件管理中上传程序的%s", checkRunMode.name(), checkRunMode.name());
}
File jarFile = fileList.get(0);
String checkJar = checkJar(jarFile);
@ -452,10 +458,16 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
return "当前项目类型不支持启动";
}
// 备份日志
backLog(nodeProjectInfoModel);
this.backLog(nodeProjectInfoModel, originalModel);
return null;
}
/**
* 校验jar包
*
* @param jarFile jar 文件
* @return mainClass
*/
private static String checkJar(File jarFile) {
try (JarFile jarFile1 = new JarFile(jarFile)) {
Manifest manifest = jarFile1.getManifest();
@ -482,11 +494,11 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param nodeProjectInfoModel 项目实体
* @return true 开启日志备份
*/
private boolean resolveOpenLogBack(NodeProjectInfoModel nodeProjectInfoModel) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
private boolean resolveOpenLogBack(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
RunMode runMode = originalModel.getRunMode();
boolean autoBackToFile = projectLogConfig.isAutoBackupToFile();
if (runMode == RunMode.Dsl) {
return Optional.ofNullable(nodeProjectInfoModel.dslConfig())
return Optional.ofNullable(originalModel.dslConfig())
.map(DslYmlDto::getConfig)
.map(DslYmlDto.Config::getAutoBackToFile)
.orElse(autoBackToFile);
@ -501,7 +513,18 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @return 结果
*/
public String backLog(NodeProjectInfoModel nodeProjectInfoModel) {
File file = nodeProjectInfoModel.absoluteLogFile();
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
return this.backLog(nodeProjectInfoModel, infoModel);
}
/**
* 清空日志信息
*
* @param nodeProjectInfoModel 项目
* @return 结果
*/
public String backLog(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
File file = projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel, originalModel);
if (!file.exists() || file.isDirectory()) {
return "not exists";
}
@ -510,11 +533,12 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
if (file.length() <= BACK_LOG_MIN_SIZE) {
return "ok";
}
boolean openLogBack = this.resolveOpenLogBack(nodeProjectInfoModel);
boolean openLogBack = this.resolveOpenLogBack(nodeProjectInfoModel, originalModel);
if (openLogBack) {
// 开启日志备份才移动文件
File backPath = nodeProjectInfoModel.logBack();
backPath = new File(backPath, DateTime.now().toString(DatePattern.PURE_DATETIME_FORMAT) + ".log");
File backPath = projectInfoService.resolveLogBack(nodeProjectInfoModel, originalModel);
String pathId = nodeProjectInfoModel.getId() + "-" + DateTime.now().toString(DatePattern.PURE_DATETIME_FORMAT) + ".log";
backPath = new File(backPath, pathId);
FileUtil.copy(file, backPath, true);
}
// 清空日志
@ -534,15 +558,26 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @return 状态
*/
protected CommandOpResult status(NodeProjectInfoModel nodeProjectInfoModel) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
NodeProjectInfoModel originalModel = projectInfoService.resolveModel(nodeProjectInfoModel);
return this.status(nodeProjectInfoModel, originalModel);
}
/**
* 查询项目状态
*
* @param nodeProjectInfoModel 项目
* @return 状态
*/
protected CommandOpResult status(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
RunMode runMode = originalModel.getRunMode();
if (runMode == RunMode.File) {
return CommandOpResult.of(false, "file 类型项目没有运行状态");
}
if (runMode == RunMode.Dsl) {
List<String> status = this.runDsl(nodeProjectInfoModel, ConsoleCommandOp.status.name(), (baseProcess, action) -> {
List<String> status = this.runDsl(originalModel, ConsoleCommandOp.status.name(), (baseProcess, action) -> {
// 提前判断脚本 id,避免填写错误在删除项目检测状态时候异常
try {
Tuple tuple = dslScriptServer.syncRun(baseProcess, nodeProjectInfoModel, action);
Tuple tuple = dslScriptServer.syncRun(baseProcess, nodeProjectInfoModel, originalModel, action);
return tuple.get(1);
} catch (IllegalArgument2Exception argument2Exception) {
log.warn("执行 DSL 脚本异常:{}", argument2Exception.getMessage());
@ -552,7 +587,7 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
return Optional.ofNullable(status)
.map(strings -> {
File log = nodeProjectInfoModel.absoluteLogFile();
File log = projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel, originalModel);
FileUtil.appendLines(strings, log, fileCharset);
return strings;
})
@ -580,13 +615,13 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @param nodeProjectInfoModel 项目
* @return 结果
*/
protected CommandOpResult reload(NodeProjectInfoModel nodeProjectInfoModel) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
protected CommandOpResult reload(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
RunMode runMode = originalModel.getRunMode();
Assert.state(runMode == RunMode.Dsl, "非 DSL 项目不支持此操作");
CommandOpResult commandOpResult = this.runDsl(nodeProjectInfoModel, ConsoleCommandOp.reload.name(), (baseProcess, action) -> {
CommandOpResult commandOpResult = this.runDsl(originalModel, ConsoleCommandOp.reload.name(), (baseProcess, action) -> {
// 提前判断脚本 id,避免填写错误在删除项目检测状态时候异常
try {
Tuple tuple = dslScriptServer.syncRun(baseProcess, nodeProjectInfoModel, action);
Tuple tuple = dslScriptServer.syncRun(baseProcess, nodeProjectInfoModel, originalModel, action);
int code = tuple.get(0);
List<String> list = tuple.get(1);
// 如果退出码为 0 认为执行成功
@ -715,7 +750,18 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @return true 正在运行
*/
public boolean isRun(NodeProjectInfoModel nodeProjectInfoModel) {
CommandOpResult result = this.status(nodeProjectInfoModel);
NodeProjectInfoModel originalModel = projectInfoService.resolveModel(nodeProjectInfoModel);
return this.isRun(nodeProjectInfoModel, originalModel);
}
/**
* 是否正在运行
*
* @param nodeProjectInfoModel 项目
* @return true 正在运行
*/
public boolean isRun(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
CommandOpResult result = this.status(nodeProjectInfoModel, originalModel);
return result.isSuccess();
}
@ -726,9 +772,9 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
*
* @return 和参数status相反
*/
protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, boolean status) {
protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, boolean status) {
int statusWaitTime = projectConfig.getStatusWaitTime();
return this.loopCheckRun(nodeProjectInfoModel, statusWaitTime, status);
return this.loopCheckRun(nodeProjectInfoModel, originalModel, statusWaitTime, status);
}
/***
@ -739,14 +785,14 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
*
* @return 如果和期望一致则返回 true反之 false
*/
protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, int waitTime, boolean status) {
protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int waitTime, boolean status) {
waitTime = Math.max(waitTime, 1);
int statusDetectionInterval = projectConfig.getStatusDetectionInterval();
statusDetectionInterval = Math.max(statusDetectionInterval, 1);
int loopCount = (int) (TimeUnit.SECONDS.toMillis(waitTime) / 500);
int count = 0;
do {
if (this.isRun(nodeProjectInfoModel) == status) {
if (this.isRun(nodeProjectInfoModel, originalModel) == status) {
// 是期望的结果
return true;
}
@ -763,24 +809,25 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
* @return 执行结果
*/
public CommandOpResult execCommand(ConsoleCommandOp consoleCommandOp, NodeProjectInfoModel nodeProjectInfoModel) {
NodeProjectInfoModel originalModel = projectInfoService.resolveModel(nodeProjectInfoModel);
CommandOpResult result;
// 执行命令
switch (consoleCommandOp) {
case restart:
result = this.restart(nodeProjectInfoModel);
result = this.restart(nodeProjectInfoModel, originalModel);
break;
case start:
result = this.start(nodeProjectInfoModel);
result = this.start(nodeProjectInfoModel, originalModel, false);
break;
case stop:
result = this.stop(nodeProjectInfoModel);
result = this.stop(nodeProjectInfoModel, originalModel, false);
break;
case status: {
result = this.status(nodeProjectInfoModel);
result = this.status(nodeProjectInfoModel, originalModel);
break;
}
case reload: {
result = this.reload(nodeProjectInfoModel);
result = this.reload(nodeProjectInfoModel, originalModel);
break;
}
case showlog:
@ -789,4 +836,88 @@ public abstract class AbstractProjectCommander implements ProjectCommander {
}
return result;
}
/**
* 获取项目文件中的所有jar 文件
*
* @param runMode 运行模式
* @param path 目录
* @return list
*/
protected List<File> listJars(RunMode runMode, String path) {
//File fileLib = projectInfoService.resolveLibFile(nodeProjectInfoModel);
return this.listJars(runMode, FileUtil.file(path));
}
/**
* 获取项目文件中的所有jar 文件
*
* @param runMode 运行模式
* @param path 目录
* @return list
*/
protected List<File> listJars(RunMode runMode, File path) {
File[] files = path.listFiles();
if (files == null) {
return new ArrayList<>();
}
return Arrays.stream(files)
.filter(File::isFile)
.filter(file -> {
if (runMode == RunMode.ClassPath || runMode == RunMode.Jar || runMode == RunMode.JavaExtDirsCp) {
return StrUtil.endWith(file.getName(), FileUtil.JAR_FILE_EXT, true);
} else if (runMode == RunMode.JarWar) {
return StrUtil.endWith(file.getName(), "war", true);
}
return false;
})
.collect(Collectors.toList());
}
/**
* 拼接java 执行的jar路径
*
* @param nodeProjectInfoModel 项目
* @return classpath 或者 jar
*/
protected String getClassPathLib(NodeProjectInfoModel nodeProjectInfoModel, String lib) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
List<File> files = this.listJars(runMode, lib);
if (CollUtil.isEmpty(files)) {
return "";
}
// 获取lib下面的所有jar包
StringBuilder classPath = new StringBuilder();
int len = files.size();
if (runMode == RunMode.ClassPath) {
classPath.append("-classpath ");
} else if (runMode == RunMode.Jar || runMode == RunMode.JarWar) {
classPath.append("-jar ");
// 只取一个jar文件
len = 1;
} else if (runMode == RunMode.JavaExtDirsCp) {
classPath.append("-Djava.ext.dirs=");
String javaExtDirsCp = nodeProjectInfoModel.javaExtDirsCp();
String[] split = StrUtil.splitToArray(javaExtDirsCp, StrUtil.COLON);
if (ArrayUtil.isEmpty(split)) {
classPath.append(". -cp ");
} else {
classPath.append(split[0]).append(" -cp ");
if (split.length > 1) {
classPath.append(split[1]).append(FileUtil.PATH_SEPARATOR);
}
}
} else {
return StrUtil.EMPTY;
}
for (int i = 0; i < len; i++) {
File file = files.get(i);
classPath.append(file.getAbsolutePath());
if (i != len - 1) {
classPath.append(FileUtil.PATH_SEPARATOR);
}
}
return classPath.toString();
}
}

View File

@ -22,7 +22,6 @@
*/
package org.dromara.jpom.common.commander;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.StrUtil;
import lombok.Lombok;
@ -59,29 +58,38 @@ public abstract class BaseUnixProjectCommander extends AbstractProjectCommander
@Override
public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel) {
String path = NodeProjectInfoModel.getClassPathLib(nodeProjectInfoModel);
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
return this.buildRunCommand(nodeProjectInfoModel, infoModel);
}
@Override
public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
String lib = projectInfoService.resolveLibPath(originalModel);
String path = this.getClassPathLib(originalModel, lib);
if (StrUtil.isBlank(path)) {
return null;
}
String tag = nodeProjectInfoModel.getId();
String absoluteLog = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
return StrUtil.format("nohup {} {} {} {} {} {} >> {} 2>&1 &",
getRunJavaPath(nodeProjectInfoModel, false),
Optional.ofNullable(nodeProjectInfoModel.getJvm()).orElse(StrUtil.EMPTY),
JvmUtil.getJpomPidTag(tag, nodeProjectInfoModel.allLib()),
JvmUtil.getJpomPidTag(tag, lib),
path,
Optional.ofNullable(nodeProjectInfoModel.mainClass()).orElse(StrUtil.EMPTY),
Optional.ofNullable(originalModel.mainClass()).orElse(StrUtil.EMPTY),
Optional.ofNullable(nodeProjectInfoModel.getArgs()).orElse(StrUtil.EMPTY),
nodeProjectInfoModel.absoluteLog());
absoluteLog);
}
@Override
public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, int pid) {
File file = FileUtil.file(nodeProjectInfoModel.allLib());
public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int pid) {
File file = projectInfoService.resolveLibFile(originalModel);
List<String> result = new ArrayList<>();
boolean success = false;
String kill = systemCommander.kill(file, pid);
result.add(kill);
if (this.loopCheckRun(nodeProjectInfoModel, false)) {
if (this.loopCheckRun(nodeProjectInfoModel, originalModel, false)) {
success = true;
} else {
// 强制杀进程
@ -93,7 +101,7 @@ public abstract class BaseUnixProjectCommander extends AbstractProjectCommander
throw Lombok.sneakyThrow(e);
}
//
if (this.loopCheckRun(nodeProjectInfoModel, 5, false)) {
if (this.loopCheckRun(nodeProjectInfoModel, originalModel, 5, false)) {
success = true;
} else {
result.add("Kill -9 not completed, kill -9 failed ");

View File

@ -30,6 +30,7 @@ import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* 命令操作执行结果
@ -116,7 +117,7 @@ public class CommandOpResult {
public static CommandOpResult of(boolean success, List<String> msg) {
CommandOpResult commandOpResult = new CommandOpResult();
commandOpResult.success = success;
commandOpResult.msgs.addAll(msg);
Optional.ofNullable(msg).ifPresent(commandOpResult.msgs::addAll);
return commandOpResult;
}

View File

@ -22,16 +22,15 @@
*/
package org.dromara.jpom.common.commander.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.StrUtil;
import org.dromara.jpom.common.commander.AbstractProjectCommander;
import org.dromara.jpom.common.commander.CommandOpResult;
import org.dromara.jpom.common.commander.Commander;
import org.dromara.jpom.common.commander.SystemCommander;
import org.dromara.jpom.configuration.AgentConfig;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.model.system.NetstatModel;
import org.dromara.jpom.configuration.AgentConfig;
import org.dromara.jpom.service.manage.ProjectInfoService;
import org.dromara.jpom.service.script.DslScriptServer;
import org.dromara.jpom.util.CommandUtil;
@ -39,6 +38,7 @@ import org.dromara.jpom.util.JvmUtil;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@ -61,34 +61,44 @@ public class WindowsProjectCommander extends AbstractProjectCommander {
@Override
public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel) {
String classPath = NodeProjectInfoModel.getClassPathLib(nodeProjectInfoModel);
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
return this.buildRunCommand(nodeProjectInfoModel, infoModel);
}
@Override
public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
String lib = projectInfoService.resolveLibPath(originalModel);
String classPath = this.getClassPathLib(originalModel, lib);
if (StrUtil.isBlank(classPath)) {
return null;
}
// 拼接命令
String jvm = nodeProjectInfoModel.getJvm();
String tag = nodeProjectInfoModel.getId();
String mainClass = nodeProjectInfoModel.mainClass();
String mainClass = originalModel.mainClass();
String args = nodeProjectInfoModel.getArgs();
String absoluteLog = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
return StrUtil.format("{} {} {} {} {} {} >> {} &",
getRunJavaPath(nodeProjectInfoModel, true),
Optional.ofNullable(jvm).orElse(StrUtil.EMPTY),
JvmUtil.getJpomPidTag(tag, nodeProjectInfoModel.allLib()),
JvmUtil.getJpomPidTag(tag, lib),
classPath,
Optional.ofNullable(mainClass).orElse(StrUtil.EMPTY),
Optional.ofNullable(args).orElse(StrUtil.EMPTY),
nodeProjectInfoModel.absoluteLog());
absoluteLog);
}
@Override
public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, int pid) {
public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int pid) {
String tag = nodeProjectInfoModel.getId();
List<String> result = new ArrayList<>();
boolean success = false;
// 如果正在运行则执行杀进程命令
String kill = systemCommander.kill(FileUtil.file(nodeProjectInfoModel.allLib()), pid);
File file = projectInfoService.resolveLibFile(nodeProjectInfoModel);
String kill = systemCommander.kill(file, pid);
result.add(kill);
if (this.loopCheckRun(nodeProjectInfoModel, false)) {
if (this.loopCheckRun(nodeProjectInfoModel, originalModel, false)) {
success = true;
} else {
result.add("Kill not completed");

View File

@ -26,7 +26,6 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.RegexPool;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import cn.keepbx.jpom.IJsonMessage;
import cn.keepbx.jpom.model.JsonMessage;
@ -73,62 +72,67 @@ public class ManageEditProjectController extends BaseAgentController {
/**
* 基础检查
*
* @param projectInfo 项目实体
* @param whitelistDirectory 授权
* @param previewData 预检查数据
* @param projectInfo 项目实体
* @param previewData 预检查数据
*/
private NodeProjectInfoModel checkParameter(NodeProjectInfoModel projectInfo,
String whitelistDirectory,
boolean previewData) {
private void checkParameter(NodeProjectInfoModel projectInfo, boolean previewData) {
String id = projectInfo.getId();
// 兼容 _
String checkId = StrUtil.replace(id, StrUtil.DASHED, StrUtil.UNDERLINE);
Validator.validateGeneral(checkId, 2, Const.ID_MAX_LEN, "项目id 长度范围2-20英文字母 、数字和下划线)");
Assert.state(!Const.SYSTEM_ID.equals(id), "项目id " + Const.SYSTEM_ID + " 关键词被系统占用");
// 运行模式
String runModeStr = getParameter("runMode");
RunMode runMode1 = EnumUtil.fromString(RunMode.class, runModeStr, RunMode.ClassPath);
projectInfo.setRunMode(runMode1);
RunMode runMode = projectInfo.getRunMode();
Assert.notNull(runMode, "请选择运行模式");
// 监测
if (runMode1 == RunMode.ClassPath || runMode1 == RunMode.JavaExtDirsCp) {
if (runMode == RunMode.ClassPath || runMode == RunMode.JavaExtDirsCp) {
Assert.hasText(projectInfo.mainClass(), "ClassPath、JavaExtDirsCp 模式 MainClass必填");
} else if (runMode1 == RunMode.Jar || runMode1 == RunMode.JarWar) {
if (runMode == RunMode.JavaExtDirsCp) {
Assert.hasText(projectInfo.javaExtDirsCp(), "JavaExtDirsCp 模式 javaExtDirsCp必填");
}
} else if (runMode == RunMode.Jar || runMode == RunMode.JarWar) {
projectInfo.setMainClass(StrUtil.EMPTY);
}
if (runMode1 == RunMode.JavaExtDirsCp) {
Assert.hasText(projectInfo.javaExtDirsCp(), "JavaExtDirsCp 模式 javaExtDirsCp必填");
} else if (runMode == RunMode.Link) {
String linkId = projectInfo.getLinkId();
Assert.hasText(linkId, "Link 模式 LinkId必填");
NodeProjectInfoModel item = projectInfoService.getItem(linkId);
Assert.notNull(item, "软链的项目部存在");
RunMode itemRunMode = item.getRunMode();
Assert.state(itemRunMode != RunMode.File && itemRunMode != RunMode.Link, "被软链的项目不能是File或Link模式");
}
// 判断是否为分发添加
String strOutGivingProject = getParameter("outGivingProject");
boolean outGivingProject = Boolean.parseBoolean(strOutGivingProject);
projectInfo.setOutGivingProject(outGivingProject);
if (!previewData) {
// 不是预检查数据才效验授权
if (!whitelistDirectoryService.checkProjectDirectory(whitelistDirectory)) {
if (outGivingProject) {
whitelistDirectoryService.addProjectWhiteList(whitelistDirectory);
} else {
throw new IllegalArgumentException("请选择正确的项目路径,或者还没有配置授权");
}
}
String logPath = projectInfo.log();
if (StrUtil.isNotEmpty(logPath)) {
if (!whitelistDirectoryService.checkProjectDirectory(logPath)) {
if (runMode != RunMode.Link) {
if (!previewData) {
String whitelistDirectory = projectInfo.whitelistDirectory();
// 不是预检查数据才效验授权
if (!whitelistDirectoryService.checkProjectDirectory(whitelistDirectory)) {
if (outGivingProject) {
whitelistDirectoryService.addProjectWhiteList(logPath);
whitelistDirectoryService.addProjectWhiteList(whitelistDirectory);
} else {
throw new IllegalArgumentException("请填写的项目日志存储路径,或者还没有配置授权");
throw new IllegalArgumentException("请选择正确的项目路径,或者还没有配置授权");
}
}
String logPath = projectInfo.logPath();
if (StrUtil.isNotEmpty(logPath)) {
if (!whitelistDirectoryService.checkProjectDirectory(logPath)) {
if (outGivingProject) {
whitelistDirectoryService.addProjectWhiteList(logPath);
} else {
throw new IllegalArgumentException("请填写的项目日志存储路径,或者还没有配置授权");
}
}
}
}
}
//
String lib = projectInfo.getLib();
Assert.state(StrUtil.isNotEmpty(lib) && !StrUtil.SLASH.equals(lib) && !Validator.isChinese(lib), "项目路径不能为空,不能为顶级目录,不能包含中文");
//
String lib = projectInfo.getLib();
Assert.state(StrUtil.isNotEmpty(lib) && !StrUtil.SLASH.equals(lib) && !Validator.isChinese(lib), "项目路径不能为空,不能为顶级目录,不能包含中文");
FileUtils.checkSlip(lib, e -> new IllegalArgumentException("项目路径存在提升目录问题"));
return projectInfoService.getItem(projectInfo.getId());
FileUtils.checkSlip(lib, e -> new IllegalArgumentException("项目路径存在提升目录问题"));
}
}
@ -137,28 +141,12 @@ public class ManageEditProjectController extends BaseAgentController {
// 预检查数据
String strPreviewData = getParameter("previewData");
boolean previewData = Convert.toBool(strPreviewData, false);
String whitelistDirectory = projectInfo.whitelistDirectory();
//
NodeProjectInfoModel exits = this.checkParameter(projectInfo, whitelistDirectory, previewData);
String id = projectInfo.getId();
//
String allLib = projectInfo.allLib();
// 判断空格
Assert.state(!id.contains(StrUtil.SPACE) && !allLib.contains(StrUtil.SPACE), "项目Id、项目路径不能包含空格");
File checkFile = FileUtil.file(allLib);
Assert.state(!FileUtil.exist(checkFile) || FileUtil.isDirectory(checkFile), "项目路径是一个已经存在的文件");
// 重复lib
List<NodeProjectInfoModel> list = projectInfoService.list();
if (list != null) {
for (NodeProjectInfoModel nodeProjectInfoModel : list) {
File fileLib = FileUtil.file(nodeProjectInfoModel.allLib());
if (!nodeProjectInfoModel.getId().equals(id) && FileUtil.equals(fileLib, checkFile)) {
return new JsonMessage<>(401, "当前项目路径已经被【" + nodeProjectInfoModel.getName() + "】占用,请检查");
}
}
}
this.checkParameter(projectInfo, previewData);
// 自动生成log文件
checkFile = projectInfo.absoluteLogFile();
File checkFile = this.projectInfoService.resolveAbsoluteLogFile(projectInfo);
Assert.state(!FileUtil.exist(checkFile) || FileUtil.isFile(checkFile), "项目log是一个已经存在的文件夹");
//
String token = projectInfo.token();
@ -168,7 +156,7 @@ public class ManageEditProjectController extends BaseAgentController {
// 判断 yml
this.checkDslYml(projectInfo);
//
return save(projectInfo, exits, previewData);
return this.save(projectInfo, previewData);
}
private void checkDslYml(NodeProjectInfoModel projectInfo) {
@ -187,10 +175,11 @@ public class ManageEditProjectController extends BaseAgentController {
* @param previewData 是否是预检查
* @return 错误信息
*/
private IJsonMessage<String> save(NodeProjectInfoModel projectInfo, NodeProjectInfoModel exits, boolean previewData) {
projectInfo.setWorkspaceId(getWorkspaceId());
private IJsonMessage<String> save(NodeProjectInfoModel projectInfo, boolean previewData) {
this.checkPath(projectInfo);
//
NodeProjectInfoModel exits = projectInfoService.getItem(projectInfo.getId());
projectInfo.setWorkspaceId(this.getWorkspaceId());
RunMode runMode = projectInfo.getRunMode();
if (exits == null) {
// 检查运行中的tag 是否被占用
@ -221,17 +210,21 @@ public class ManageEditProjectController extends BaseAgentController {
exits.setToken(projectInfo.token());
exits.setDslContent(projectInfo.getDslContent());
exits.setDslEnv(projectInfo.getDslEnv());
exits.setJavaExtDirsCp(projectInfo.javaExtDirsCp());
// 移动到新路径
this.moveTo(exits, projectInfo);
// 最后才设置新的路径
exits.setLib(projectInfo.getLib());
exits.setWhitelistDirectory(projectInfo.whitelistDirectory());
//
exits.setLog(projectInfo.log());
exits.setLogPath(projectInfo.logPath());
projectInfoService.updateItem(exits);
if (runMode == RunMode.Link) {
// 如果是链接模式
Assert.state(runMode == exits.getRunMode(), "已经存在的项目不能修改为软链项目");
} else {
// 移动到新路径
this.moveTo(exits, projectInfo);
// 最后才设置新的路径
exits.setLib(projectInfo.getLib());
exits.setWhitelistDirectory(projectInfo.whitelistDirectory());
//
//exits.setLog(projectInfo.log());
exits.setLogPath(projectInfo.logPath());
}
projectInfoService.updateById(exits, exits.getId());
return JsonMessage.success("修改成功");
}
}
@ -239,8 +232,8 @@ public class ManageEditProjectController extends BaseAgentController {
private void moveTo(NodeProjectInfoModel old, NodeProjectInfoModel news) {
{
// 移动目录
File oldLib = FileUtil.file(old.allLib());
File newLib = FileUtil.file(news.allLib());
File oldLib = projectInfoService.resolveLibFile(old);
File newLib = projectInfoService.resolveLibFile(news);
if (!FileUtil.equals(oldLib, newLib)) {
// 正在运行的项目不能修改路径
this.projectMustNotRun(old, "正在运行的项目不能修改路径");
@ -251,8 +244,8 @@ public class ManageEditProjectController extends BaseAgentController {
}
{
// log
File oldLog = old.absoluteLogFile();
File newLog = news.absoluteLogFile();
File oldLog = projectInfoService.resolveAbsoluteLogFile(old);
File newLog = projectInfoService.resolveAbsoluteLogFile(news);
if (!FileUtil.equals(oldLog, newLog)) {
// 正在运行的项目不能修改路径
this.projectMustNotRun(old, "正在运行的项目不能修改路径");
@ -261,9 +254,9 @@ public class ManageEditProjectController extends BaseAgentController {
FileUtil.move(oldLog, newLog, true);
}
// logBack
File oldLogBack = old.logBack();
File oldLogBack = projectInfoService.resolveLogBack(old);
if (oldLogBack.exists()) {
File logBack = news.logBack();
File logBack = projectInfoService.resolveLogBack(news);
FileUtils.tempMoveContent(oldLogBack, logBack);
}
}
@ -281,15 +274,41 @@ public class ManageEditProjectController extends BaseAgentController {
* @param nodeProjectInfoModel 比较的项目
*/
private void checkPath(NodeProjectInfoModel nodeProjectInfoModel) {
List<NodeProjectInfoModel> nodeProjectInfoModelList = projectInfoService.list();
if (nodeProjectInfoModelList == null) {
String id = nodeProjectInfoModel.getId();
Assert.state(!id.contains(StrUtil.SPACE), "项目Id不能包含空格");
RunMode runMode = nodeProjectInfoModel.getRunMode();
if (runMode == RunMode.Link) {
return;
}
List<NodeProjectInfoModel> list = projectInfoService.list();
if (list == null) {
return;
}
//
String allLib = nodeProjectInfoModel.allLib();
// 判断空格
Assert.state(!allLib.contains(StrUtil.SPACE), "项目路径不能包含空格");
File checkFile = FileUtil.file(allLib);
Assert.state(!FileUtil.exist(checkFile) || FileUtil.isDirectory(checkFile), "项目路径是一个已经存在的文件");
// 重复lib
for (NodeProjectInfoModel item : list) {
if (item.getRunMode() == RunMode.Link) {
continue;
}
File fileLib = projectInfoService.resolveLibFile(item);
if (!nodeProjectInfoModel.getId().equals(id) && FileUtil.equals(fileLib, checkFile)) {
throw new IllegalArgumentException("当前项目路径已经被【" + item.getName() + "】占用,请检查");
}
}
NodeProjectInfoModel nodeProjectInfoModel1 = null;
for (NodeProjectInfoModel model : nodeProjectInfoModelList) {
for (NodeProjectInfoModel model : list) {
if (model.getRunMode() == RunMode.Link) {
continue;
}
if (!model.getId().equals(nodeProjectInfoModel.getId())) {
File file1 = new File(model.allLib());
File file2 = new File(nodeProjectInfoModel.allLib());
File file1 = projectInfoService.resolveLibFile(model);
File file2 = projectInfoService.resolveLibFile(nodeProjectInfoModel);
if (FileUtil.pathEquals(file1, file2)) {
nodeProjectInfoModel1 = model;
break;
@ -312,7 +331,7 @@ public class ManageEditProjectController extends BaseAgentController {
* @return json
*/
@RequestMapping(value = "deleteProject", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<String> deleteProject(String thorough) {
public IJsonMessage<String> deleteProject(String id, String thorough) {
NodeProjectInfoModel nodeProjectInfoModel = tryGetProjectInfoModel();
if (nodeProjectInfoModel == null) {
// 返回正常 200 状态码考虑节点分发重复操作
@ -321,6 +340,14 @@ public class ManageEditProjectController extends BaseAgentController {
// 运行判断
boolean run = projectCommander.isRun(nodeProjectInfoModel);
Assert.state(!run, "不能删除正在运行的项目");
// 判断是否被软链
List<NodeProjectInfoModel> list = projectInfoService.list();
for (NodeProjectInfoModel projectInfoModel : list) {
if (nodeProjectInfoModel.getRunMode() != RunMode.Link) {
continue;
}
Assert.state(!StrUtil.equals(projectInfoModel.getLinkId(), id), "项目被" + projectInfoModel.getName() + "软链中");
}
this.thorough(thorough, nodeProjectInfoModel);
//
projectInfoService.deleteItem(nodeProjectInfoModel.getId());
@ -339,24 +366,28 @@ public class ManageEditProjectController extends BaseAgentController {
if (StrUtil.isEmpty(thorough)) {
return;
}
File logBack = nodeProjectInfoModel.logBack();
File logBack = this.projectInfoService.resolveLogBack(nodeProjectInfoModel);
boolean fastDel = CommandUtil.systemFastDel(logBack);
Assert.state(!fastDel, "删除日志文件失败:" + logBack.getAbsolutePath());
File log = nodeProjectInfoModel.absoluteLogFile();
File log = this.projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel);
fastDel = CommandUtil.systemFastDel(log);
Assert.state(!fastDel, "删除日志文件失败:" + log.getAbsolutePath());
//
File allLib = FileUtil.file(nodeProjectInfoModel.allLib());
fastDel = CommandUtil.systemFastDel(allLib);
Assert.state(!fastDel, "删除项目文件失败:" + allLib.getAbsolutePath());
if (nodeProjectInfoModel.getRunMode() != RunMode.Link) {
// 非软链项目才删除文件
File allLib = projectInfoService.resolveLibFile(nodeProjectInfoModel);
fastDel = CommandUtil.systemFastDel(allLib);
Assert.state(!fastDel, "删除项目文件失败:" + allLib.getAbsolutePath());
}
}
@RequestMapping(value = "releaseOutGiving", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<Object> releaseOutGiving() {
NodeProjectInfoModel nodeProjectInfoModel = tryGetProjectInfoModel();
if (nodeProjectInfoModel != null) {
nodeProjectInfoModel.setOutGivingProject(false);
projectInfoService.updateItem(nodeProjectInfoModel);
NodeProjectInfoModel update = new NodeProjectInfoModel();
update.setOutGivingProject(false);
projectInfoService.updateById(update, nodeProjectInfoModel.getId());
}
return JsonMessage.success("释放成功");
}
@ -367,9 +398,10 @@ public class ManageEditProjectController extends BaseAgentController {
Assert.hasText(newWorkspaceId, "请选择要修改的节");
NodeProjectInfoModel nodeProjectInfoModel = tryGetProjectInfoModel();
if (nodeProjectInfoModel != null) {
nodeProjectInfoModel.setNodeId(newNodeId);
nodeProjectInfoModel.setWorkspaceId(newWorkspaceId);
projectInfoService.updateItem(nodeProjectInfoModel);
NodeProjectInfoModel update = new NodeProjectInfoModel();
update.setNodeId(newNodeId);
update.setWorkspaceId(newWorkspaceId);
projectInfoService.updateById(update, nodeProjectInfoModel.getId());
}
return JsonMessage.success("修改成功");
}

View File

@ -178,7 +178,7 @@ public class ProjectFileBackupController extends BaseAgentController {
public IJsonMessage<Object> recoverFile(String id, @ValidatorItem String backupId, String type, String filename, String levelName) {
NodeProjectInfoModel projectInfoModel = super.getProjectInfoModel();
File backupPath = projectFileBackupService.pathProjectBackup(projectInfoModel, backupId);
String projectPath = projectInfoModel.allLib();
File projectPath = projectInfoService.resolveLibFile(projectInfoModel);
//
File backupFile;
File projectFile;

View File

@ -95,9 +95,8 @@ public class ProjectFileControl extends BaseAgentController {
@RequestMapping(value = "getFileList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<List<JSONObject>> getFileList(String id, String path) {
// 查询项目路径
NodeProjectInfoModel pim = projectInfoService.getItem(id);
Assert.notNull(pim, "查询失败:项目不存在");
String lib = pim.allLib();
NodeProjectInfoModel pim = getProjectInfoModel();
String lib = projectInfoService.resolveLibPath(pim);
File fileDir = FileUtil.file(lib, StrUtil.emptyToDefault(path, FileUtil.FILE_SEPARATOR));
boolean exist = FileUtil.exist(fileDir);
if (!exist) {
@ -131,7 +130,8 @@ public class ProjectFileControl extends BaseAgentController {
List<DiffFileVo.DiffItem> data = diffFileVo.getData();
Assert.notEmpty(data, "没有要对比的数据");
// 扫描项目目录下面的所有文件
String path = FileUtil.file(projectInfoModel.allLib(), Opt.ofBlankAble(diffFileVo.getDir()).orElse(StrUtil.SLASH)).getAbsolutePath();
File lib = projectInfoService.resolveLibFile(projectInfoModel);
String path = FileUtil.file(lib, Opt.ofBlankAble(diffFileVo.getDir()).orElse(StrUtil.SLASH)).getAbsolutePath();
List<File> files = FileUtil.loopFiles(path);
// 将所有的文件信息组装并签名
List<JSONObject> collect = files.stream().map(file -> {
@ -241,7 +241,8 @@ public class ProjectFileControl extends BaseAgentController {
*/
private IJsonMessage<CommandOpResult> upload(File file, String type, String levelName, Integer stripComponents, String after) throws Exception {
NodeProjectInfoModel pim = getProjectInfoModel();
File lib = StrUtil.isEmpty(levelName) ? new File(pim.allLib()) : FileUtil.file(pim.allLib(), levelName);
File libFile = projectInfoService.resolveLibFile(pim);
File lib = StrUtil.isEmpty(levelName) ? libFile : FileUtil.file(libFile, levelName);
// 备份文件
String backupId = projectFileBackupService.backup(pim);
try {
@ -295,7 +296,8 @@ public class ProjectFileControl extends BaseAgentController {
@RequestMapping(value = "deleteFile", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<String> deleteFile(String filename, String type, String levelName) {
NodeProjectInfoModel pim = getProjectInfoModel();
File file = FileUtil.file(pim.allLib(), StrUtil.emptyToDefault(levelName, StrUtil.SLASH));
File libFile = projectInfoService.resolveLibFile(pim);
File file = FileUtil.file(libFile, StrUtil.emptyToDefault(levelName, StrUtil.SLASH));
// 备份文件
String backupId = projectFileBackupService.backup(pim);
try {
@ -335,8 +337,9 @@ public class ProjectFileControl extends BaseAgentController {
//
List<DiffFileVo.DiffItem> data = diffFileVo.getData();
Assert.notEmpty(data, "没有要对比的数据");
File libFile = projectInfoService.resolveLibFile(projectInfoModel);
//
File path = FileUtil.file(projectInfoModel.allLib(), Opt.ofBlankAble(dir).orElse(StrUtil.SLASH));
File path = FileUtil.file(libFile, Opt.ofBlankAble(dir).orElse(StrUtil.SLASH));
for (DiffFileVo.DiffItem datum : data) {
File file = FileUtil.file(path, datum.getName());
if (FileUtil.del(file)) {
@ -366,7 +369,8 @@ public class ProjectFileControl extends BaseAgentController {
// 判断文件后缀
AgentWhitelist whitelist = whitelistDirectoryService.getWhitelist();
Charset charset = AgentWhitelist.checkFileSuffix(whitelist.getAllowEditSuffix(), filename);
File file = FileUtil.file(pim.allLib(), filePath, filename);
File libFile = projectInfoService.resolveLibFile(pim);
File file = FileUtil.file(libFile, filePath, filename);
String ymlString = FileUtil.readString(file, charset);
return JsonMessage.success("", ymlString);
}
@ -388,8 +392,9 @@ public class ProjectFileControl extends BaseAgentController {
Charset charset = AgentWhitelist.checkFileSuffix(whitelist.getAllowEditSuffix(), filename);
// 备份文件
String backupId = projectFileBackupService.backup(pim);
File libFile = projectInfoService.resolveLibFile(pim);
try {
FileUtil.writeString(fileText, FileUtil.file(pim.allLib(), filePath, filename), charset);
FileUtil.writeString(fileText, FileUtil.file(libFile, filePath, filename), charset);
projectCommander.asyncWebHooks(pim, "fileChange", "changeEvent", "edit", "levelName", filePath, "fileName", filename);
return JsonMessage.success("文件写入成功");
} finally {
@ -412,9 +417,10 @@ public class ProjectFileControl extends BaseAgentController {
// if (StrUtil.isEmpty(safeFileName)) {
// return JsonMessage.getString(405, "非法操作");
// }
NodeProjectInfoModel pim = getProjectInfoModel();
File libFile = projectInfoService.resolveLibFile(pim);
try {
NodeProjectInfoModel pim = projectInfoService.getItem(id);
File file = FileUtil.file(pim.allLib(), StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), filename);
File file = FileUtil.file(libFile, StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), filename);
if (file.isDirectory()) {
ServletUtil.write(response, JsonMessage.getString(400, "暂不支持下载文件夹"), MediaType.APPLICATION_JSON_VALUE);
return;
@ -439,9 +445,8 @@ public class ProjectFileControl extends BaseAgentController {
@PostMapping(value = "remote_download", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<String> remoteDownload(String id, String url, String levelName, String unzip, Integer stripComponents) {
Assert.hasText(url, "请输入正确的远程地址");
NodeProjectInfoModel pim = projectInfoService.getItem(id);
NodeProjectInfoModel pim = getProjectInfoModel();
File libFile = projectInfoService.resolveLibFile(pim);
String tempPathName = agentConfig.getTempPathName();
//
String backupId = null;
@ -450,7 +455,7 @@ public class ProjectFileControl extends BaseAgentController {
String fileSize = FileUtil.readableFileSize(downloadFile);
// 备份文件
backupId = projectFileBackupService.backup(pim);
File file = FileUtil.file(pim.allLib(), StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR));
File file = FileUtil.file(libFile, StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR));
FileUtil.mkdir(file);
if (BooleanUtil.toBoolean(unzip)) {
// 需要解压文件
@ -487,9 +492,9 @@ public class ProjectFileControl extends BaseAgentController {
*/
@PostMapping(value = "new_file_folder.json", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<Object> newFileFolder(String id, String levelName, @ValidatorItem String filename, String unFolder) {
NodeProjectInfoModel projectInfoModel = projectInfoService.getItem(id);
Assert.notNull(projectInfoModel, "没有对应到项目");
File file = FileUtil.file(projectInfoModel.allLib(), StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), filename);
NodeProjectInfoModel projectInfoModel = getProjectInfoModel();
File libFile = projectInfoService.resolveLibFile(projectInfoModel);
File file = FileUtil.file(libFile, StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), filename);
//
Assert.state(!FileUtil.exist(file), "文件夹或者文件已存在");
boolean folder = !Convert.toBool(unFolder, false);
@ -514,8 +519,9 @@ public class ProjectFileControl extends BaseAgentController {
@PostMapping(value = "rename.json", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<Object> rename(String id, String levelName, @ValidatorItem String filename, String newname) {
NodeProjectInfoModel projectInfoModel = getProjectInfoModel();
File file = FileUtil.file(projectInfoModel.allLib(), StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), filename);
File newFile = FileUtil.file(projectInfoModel.allLib(), StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), newname);
File libFile = projectInfoService.resolveLibFile(projectInfoModel);
File file = FileUtil.file(libFile, StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), filename);
File newFile = FileUtil.file(libFile, StrUtil.emptyToDefault(levelName, FileUtil.FILE_SEPARATOR), newname);
Assert.state(FileUtil.exist(file), "文件不存在");
Assert.state(!FileUtil.exist(newFile), "文件名已经存在拉");

View File

@ -64,7 +64,7 @@ public class ProjectLogBackController extends BaseAgentController {
JSONObject jsonObject = new JSONObject();
//
//获取日志备份路径
File logBack = nodeProjectInfoModel.logBack();
File logBack = projectInfoService.resolveLogBack(nodeProjectInfoModel);
boolean logBackBool = logBack.exists() && logBack.isDirectory();
jsonObject.put("logBack", logBackBool);
String info = this.getLogSize(nodeProjectInfoModel);
@ -82,7 +82,7 @@ public class ProjectLogBackController extends BaseAgentController {
if (nodeProjectInfoModel == null) {
return null;
}
File file = nodeProjectInfoModel.absoluteLogFile();
File file = projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel);
if (file.exists()) {
long fileSize = file.length();
if (fileSize <= 0) {
@ -112,7 +112,7 @@ public class ProjectLogBackController extends BaseAgentController {
public IJsonMessage<String> clear(String name) {
Assert.hasText(name, "没有对应到文件");
NodeProjectInfoModel pim = getProjectInfoModel();
File logBack = pim.logBack();
File logBack = projectInfoService.resolveLogBack(pim);
if (logBack.exists() && logBack.isDirectory()) {
logBack = FileUtil.file(logBack, name);
if (logBack.exists()) {
@ -130,7 +130,7 @@ public class ProjectLogBackController extends BaseAgentController {
Assert.hasText(key, "请选择对应到文件");
try {
NodeProjectInfoModel pim = getProjectInfoModel();
File logBack = pim.logBack();
File logBack = projectInfoService.resolveLogBack(pim);
if (logBack.exists() && logBack.isDirectory()) {
logBack = FileUtil.file(logBack, key);
ServletUtil.write(response, logBack);
@ -149,8 +149,8 @@ public class ProjectLogBackController extends BaseAgentController {
NodeProjectInfoModel pim = getProjectInfoModel();
JSONObject jsonObject = new JSONObject();
File logBack = pim.logBack();
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(pim);
File logBack = projectInfoService.resolveLogBack(pim, infoModel);
if (logBack.exists() && logBack.isDirectory()) {
File[] filesAll = logBack.listFiles();
if (filesAll != null) {
@ -159,17 +159,17 @@ public class ProjectLogBackController extends BaseAgentController {
}
}
jsonObject.put("id", pim.getId());
jsonObject.put("logPath", pim.log());
jsonObject.put("logPath", projectInfoService.resolveAbsoluteLog(pim, infoModel));
jsonObject.put("logBackPath", logBack.getAbsolutePath());
return JsonMessage.success("", jsonObject);
}
@RequestMapping(value = "export.html", method = RequestMethod.GET)
@RequestMapping(value = "export", method = RequestMethod.GET)
@ResponseBody
public void export(HttpServletResponse response) {
NodeProjectInfoModel pim = getProjectInfoModel();
File file = pim.absoluteLogFile();
File file = projectInfoService.resolveAbsoluteLogFile(pim);
if (!file.exists()) {
ServletUtil.write(response, JsonMessage.getString(400, "没有日志文件:" + file.getPath()), MediaType.APPLICATION_JSON_VALUE);
return;

View File

@ -22,9 +22,7 @@
*/
package org.dromara.jpom.model.data;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
@ -35,12 +33,8 @@ import org.dromara.jpom.model.RunMode;
import org.dromara.jpom.system.JpomRuntimeException;
import org.springframework.util.Assert;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 项目配置信息实体
@ -54,18 +48,22 @@ public class NodeProjectInfoModel extends BaseWorkspaceModel {
* 分组
*/
private String group;
private String mainClass;
/**
* 项目路径
*/
private String lib;
/**
* 授权目录
*/
private String whitelistDirectory;
private String log;
/**
* 日志目录
*/
private String logPath;
/**
* java 模式运行的 class
*/
private String mainClass;
/**
* jvm 参数
*/
@ -78,20 +76,23 @@ public class NodeProjectInfoModel extends BaseWorkspaceModel {
* WebHooks
*/
private String token;
/**
* 项目运行模式
*/
private RunMode runMode;
/**
* 软链的父级项目id
*/
private String linkId;
/**
* 节点分发项目不允许在项目管理中编辑
*/
private Boolean outGivingProject;
/**
* -Djava.ext.dirs=lib -cp conf:run.jar
* 填写lib:conf
*/
private String javaExtDirsCp;
/**
* 项目自动启动
*/
@ -134,7 +135,6 @@ public class NodeProjectInfoModel extends BaseWorkspaceModel {
return outGivingProject != null && outGivingProject;
}
public String mainClass() {
return StrUtil.emptyToDefault(mainClass, StrUtil.EMPTY);
}
@ -151,120 +151,10 @@ public class NodeProjectInfoModel extends BaseWorkspaceModel {
return FileUtil.file(directory, this.getLib()).getAbsolutePath();
}
/**
* 获取项目文件中的所有jar 文件
*
* @param nodeProjectInfoModel 项目
* @return list
*/
public static List<File> listJars(NodeProjectInfoModel nodeProjectInfoModel) {
File fileLib = new File(nodeProjectInfoModel.allLib());
File[] files = fileLib.listFiles();
if (files == null) {
return new ArrayList<>();
}
RunMode runMode = nodeProjectInfoModel.getRunMode();
return Arrays.stream(files)
.filter(File::isFile)
.filter(file -> {
if (runMode == RunMode.ClassPath || runMode == RunMode.Jar || runMode == RunMode.JavaExtDirsCp) {
return StrUtil.endWith(file.getName(), FileUtil.JAR_FILE_EXT, true);
} else if (runMode == RunMode.JarWar) {
return StrUtil.endWith(file.getName(), "war", true);
}
return false;
})
.collect(Collectors.toList());
}
/**
* 拼接java 执行的jar路径
*
* @param nodeProjectInfoModel 项目
* @return classpath 或者 jar
*/
public static String getClassPathLib(NodeProjectInfoModel nodeProjectInfoModel) {
List<File> files = listJars(nodeProjectInfoModel);
if (CollUtil.isEmpty(files)) {
return "";
}
// 获取lib下面的所有jar包
StringBuilder classPath = new StringBuilder();
RunMode runMode = nodeProjectInfoModel.getRunMode();
int len = files.size();
if (runMode == RunMode.ClassPath) {
classPath.append("-classpath ");
} else if (runMode == RunMode.Jar || runMode == RunMode.JarWar) {
classPath.append("-jar ");
// 只取一个jar文件
len = 1;
} else if (runMode == RunMode.JavaExtDirsCp) {
classPath.append("-Djava.ext.dirs=");
String javaExtDirsCp = nodeProjectInfoModel.javaExtDirsCp();
String[] split = StrUtil.splitToArray(javaExtDirsCp, StrUtil.COLON);
if (ArrayUtil.isEmpty(split)) {
classPath.append(". -cp ");
} else {
classPath.append(split[0]).append(" -cp ");
if (split.length > 1) {
classPath.append(split[1]).append(FileUtil.PATH_SEPARATOR);
}
}
} else {
return StrUtil.EMPTY;
}
for (int i = 0; i < len; i++) {
File file = files.get(i);
classPath.append(file.getAbsolutePath());
if (i != len - 1) {
classPath.append(FileUtil.PATH_SEPARATOR);
}
}
return classPath.toString();
}
public String logPath() {
return StrUtil.emptyToDefault(this.logPath, StrUtil.EMPTY);
}
public String log() {
String id = this.getId();
if (StrUtil.isEmpty(id)) {
return StrUtil.EMPTY;
}
String loggedPath = this.logPath();
if (StrUtil.isNotEmpty(loggedPath)) {
return FileUtil.normalize(String.format("%s/%s/%s.log", loggedPath, id, id));
}
if (StrUtil.isEmpty(this.log)) {
String log = new File(this.allLib()).getParent();
this.log = FileUtil.normalize(String.format("%s/%s.log", log, id));
}
return StrUtil.emptyToDefault(this.log, StrUtil.EMPTY);
}
public String absoluteLog() {
File file = this.absoluteLogFile();
return FileUtil.getAbsolutePath(file);
}
public File absoluteLogFile() {
String pathname = log();
Assert.hasText(pathname, "log path error");
File file = new File(pathname);
// auto create dir
FileUtil.mkParentDirs(file);
return file;
}
public File logBack() {
String log1 = log();
Assert.hasText(log1, "log path error");
return new File(log1 + "_back");
}
/**
* 默认
*

View File

@ -24,6 +24,8 @@ package org.dromara.jpom.model.system;
import cn.hutool.core.util.StrUtil;
import cn.keepbx.jpom.model.BaseJsonModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 网络端口信息实体
@ -31,74 +33,20 @@ import cn.keepbx.jpom.model.BaseJsonModel;
* @author bwcx_jzy
* @since 2019/4/10
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class NetstatModel extends BaseJsonModel {
/**
* 协议
*/
private String protocol;
private String receive = StrUtil.DASHED;
private String send = StrUtil.DASHED;
/**
* 端口
*/
private String local;
private String foreign;
private String status;
private String name;
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getReceive() {
return receive;
}
public void setReceive(String receive) {
this.receive = receive;
}
public String getSend() {
return send;
}
public void setSend(String send) {
this.send = send;
}
public String getLocal() {
return local;
}
public void setLocal(String local) {
this.local = local;
}
public String getForeign() {
return foreign;
}
public void setForeign(String foreign) {
this.foreign = foreign;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 协议
*/
private String protocol;
private String receive = StrUtil.DASHED;
private String send = StrUtil.DASHED;
/**
* 端口
*/
private String local;
private String foreign;
private String status;
private String name;
}

View File

@ -1,144 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.dromara.jpom.service;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import org.dromara.jpom.JpomApplication;
import org.dromara.jpom.model.BaseModel;
import org.dromara.jpom.system.JpomRuntimeException;
import org.dromara.jpom.util.JsonFileUtil;
import java.io.FileNotFoundException;
/**
* 公共文件操作Service
*
* @author bwcx_jzy
* @since 2019/1/16
*/
public abstract class BaseDataService {
/**
* 获取数据文件的路径如果文件不存在则创建一个
*
* @param filename 文件名
* @return path
*/
protected String getDataFilePath(String filename) {
return FileUtil.normalize(JpomApplication.getInstance().getDataPath() + StrUtil.SLASH + filename);
}
/**
* 保存json对象
*
* @param filename 文件名
* @param json json数据
*/
protected void saveJson(String filename, BaseModel json) {
String key = json.getId();
// 读取文件如果存在记录则抛出异常
JSONObject allData = getJSONObject(filename);
if (allData != null) {
// 判断是否存在数据
if (allData.containsKey(key)) {
throw new JpomRuntimeException("数据Id已经存在啦" + filename + " :" + key);
}
} else {
allData = new JSONObject();
}
allData.put(key, json.toJson());
JsonFileUtil.saveJson(getDataFilePath(filename), allData);
}
/**
* 修改json对象
*
* @param filename 文件名
* @param json json数据
*/
protected void updateJson(String filename, BaseModel json) {
String key = json.getId();
// 读取文件如果不存在记录则抛出异常
JSONObject allData = getJSONObject(filename);
JSONObject data = allData.getJSONObject(key);
// 判断是否存在数据
if (MapUtil.isEmpty(data)) {
throw new JpomRuntimeException("数据不存在:" + key);
} else {
allData.put(key, json.toJson());
JsonFileUtil.saveJson(getDataFilePath(filename), allData);
}
}
/**
* 删除json对象
*
* @param filename 文件
* @param key key
*/
protected void deleteJson(String filename, String key) {
// 读取文件如果存在记录则抛出异常
JSONObject allData = getJSONObject(filename);
if (allData == null) {
return;
}
//Assert.notNull(allData, "没有任何数据");
//JSONObject data = allData.getJSONObject(key);
allData.remove(key);
JsonFileUtil.saveJson(getDataFilePath(filename), allData);
}
/**
* 读取整个json文件
*
* @param filename 文件名
* @return json
*/
protected JSONObject getJSONObject(String filename) {
try {
return (JSONObject) JsonFileUtil.readJson(getDataFilePath(filename));
} catch (FileNotFoundException e) {
return null;
}
}
protected <T> T getJsonObjectById(String file, String id, Class<T> cls) {
if (StrUtil.isEmpty(id)) {
return null;
}
JSONObject jsonObject = getJSONObject(file);
if (jsonObject == null) {
return null;
}
jsonObject = jsonObject.getJSONObject(id);
if (jsonObject == null) {
return null;
}
return jsonObject.toJavaObject(cls);
}
}

View File

@ -24,14 +24,20 @@ package org.dromara.jpom.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.lock.LockUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.dromara.jpom.JpomApplication;
import org.dromara.jpom.model.BaseModel;
import org.dromara.jpom.system.JpomRuntimeException;
import org.dromara.jpom.util.JsonFileUtil;
import org.springframework.util.Assert;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@ -43,15 +49,15 @@ import java.util.concurrent.locks.Lock;
* @author bwcx_jzy
* @since 2019/3/14
*/
public abstract class BaseOperService<T extends BaseModel> extends BaseDataService {
public abstract class BaseOperService<T extends BaseModel> {
private final String fileName;
private final Class<?> typeArgument;
private final Class<T> typeArgument;
private final Lock lock = LockUtil.createStampLock().asWriteLock();
public BaseOperService(String fileName) {
this.fileName = fileName;
this.typeArgument = ClassUtil.getTypeArgument(this.getClass());
this.typeArgument = (Class<T>) ClassUtil.getTypeArgument(this.getClass());
}
/**
@ -85,7 +91,7 @@ public abstract class BaseOperService<T extends BaseModel> extends BaseDataServi
*/
public T getItem(String id) {
Objects.requireNonNull(fileName, "没有配置fileName");
return (T) getJsonObjectById(fileName, id, typeArgument);
return getJsonObjectById(fileName, id, typeArgument);
}
@ -152,4 +158,105 @@ public abstract class BaseOperService<T extends BaseModel> extends BaseDataServi
lock.unlock();
}
}
/**
* 获取数据文件的路径如果文件不存在则创建一个
*
* @param filename 文件名
* @return path
*/
protected String getDataFilePath(String filename) {
return FileUtil.normalize(JpomApplication.getInstance().getDataPath() + StrUtil.SLASH + filename);
}
/**
* 保存json对象
*
* @param filename 文件名
* @param json json数据
*/
protected void saveJson(String filename, BaseModel json) {
String key = json.getId();
// 读取文件如果存在记录则抛出异常
JSONObject allData = getJSONObject(filename);
if (allData != null) {
// 判断是否存在数据
if (allData.containsKey(key)) {
throw new JpomRuntimeException("数据Id已经存在啦" + filename + " :" + key);
}
} else {
allData = new JSONObject();
}
allData.put(key, json.toJson());
JsonFileUtil.saveJson(getDataFilePath(filename), allData);
}
/**
* 修改json对象
*
* @param filename 文件名
* @param json json数据
*/
protected void updateJson(String filename, BaseModel json) {
String key = json.getId();
// 读取文件如果不存在记录则抛出异常
JSONObject allData = getJSONObject(filename);
JSONObject data = allData.getJSONObject(key);
// 判断是否存在数据
if (MapUtil.isEmpty(data)) {
throw new JpomRuntimeException("数据不存在:" + key);
} else {
allData.put(key, json.toJson());
JsonFileUtil.saveJson(getDataFilePath(filename), allData);
}
}
/**
* 删除json对象
*
* @param filename 文件
* @param key key
*/
protected void deleteJson(String filename, String key) {
// 读取文件如果存在记录则抛出异常
JSONObject allData = getJSONObject(filename);
if (allData == null) {
return;
}
//Assert.notNull(allData, "没有任何数据");
//JSONObject data = allData.getJSONObject(key);
allData.remove(key);
JsonFileUtil.saveJson(getDataFilePath(filename), allData);
}
/**
* 读取整个json文件
*
* @param filename 文件名
* @return json
*/
protected JSONObject getJSONObject(String filename) {
try {
return (JSONObject) JsonFileUtil.readJson(getDataFilePath(filename));
} catch (FileNotFoundException e) {
return null;
}
}
protected T getJsonObjectById(String file, String id, Class<T> cls) {
if (StrUtil.isEmpty(id)) {
return null;
}
JSONObject jsonObject = getJSONObject(file);
if (jsonObject == null) {
return null;
}
jsonObject = jsonObject.getJSONObject(id);
if (jsonObject == null) {
return null;
}
return jsonObject.toJavaObject(cls);
}
}

View File

@ -39,6 +39,7 @@ import org.dromara.jpom.configuration.AgentConfig;
import org.dromara.jpom.configuration.ProjectConfig;
import org.dromara.jpom.model.data.DslYmlDto;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.service.manage.ProjectInfoService;
import org.dromara.jpom.util.CommandUtil;
import org.dromara.jpom.util.StringUtil;
import org.springframework.stereotype.Service;
@ -59,9 +60,12 @@ import java.util.stream.Collectors;
public class ProjectFileBackupService {
private final ProjectConfig projectConfig;
private final ProjectInfoService projectInfoService;
public ProjectFileBackupService(AgentConfig agentConfig) {
public ProjectFileBackupService(AgentConfig agentConfig,
ProjectInfoService projectInfoService) {
this.projectConfig = agentConfig.getProject();
this.projectInfoService = projectInfoService;
}
/**
@ -71,9 +75,10 @@ public class ProjectFileBackupService {
* @return file
*/
public File pathProject(NodeProjectInfoModel projectInfoModel) {
DslYmlDto dslYmlDto = projectInfoModel.dslConfig();
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(projectInfoModel);
DslYmlDto dslYmlDto = infoModel.dslConfig();
String backupPath = resolveBackupPath(dslYmlDto);
return pathProject(backupPath, projectInfoModel.getId());
return pathProject(backupPath, infoModel.getId());
}
/**
@ -109,18 +114,19 @@ public class ProjectFileBackupService {
* @param projectInfoModel 项目
*/
public String backup(NodeProjectInfoModel projectInfoModel) {
int backupCount = resolveBackupCount(projectInfoModel.dslConfig());
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(projectInfoModel);
int backupCount = resolveBackupCount(infoModel.dslConfig());
if (backupCount <= 0) {
// 未开启备份
return null;
}
File file = FileUtil.file(projectInfoModel.allLib());
File file = projectInfoService.resolveLibFile(infoModel);
//
if (!FileUtil.exist(file)) {
return null;
}
String backupId = DateTime.now().toString(DatePattern.PURE_DATETIME_MS_FORMAT);
File projectFileBackup = this.pathProjectBackup(projectInfoModel, backupId);
File projectFileBackup = this.pathProjectBackup(infoModel, backupId);
Assert.state(!FileUtil.exist(projectFileBackup), "备份目录冲突:" + projectFileBackup.getName());
FileUtil.copyContent(file, projectFileBackup, true);
//
@ -187,16 +193,17 @@ public class ProjectFileBackupService {
// 备份ID 不存在
return;
}
String projectPath = projectInfoModel.allLib();
DslYmlDto dslYmlDto = projectInfoModel.dslConfig();
NodeProjectInfoModel infoModel = projectInfoService.resolveModel(projectInfoModel);
File projectPath = projectInfoService.resolveLibFile(infoModel);
DslYmlDto dslYmlDto = infoModel.dslConfig();
// 考虑到大文件对比比较耗时需要异步对比文件
ThreadUtil.execute(() -> {
try {
//String useBackupPath = resolveBackupPath(dslYmlDto);
File backupItemPath = this.pathProjectBackup(projectInfoModel, backupId);
File backupPath = this.pathProject(projectInfoModel);
File backupItemPath = this.pathProjectBackup(infoModel, backupId);
File backupPath = this.pathProject(infoModel);
// 获取文件列表
Map<String, File> backupFiles = this.listFiles(backupItemPath.getAbsolutePath());
Map<String, File> backupFiles = this.listFiles(backupItemPath);
Map<String, File> nowFiles = this.listFiles(projectPath);
nowFiles.forEach((fileSha1, file) -> {
// 当前目录存在的但是备份目录也存在的相同文件则删除
@ -231,7 +238,7 @@ public class ProjectFileBackupService {
// 检查备份保留个数
clearOldBackup(backupPath, dslYmlDto);
// 合并之前备份目录
margeBackupPath(projectInfoModel);
margeBackupPath(infoModel);
} catch (Exception e) {
log.warn("对比清空项目文件备份失败", e);
}
@ -275,7 +282,7 @@ public class ProjectFileBackupService {
* @param path 路径
* @return 文件列表信息
*/
private Map<String, File> listFiles(String path) {
private Map<String, File> listFiles(File path) {
// 将所有的文件信息组装并签名
List<File> files = FileUtil.loopFiles(path);
List<JSONObject> collect = files.stream().map(file -> {

View File

@ -43,7 +43,11 @@ import java.util.stream.Collectors;
*/
@Service
@Slf4j
public class WhitelistDirectoryService extends BaseDataService {
public class WhitelistDirectoryService extends BaseOperService<AgentWhitelist> {
public WhitelistDirectoryService() {
super(AgentConst.WHITELIST_DIRECTORY);
}
/**
* 获取授权信息配置如何没有配置或者配置错误将返回新对象
@ -52,7 +56,7 @@ public class WhitelistDirectoryService extends BaseDataService {
*/
public AgentWhitelist getWhitelist() {
try {
JSONObject jsonObject = getJSONObject(AgentConst.WHITELIST_DIRECTORY);
JSONObject jsonObject = getJSONObject();
if (jsonObject == null) {
return new AgentWhitelist();
}

View File

@ -22,11 +22,17 @@
*/
package org.dromara.jpom.service.manage;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import org.dromara.jpom.common.AgentConst;
import org.dromara.jpom.model.RunMode;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.service.BaseWorkspaceOptService;
import org.dromara.jpom.system.ExtConfigBean;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.io.File;
/**
* 项目管理
@ -36,16 +42,142 @@ import org.springframework.stereotype.Service;
@Service
public class ProjectInfoService extends BaseWorkspaceOptService<NodeProjectInfoModel> {
public ProjectInfoService() {
super(AgentConst.PROJECT);
}
@Override
public void addItem(NodeProjectInfoModel nodeProjectInfoModel) {
nodeProjectInfoModel.setCreateTime(DateUtil.now());
super.addItem(nodeProjectInfoModel);
public void updateItem(NodeProjectInfoModel data) {
super.updateItem(data);
}
/**
* 获取原始项目信息
*
* @param nodeProjectInfoModel 项目信息
* @return model
*/
public NodeProjectInfoModel resolveModel(NodeProjectInfoModel nodeProjectInfoModel) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
if (runMode != RunMode.Link) {
return nodeProjectInfoModel;
}
NodeProjectInfoModel item = this.getItem(nodeProjectInfoModel.getLinkId());
Assert.notNull(item, "被软链的项目已经不存在啦," + nodeProjectInfoModel.getLinkId());
return item;
}
/**
* 解析lib路径
*
* @param nodeProjectInfoModel 项目
* @return 项目的 lib 路径文件路径
*/
public String resolveLibPath(NodeProjectInfoModel nodeProjectInfoModel) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
if (runMode == RunMode.Link) {
NodeProjectInfoModel item = this.getItem(nodeProjectInfoModel.getLinkId());
Assert.notNull(item, "软链项目已经不存在啦");
return item.allLib();
}
return nodeProjectInfoModel.allLib();
}
/**
* 解析lib路径
*
* @param nodeProjectInfoModel 项目
* @return 项目的 lib 路径文件路径
*/
public File resolveLibFile(NodeProjectInfoModel nodeProjectInfoModel) {
String path = this.resolveLibPath(nodeProjectInfoModel);
return FileUtil.file(path);
}
/**
* 解析项目的日志路径
*
* @param nodeProjectInfoModel 项目
* @return path
*/
private File resolveLogFile(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
String id = nodeProjectInfoModel.getId();
File logPath = this.resolveLogPath(nodeProjectInfoModel, originalModel);
return FileUtil.file(logPath, id + ".log");
}
/**
* 解析项目的日志路径
*
* @param nodeProjectInfoModel 项目
* @return path
*/
private File resolveLogPath(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
String id = nodeProjectInfoModel.getId();
Assert.hasText(id, "没有项目id");
String loggedPath = originalModel.logPath();
if (StrUtil.isNotEmpty(loggedPath)) {
return FileUtil.file(loggedPath, id);
}
String path = ExtConfigBean.getPath();
return FileUtil.file(path, "project-log", id);
}
/**
* 解析项目的日志路径
*
* @param nodeProjectInfoModel 项目
* @return path
*/
public String resolveAbsoluteLog(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
File file = this.resolveAbsoluteLogFile(nodeProjectInfoModel, originalModel);
return FileUtil.getAbsolutePath(file);
}
/**
* 解析项目的日志路径
*
* @param nodeProjectInfoModel 项目
* @return path
*/
public File resolveAbsoluteLogFile(NodeProjectInfoModel nodeProjectInfoModel) {
NodeProjectInfoModel infoModel = this.resolveModel(nodeProjectInfoModel);
return this.resolveLogFile(nodeProjectInfoModel, infoModel);
}
/**
* 解析项目的日志路径
*
* @param nodeProjectInfoModel 项目
* @return path
*/
public File resolveAbsoluteLogFile(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
File file = this.resolveLogFile(nodeProjectInfoModel, originalModel);
// auto create dir
FileUtil.touch(file);
return file;
}
/**
* 解析日志备份路径
*
* @param nodeProjectInfoModel 项目
* @return file
*/
public File resolveLogBack(NodeProjectInfoModel nodeProjectInfoModel) {
NodeProjectInfoModel infoModel = this.resolveModel(nodeProjectInfoModel);
return this.resolveLogBack(nodeProjectInfoModel, infoModel);
}
/**
* 解析日志备份路径
*
* @param nodeProjectInfoModel 项目
* @return file
*/
public File resolveLogBack(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
File logPath = this.resolveLogPath(nodeProjectInfoModel, originalModel);
return FileUtil.file(logPath, "back");
}
}

View File

@ -19,6 +19,7 @@ import org.dromara.jpom.model.data.DslYmlDto;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.model.data.NodeScriptModel;
import org.dromara.jpom.script.DslScriptBuilder;
import org.dromara.jpom.service.manage.ProjectInfoService;
import org.dromara.jpom.service.system.AgentWorkspaceEnvVarService;
import org.dromara.jpom.socket.ConsoleCommandOp;
import org.dromara.jpom.system.ExtConfigBean;
@ -41,15 +42,18 @@ public class DslScriptServer {
private final NodeScriptServer nodeScriptServer;
private final ProjectLogConfig logConfig;
private final JpomApplication jpomApplication;
private final ProjectInfoService projectInfoService;
public DslScriptServer(AgentWorkspaceEnvVarService agentWorkspaceEnvVarService,
NodeScriptServer nodeScriptServer,
ProjectLogConfig logConfig,
JpomApplication jpomApplication) {
JpomApplication jpomApplication,
ProjectInfoService projectInfoService) {
this.agentWorkspaceEnvVarService = agentWorkspaceEnvVarService;
this.nodeScriptServer = nodeScriptServer;
this.logConfig = logConfig;
this.jpomApplication = jpomApplication;
this.projectInfoService = projectInfoService;
}
/**
@ -58,8 +62,8 @@ public class DslScriptServer {
* @param scriptProcess 脚本流程
* @param log 日志
*/
public void run(DslYmlDto.BaseProcess scriptProcess, NodeProjectInfoModel nodeProjectInfoModel, String action, String log, boolean sync) throws Exception {
DslScriptBuilder builder = this.create(scriptProcess, nodeProjectInfoModel, action, log);
public void run(DslYmlDto.BaseProcess scriptProcess, NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, String action, String log, boolean sync) throws Exception {
DslScriptBuilder builder = this.create(scriptProcess, nodeProjectInfoModel, originalModel, action, log);
Future<?> execute = ThreadUtil.execAsync(builder);
if (sync) {
execute.get();
@ -71,8 +75,8 @@ public class DslScriptServer {
*
* @param scriptProcess 脚本流程
*/
public Tuple syncRun(DslYmlDto.BaseProcess scriptProcess, NodeProjectInfoModel nodeProjectInfoModel, String action) {
try (DslScriptBuilder builder = this.create(scriptProcess, nodeProjectInfoModel, action, null)) {
public Tuple syncRun(DslYmlDto.BaseProcess scriptProcess, NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, String action) {
try (DslScriptBuilder builder = this.create(scriptProcess, nodeProjectInfoModel, originalModel, action, null)) {
return builder.syncExecute();
}
}
@ -97,7 +101,7 @@ public class DslScriptServer {
* @param scriptProcess 流程
* @return data
*/
public Tuple resolveProcessScript(NodeProjectInfoModel nodeProjectInfoModel, DslYmlDto.BaseProcess scriptProcess) {
private Tuple resolveProcessScript(NodeProjectInfoModel nodeProjectInfoModel, DslYmlDto.BaseProcess scriptProcess) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("status", false);
if (scriptProcess == null) {
@ -118,7 +122,8 @@ public class DslScriptServer {
jsonObject.put("scriptId", scriptId);
return new Tuple(jsonObject, item);
}
File scriptFile = FileUtil.file(nodeProjectInfoModel.allLib(), scriptId);
File lib = projectInfoService.resolveLibFile(nodeProjectInfoModel);
File scriptFile = FileUtil.file(lib, scriptId);
if (FileUtil.isFile(scriptFile)) {
// 文件存在
jsonObject.put("status", true);
@ -138,8 +143,8 @@ public class DslScriptServer {
* @param log 日志路径
* @param action 具体操作
*/
private DslScriptBuilder create(DslYmlDto.BaseProcess scriptProcess, NodeProjectInfoModel nodeProjectInfoModel, String action, String log) {
Tuple tuple = this.resolveProcessScript(nodeProjectInfoModel, scriptProcess);
private DslScriptBuilder create(DslYmlDto.BaseProcess scriptProcess, NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, String action, String log) {
Tuple tuple = this.resolveProcessScript(originalModel, scriptProcess);
JSONObject jsonObject = tuple.get(0);
// 判断状态
boolean status = jsonObject.getBooleanValue("status");
@ -149,6 +154,7 @@ public class DslScriptServer {
});
String type = jsonObject.getString("type");
EnvironmentMapBuilder environment = this.environment(nodeProjectInfoModel, scriptProcess);
environment.put("PROJECT_LOG_FILE", log);
File scriptFile;
boolean autoDelete = false;
if (StrUtil.equals(type, "file")) {
@ -196,12 +202,13 @@ public class DslScriptServer {
return map1;
})
.ifPresent(environmentMapBuilder::putStr);
String lib = projectInfoService.resolveLibPath(nodeProjectInfoModel);
//
environmentMapBuilder
.putStr(scriptProcess.getScriptEnv())
.put("PROJECT_ID", nodeProjectInfoModel.getId())
.put("PROJECT_NAME", nodeProjectInfoModel.getName())
.put("PROJECT_PATH", nodeProjectInfoModel.allLib());
.put("PROJECT_PATH", lib);
return environmentMapBuilder;
}
}

View File

@ -208,10 +208,10 @@ public class AgentWebSocketConsoleHandle extends BaseAgentWebSocketHandle {
} finally {
if (logUser) {
// 记录操作人
NodeProjectInfoModel newNodeProjectInfoModel = projectInfoService.getItem(nodeProjectInfoModel.getId());
NodeProjectInfoModel update = new NodeProjectInfoModel();
String name = getOptUserName(session);
newNodeProjectInfoModel.setModifyUser(name);
projectInfoService.updateItem(newNodeProjectInfoModel);
update.setModifyUser(name);
projectInfoService.updateById(update, nodeProjectInfoModel.getId());
}
}
// 返回数据
@ -246,7 +246,8 @@ public class AgentWebSocketConsoleHandle extends BaseAgentWebSocketHandle {
private JsonMessage<Object> searchLog(Session session, NodeProjectInfoModel nodeProjectInfoModel, JSONObject reqJson) {
//
String fileName = reqJson.getString("logFile");
File file = FileUtil.file(nodeProjectInfoModel.allLib(), fileName);
File libFile = projectInfoService.resolveLibFile(nodeProjectInfoModel);
File file = FileUtil.file(libFile, fileName);
if (!FileUtil.isFile(file)) {
return new JsonMessage<>(404, "文件不存在");
}
@ -285,9 +286,10 @@ public class AgentWebSocketConsoleHandle extends BaseAgentWebSocketHandle {
String fileName = reqJson.getString("fileName");
File file;
if (StrUtil.isEmpty(fileName)) {
file = nodeProjectInfoModel.absoluteLogFile();
file = projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel);
} else {
file = FileUtil.file(nodeProjectInfoModel.allLib(), fileName);
File libFile = projectInfoService.resolveLibFile(nodeProjectInfoModel);
file = FileUtil.file(libFile, fileName);
}
try {
Charset charset = logConfig.getFileCharset();

View File

@ -115,7 +115,7 @@ public class AgentStartInit implements ILoadEvent, ISystemTask {
}
private void checkProject(NodeProjectInfoModel nodeProjectInfoModel) {
File file = nodeProjectInfoModel.absoluteLogFile();
File file = projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel);
if (!file.exists()) {
return;
}
@ -130,7 +130,7 @@ public class AgentStartInit implements ILoadEvent, ISystemTask {
}
}
// 清理过期的文件
File logFile = nodeProjectInfoModel.logBack();
File logFile = projectInfoService.resolveLogBack(nodeProjectInfoModel);
DateTime nowTime = DateTime.now();
List<File> files = FileUtil.loopFiles(logFile, pathname -> {
DateTime dateTime = DateUtil.date(pathname.lastModified());

View File

@ -30,7 +30,6 @@ import cn.hutool.extra.servlet.ServletUtil;
import lombok.Lombok;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.dromara.jpom.common.multipart.MultipartFileBuilder;
import org.dromara.jpom.util.FileUtils;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestAttributes;
@ -47,7 +46,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
/**
@ -228,24 +226,6 @@ public abstract class BaseJpomController {
throw new IllegalArgumentException("not MultipartHttpServletRequest");
}
/**
* 判断是否存在文件
*
* @return true 存在文件
*/
protected boolean hasFile() {
Map<String, MultipartFile> fileMap = getMultiRequest().getFileMap();
return fileMap.size() > 0;
}
/**
* 创建多文件上传对象
*
* @return MultipartFileBuilder
*/
protected MultipartFileBuilder createMultipart() {
return new MultipartFileBuilder(getMultiRequest());
}
// ------------------------文件上传结束
/**
@ -346,7 +326,7 @@ public abstract class BaseJpomController {
protected void setApplicationHeader(HttpServletResponse response, String fileName) {
String contentType = ObjectUtil.defaultIfNull(FileUtil.getMimeType(fileName), "application/octet-stream");
response.setHeader("Content-Disposition", StrUtil.format("attachment;filename=\"{}\"",
URLUtil.encode(fileName, CharsetUtil.CHARSET_UTF_8)));
URLUtil.encode(fileName, CharsetUtil.CHARSET_UTF_8)));
response.setContentType(contentType);
}

View File

@ -141,8 +141,15 @@ public class JpomManifest {
// Windows NT 10.0; Win64; x64
OsInfo osInfo = SystemUtil.getOsInfo();
JavaInfo javaInfo = SystemUtil.getJavaInfo();
boolean inDocker = StrUtil.isNotEmpty(SystemUtil.get("JPOM_PKG"));
String osName = Opt.ofBlankAble(osInfo.getName()).orElseGet(() -> {
if (inDocker) {
return "docker";
}
return UserAgentInfo.NameUnknown;
});
return StrUtil.format("{} {}; {}; {}",
Opt.ofBlankAble(osInfo.getName()).orElse(UserAgentInfo.NameUnknown),
osName,
Opt.ofBlankAble(osInfo.getVersion()).orElse("0"),
Opt.ofBlankAble(osInfo.getArch()).orElse(UserAgentInfo.NameUnknown),
Opt.ofBlankAble(javaInfo.getVersion()).orElse(UserAgentInfo.NameUnknown)

View File

@ -1,371 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.dromara.jpom.common.multipart;
import ch.qos.logback.core.util.FileSize;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.UnicodeUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* 文件上传builder
*
* @author bwcx_jzy
* @since 2018/10/23
*/
public class MultipartFileBuilder {
private final MultipartHttpServletRequest multipartHttpServletRequest;
/**
* 限制上传文件的大小
*/
private long maxSize = 0;
/**
* 字段名称
*/
private final Set<String> fieldNames = new HashSet<>();
/**
* 多文件上传
*/
private boolean multiple;
/**
* 文件名后缀
*/
private String[] fileExt;
/**
* 文件类型
*
* @see FileUtil#getMimeType(String)
*/
private String contentTypePrefix;
/**
* 文件流类型
*
* @see FileUtil#getType(File)
*/
private String[] inputStreamType;
/**
* 保存路径
*/
private String savePath;
/**
* 使用原文件名
*/
private boolean useOriginalFilename;
/**
* 文件上传大小限制
*
* @param maxSize 字节大小
* @return this
*/
public MultipartFileBuilder setMaxSize(long maxSize) {
this.maxSize = maxSize;
return this;
}
/**
* 文件上传大小限制
*
* @param maxSize 字符串
* @return this
*/
public MultipartFileBuilder setMaxSize(String maxSize) {
this.maxSize = FileSize.valueOf(maxSize).getSize();
return this;
}
/**
* 是否使用原文件名保存
*
* @param useOriginalFilename true
* @return this
*/
public MultipartFileBuilder setUseOriginalFilename(boolean useOriginalFilename) {
this.useOriginalFilename = useOriginalFilename;
return this;
}
/**
* 需要接受的文件字段
*
* @param fieldName 参数名
* @return this
*/
public MultipartFileBuilder addFieldName(String fieldName) {
this.fieldNames.add(fieldName);
return this;
}
/**
* 清空数据并重新赋值
*
* @param fieldName 参数名
* @return this
*/
public MultipartFileBuilder resetFieldName(String fieldName) {
this.fieldNames.clear();
this.fieldNames.add(fieldName);
return this;
}
/**
* 是否为多文件上传
*
* @param multiple true
* @return this
*/
public MultipartFileBuilder setMultiple(boolean multiple) {
this.multiple = multiple;
return this;
}
/**
* 限制文件后缀名
*
* @param fileExt 后缀
* @return this
*/
public MultipartFileBuilder setFileExt(String... fileExt) {
this.fileExt = fileExt;
return this;
}
/**
* 限制文件流类型
*
* @param inputStreamType type
* @return this
* @see FileTypeUtil#getType(InputStream)
*/
public MultipartFileBuilder setInputStreamType(String... inputStreamType) {
this.inputStreamType = inputStreamType;
return this;
}
/**
* 使用 获取到类型
*
* @param contentTypePrefix 前缀
* @return this
* @see FileUtil#getMimeType(String)
*/
public MultipartFileBuilder setContentTypePrefix(String contentTypePrefix) {
this.contentTypePrefix = contentTypePrefix;
return this;
}
/**
* 文件保存的路径
*
* @param savePath 路径
* @return this
*/
public MultipartFileBuilder setSavePath(String savePath) {
this.savePath = savePath;
return this;
}
private void checkSaveOne() {
if (this.fieldNames.size() != 1) {
throw new IllegalArgumentException("fieldNames size:" + this.fieldNames.size() + " use saves");
}
if (this.multiple) {
throw new IllegalArgumentException("multiple use saves");
}
}
/**
* 接收单文件上传
*
* @return 本地路径
* @throws IOException IO
*/
public String save() throws IOException {
checkSaveOne();
String[] paths = saves();
return paths[0];
}
/**
* 保存多个文件
*
* @return 本地路径数组
* @throws IOException IO
*/
public String[] saves() throws IOException {
if (fieldNames.isEmpty()) {
throw new IllegalArgumentException("fieldNames:empty");
}
String[] paths = new String[fieldNames.size()];
int index = 0;
for (String fieldName : fieldNames) {
if (this.multiple) {
List<MultipartFile> multipartFiles = multipartHttpServletRequest.getFiles(fieldName);
for (MultipartFile multipartFile : multipartFiles) {
paths[index++] = saveAndName(multipartFile)[0];
}
} else {
MultipartFile multipartFile = multipartHttpServletRequest.getFile(fieldName);
paths[index++] = saveAndName(multipartFile)[0];
}
}
return paths;
}
/**
* 上传文件并且返回原文件名
*
* @return 数组
* @throws IOException IO
*/
public String[] saveAndName() throws IOException {
checkSaveOne();
List<String[]> list = saveAndNames();
return list.get(0);
}
/**
* 上传文件并且返回原文件名
*
* @return 集合
* @throws IOException IO
*/
public List<String[]> saveAndNames() throws IOException {
if (fieldNames.isEmpty()) {
throw new IllegalArgumentException("fieldNames:empty");
}
List<String[]> list = new ArrayList<>();
for (String fieldName : fieldNames) {
if (this.multiple) {
List<MultipartFile> multipartFiles = multipartHttpServletRequest.getFiles(fieldName);
for (MultipartFile multipartFile : multipartFiles) {
String[] info = saveAndName(multipartFile);
list.add(info);
}
} else {
MultipartFile multipartFile = multipartHttpServletRequest.getFile(fieldName);
String[] info = saveAndName(multipartFile);
list.add(info);
}
}
return list;
}
/**
* 保存文件并验证类型
*
* @param multiFile file
* @return 本地路径和原文件名
* @throws IOException IO
*/
private String[] saveAndName(MultipartFile multiFile) throws IOException {
Assert.notNull(multiFile, "not null");
String fileName = multiFile.getOriginalFilename();
if (StrUtil.isEmpty(fileName)) {
throw new IllegalArgumentException("fileName:不能获取到文件名");
}
long fileSize = multiFile.getSize();
if (fileSize <= 0) {
throw new IllegalArgumentException("fileSize:文件内容为空");
}
// 文件名后缀
if (this.fileExt != null) {
String checkName = FileUtil.extName(fileName);
boolean find = false;
for (String ext : this.fileExt) {
find = StrUtil.equalsIgnoreCase(checkName, ext);
if (find) {
break;
}
}
if (!find) {
throw new IllegalArgumentException("fileExt:类型错误:" + checkName);
}
}
// 文件大小
if (maxSize > 0 && fileSize > maxSize) {
throw new IllegalArgumentException("maxSize:too big:" + fileSize + ">" + maxSize);
}
// 文件流类型
if (this.inputStreamType != null) {
InputStream inputStream = multiFile.getInputStream();
String fileType = FileTypeUtil.getType(inputStream);
if (!ArrayUtil.containsIgnoreCase(this.inputStreamType, fileType)) {
throw new IllegalArgumentException("inputStreamType:类型错误:" + fileType);
}
}
// 保存路径
String localPath;
if (this.savePath != null) {
localPath = this.savePath;
} else {
localPath = MultipartFileConfig.getFileTempPath();
}
// 保存的文件名
String filePath;
if (useOriginalFilename) {
filePath = FileUtil.normalize(String.format("%s/%s", localPath, fileName));
} else {
// 防止中文乱码
String saveFileName = UnicodeUtil.toUnicode(fileName);
saveFileName = saveFileName.replace(StrUtil.BACKSLASH, "_");
// 生成唯一id
filePath = FileUtil.normalize(String.format("%s/%s_%s", localPath, IdUtil.objectId(), saveFileName));
}
FileUtil.writeFromStream(multiFile.getInputStream(), filePath);
// 文件contentType
if (this.contentTypePrefix != null) {
// Path source = Paths.get(filePath);
String contentType = FileUtil.getMimeType(filePath);
//Files.probeContentType(source);
if (contentType == null) {
// 自动清理文件
FileUtil.del(filePath);
throw new IllegalArgumentException("contentTypePrefix:获取文件类型失败");
}
if (!contentType.startsWith(contentTypePrefix)) {
// 自动清理文件
FileUtil.del(filePath);
throw new IllegalArgumentException("contentTypePrefix:文件类型不正确:" + contentType);
}
}
return new String[]{filePath, fileName};
}
public MultipartFileBuilder(MultipartHttpServletRequest multipartHttpServletRequest) {
Objects.requireNonNull(multipartHttpServletRequest);
this.multipartHttpServletRequest = multipartHttpServletRequest;
}
}

View File

@ -1,54 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.dromara.jpom.common.multipart;
import cn.hutool.core.util.StrUtil;
import cn.hutool.system.UserInfo;
/**
* 上传文件保存路径
*
* @author bwcx_jzy
* @since 2017/10/25
*/
public class MultipartFileConfig {
private static String fileTempPath;
private static final UserInfo USER_INFO = new UserInfo();
/**
* 设置文件上传保存路径
*
* @param fileTempPath path
*/
public static void setFileTempPath(String fileTempPath) {
MultipartFileConfig.fileTempPath = fileTempPath;
}
public static String getFileTempPath() {
if (StrUtil.isBlank(fileTempPath)) {
fileTempPath = USER_INFO.getTempDir();
}
return fileTempPath;
}
}

View File

@ -29,28 +29,32 @@ package org.dromara.jpom.model;
* @since 2019/4/22
*/
public enum RunMode {
/**
* java -classpath
*/
ClassPath,
/**
* java -jar
*/
Jar,
/**
* java -jar Springboot war
*/
JarWar,
/**
* java -Djava.ext.dirs=lib -cp conf:run.jar $MAIN_CLASS
*/
JavaExtDirsCp,
/**
* 纯文件管理
*/
File,
/**
* 自定义项目管理
*/
Dsl,
/**
* java -classpath
*/
ClassPath,
/**
* java -jar
*/
Jar,
/**
* java -jar Springboot war
*/
JarWar,
/**
* java -Djava.ext.dirs=lib -cp conf:run.jar $MAIN_CLASS
*/
JavaExtDirsCp,
/**
* 纯文件管理
*/
File,
/**
* 自定义项目管理
*/
Dsl,
/**
* 软链
*/
Link,
}

View File

@ -29,10 +29,10 @@ import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.keepbx.jpom.model.BaseJsonModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.model.BaseModel;
import org.dromara.jpom.system.ExtConfigBean;
import org.springframework.util.Assert;
@ -53,7 +53,7 @@ import java.util.stream.Collectors;
@Slf4j
@Data
@EqualsAndHashCode(callSuper = true)
public class AgentWhitelist extends BaseJsonModel {
public class AgentWhitelist extends BaseModel {
/**
* 项目目录授权日志文件授权
*/

View File

@ -55,9 +55,9 @@ public class JvmUtil {
};
/**
* 持的标签数组
* 持的标签数组
*/
private static final String[] JPOM_PID_TAG = new String[]{"DJpom.application", "Jpom.application", "Dapplication"};
private static final String[] JPOM_PID_TAG = new String[]{"DJpom.application", "Jpom.application"};
/**
* 检查 jps 命令是否正常
@ -97,10 +97,13 @@ public class JvmUtil {
public static boolean exist(long pid) {
String execSystemCommand = CommandUtil.execSystemCommand("jps -l");
List<String> list = StrSplitter.splitTrim(execSystemCommand, StrUtil.LF, true);
String pidCommandInfo = list.stream().filter(s -> {
List<String> split = StrSplitter.splitTrim(s, StrUtil.SPACE, true);
return StrUtil.equals(pid + "", CollUtil.getFirst(split));
}).findAny().orElse(null);
String pidCommandInfo = list.stream()
.filter(s -> {
List<String> split = StrSplitter.splitTrim(s, StrUtil.SPACE, true);
return StrUtil.equals(pid + "", CollUtil.getFirst(split));
})
.findAny()
.orElse(null);
return StrUtil.isNotEmpty(pidCommandInfo);
}

View File

@ -141,7 +141,7 @@ public enum NodeUrl {
Manage_Log_logBack("/manage/log/logBack"),
Manage_Log_export("/manage/log/export.html", true),
Manage_Log_export("/manage/log/export", true),
Script_List("/script/list.json"),

View File

@ -77,7 +77,7 @@ public class BuildInfoHistoryController extends BaseServerController {
*
* @param logId 日志id
*/
@RequestMapping(value = "/build/history/download_file.html", method = RequestMethod.GET)
@RequestMapping(value = "/build/history/download_file", method = RequestMethod.GET)
@Feature(method = MethodFeature.DOWNLOAD)
public void downloadFile(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据") String logId, HttpServletRequest request, HttpServletResponse response) {
BuildHistoryLog buildHistoryLog = dbBuildHistoryLogService.getByKey(logId, request, false);
@ -94,8 +94,9 @@ public class BuildInfoHistoryController extends BaseServerController {
@Feature(method = MethodFeature.DOWNLOAD)
public void downloadFile(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据") String buildId,
@ValidatorItem(ValidatorRule.NUMBERS) int buildNumberId,
HttpServletResponse response) {
String workspaceId = dbBuildHistoryLogService.getCheckUserWorkspace(getRequest());
HttpServletResponse response,
HttpServletRequest request) {
String workspaceId = dbBuildHistoryLogService.getCheckUserWorkspace(request);
//
BuildHistoryLog historyLog = new BuildHistoryLog();
historyLog.setWorkspaceId(workspaceId);
@ -119,7 +120,7 @@ public class BuildInfoHistoryController extends BaseServerController {
}
@RequestMapping(value = "/build/history/download_log.html", method = RequestMethod.GET)
@RequestMapping(value = "/build/history/download_log", method = RequestMethod.GET)
@Feature(method = MethodFeature.DOWNLOAD)
public void downloadLog(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据") String logId, HttpServletRequest request, HttpServletResponse response) {
BuildHistoryLog buildHistoryLog = dbBuildHistoryLogService.getByKey(logId, request);
@ -137,8 +138,8 @@ public class BuildInfoHistoryController extends BaseServerController {
@RequestMapping(value = "/build/history/history_list.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<BuildHistoryLog>> historyList() {
PageResultDto<BuildHistoryLog> pageResultTemp = dbBuildHistoryLogService.listPage(getRequest());
public IJsonMessage<PageResultDto<BuildHistoryLog>> historyList(HttpServletRequest request) {
PageResultDto<BuildHistoryLog> pageResultTemp = dbBuildHistoryLogService.listPage(request);
pageResultTemp.each(buildHistoryLog -> {
File file = BuildUtil.getHistoryPackageFile(buildHistoryLog.getBuildDataId(), buildHistoryLog.getBuildNumberId(), buildHistoryLog.getResultDirFile());
buildHistoryLog.setHasFile(FileUtil.isNotEmpty(file));
@ -157,10 +158,10 @@ public class BuildInfoHistoryController extends BaseServerController {
*/
@RequestMapping(value = "/build/history/delete_log.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<String> delete(@ValidatorConfig(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据")) String logId) {
public IJsonMessage<String> delete(@ValidatorConfig(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据")) String logId, HttpServletRequest request) {
List<String> strings = StrUtil.splitTrim(logId, StrUtil.COMMA);
for (String itemId : strings) {
BuildHistoryLog buildHistoryLog = dbBuildHistoryLogService.getByKey(itemId, getRequest());
BuildHistoryLog buildHistoryLog = dbBuildHistoryLogService.getByKey(itemId, request);
IJsonMessage<String> jsonMessage = dbBuildHistoryLogService.deleteLogAndFile(buildHistoryLog);
if (!jsonMessage.success()) {
return jsonMessage;

View File

@ -97,8 +97,9 @@ public class BuildInfoManageController extends BaseServerController {
String checkRepositoryDiff,
String projectSecondaryDirectory,
String buildEnvParameter,
String dispatchSelectProject) {
BuildInfoModel item = buildInfoService.getByKey(id, getRequest());
String dispatchSelectProject,
HttpServletRequest request) {
BuildInfoModel item = buildInfoService.getByKey(id, request);
Assert.notNull(item, "没有对应数据");
// 更新数据
BuildInfoModel update = new BuildInfoModel();
@ -136,8 +137,8 @@ public class BuildInfoManageController extends BaseServerController {
*/
@RequestMapping(value = "/build/manage/cancel", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EXECUTE)
public IJsonMessage<String> cancel(@ValidatorConfig(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据")) String id) {
BuildInfoModel item = buildInfoService.getByKey(id, getRequest());
public IJsonMessage<String> cancel(@ValidatorConfig(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据")) String id, HttpServletRequest request) {
BuildInfoModel item = buildInfoService.getByKey(id, request);
Objects.requireNonNull(item, "没有对应数据");
String checkStatus = buildExecuteService.checkStatus(item);
BuildStatus nowStatus = BaseEnum.getEnum(BuildStatus.class, item.getStatus());
@ -184,8 +185,9 @@ public class BuildInfoManageController extends BaseServerController {
@Feature(method = MethodFeature.LIST)
public IJsonMessage<JSONObject> getNowLog(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据") String id,
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "没有buildId") int buildId,
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "line") int line) {
BuildInfoModel item = buildInfoService.getByKey(id, getRequest());
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "line") int line,
HttpServletRequest request) {
BuildInfoModel item = buildInfoService.getByKey(id, request);
Assert.notNull(item, "没有对应数据");
Assert.state(buildId <= item.getBuildId(), "还没有对应的构建记录");

View File

@ -42,6 +42,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@ -72,8 +73,8 @@ public class BuildInfoTriggerController extends BaseServerController {
*/
@RequestMapping(value = "/build/trigger/url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Map<String, String>> getTriggerUrl(String id, String rest) {
BuildInfoModel item = buildInfoService.getByKey(id, getRequest());
public IJsonMessage<Map<String, String>> getTriggerUrl(String id, String rest, HttpServletRequest request) {
BuildInfoModel item = buildInfoService.getByKey(id, request);
UserModel user = getUser();
BuildInfoModel updateInfo;
if (StrUtil.isEmpty(item.getTriggerToken()) || StrUtil.isNotEmpty(rest)) {
@ -85,12 +86,12 @@ public class BuildInfoTriggerController extends BaseServerController {
} else {
updateInfo = item;
}
Map<String, String> map = this.getBuildToken(updateInfo);
Map<String, String> map = this.getBuildToken(updateInfo, request);
return JsonMessage.success(StrUtil.isEmpty(rest) ? "ok" : "重置成功", map);
}
private Map<String, String> getBuildToken(BuildInfoModel item) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(getRequest(), ServerConst.PROXY_PATH);
private Map<String, String> getBuildToken(BuildInfoModel item, HttpServletRequest request) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(request, ServerConst.PROXY_PATH);
String url = ServerOpenApi.BUILD_TRIGGER_BUILD2.
replace("{id}", item.getId()).
replace("{token}", item.getTriggerToken());

View File

@ -133,8 +133,8 @@ public class DockerInfoController extends BaseServerController {
@GetMapping(value = "sync-to-workspace", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
@SystemPermission()
public IJsonMessage<String> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId) {
String nowWorkspaceId = dockerInfoService.getCheckUserWorkspace(getRequest());
public IJsonMessage<String> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId, HttpServletRequest request) {
String nowWorkspaceId = dockerInfoService.getCheckUserWorkspace(request);
//
dockerInfoService.checkUserWorkspace(toWorkspaceId);
dockerInfoService.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId);

View File

@ -49,7 +49,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.List;
/**
@ -85,8 +84,8 @@ public class MonitorListController extends BaseServerController {
*/
@RequestMapping(value = "getMonitorList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<MonitorModel>> getMonitorList() {
PageResultDto<MonitorModel> pageResultDto = monitorService.listPage(getRequest());
public IJsonMessage<PageResultDto<MonitorModel>> getMonitorList(HttpServletRequest request) {
PageResultDto<MonitorModel> pageResultDto = monitorService.listPage(request);
return JsonMessage.success("", pageResultDto);
}
@ -98,9 +97,9 @@ public class MonitorListController extends BaseServerController {
*/
@RequestMapping(value = "deleteMonitor", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<Object> deleteMonitor(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "删除失败") String id) throws SQLException {
public IJsonMessage<Object> deleteMonitor(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "删除失败") String id, HttpServletRequest request) {
//
HttpServletRequest request = getRequest();
int delByKey = monitorService.delByKey(id, request);
if (delByKey > 0) {
// 删除日志
@ -121,9 +120,10 @@ public class MonitorListController extends BaseServerController {
@RequestMapping(value = "updateMonitor", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Object> updateMonitor(String id,
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "监控名称不能为空") String name,
@ValidatorItem(msg = "请配置监控周期") String execCron,
String notifyUser, String webhook) {
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "监控名称不能为空") String name,
@ValidatorItem(msg = "请配置监控周期") String execCron,
String notifyUser, String webhook,
HttpServletRequest request) {
String status = getParameter("status");
String autoRestart = getParameter("autoRestart");
@ -171,7 +171,7 @@ public class MonitorListController extends BaseServerController {
monitorService.insert(monitorModel);
return JsonMessage.success("添加成功");
}
HttpServletRequest request = getRequest();
monitorService.updateById(monitorModel, request);
return JsonMessage.success("修改成功");
}

View File

@ -36,6 +36,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* 监控列表
*
@ -60,8 +62,8 @@ public class MonitorLogController extends BaseServerController {
*/
@RequestMapping(value = "list_data.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<MonitorNotifyLog>> listData() {
PageResultDto<MonitorNotifyLog> pageResult = dbMonitorNotifyLogService.listPage(getRequest());
public IJsonMessage<PageResultDto<MonitorNotifyLog>> listData(HttpServletRequest request) {
PageResultDto<MonitorNotifyLog> pageResult = dbMonitorNotifyLogService.listPage(request);
return JsonMessage.success("获取成功", pageResult);
}
}

View File

@ -44,6 +44,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@ -69,8 +70,8 @@ public class MonitorUserOptListController extends BaseServerController {
@RequestMapping(value = "list_data", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<MonitorUserOptModel>> getMonitorList() {
PageResultDto<MonitorUserOptModel> pageResultDto = monitorUserOptService.listPage(getRequest());
public IJsonMessage<PageResultDto<MonitorUserOptModel>> getMonitorList(HttpServletRequest request) {
PageResultDto<MonitorUserOptModel> pageResultDto = monitorUserOptService.listPage(request);
return JsonMessage.success("", pageResultDto);
}
@ -117,9 +118,9 @@ public class MonitorUserOptListController extends BaseServerController {
*/
@RequestMapping(value = "delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<Object> deleteMonitor(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "删除失败") String id) {
public IJsonMessage<Object> deleteMonitor(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "删除失败") String id, HttpServletRequest request) {
//
monitorUserOptService.delByKey(id, getRequest());
monitorUserOptService.delByKey(id, request);
return JsonMessage.success("删除成功");
}
@ -135,11 +136,11 @@ public class MonitorUserOptListController extends BaseServerController {
@RequestMapping(value = "update", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Object> updateMonitor(String id,
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "监控名称不能为空") String name,
String notifyUser,
String monitorUser,
String monitorOpt,
String monitorFeature) {
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "监控名称不能为空") String name,
String notifyUser,
String monitorUser,
String monitorOpt,
String monitorFeature) {
String status = getParameter("status");
@ -210,7 +211,7 @@ public class MonitorUserOptListController extends BaseServerController {
@RequestMapping(value = "changeStatus", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Object> changeStatus(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "id不能为空") String id,
String status) {
String status) {
MonitorUserOptModel monitorModel = monitorUserOptService.getByKey(id);
Assert.notNull(monitorModel, "不存在监控项啦");

View File

@ -131,8 +131,7 @@ public class NodeEditController extends BaseServerController {
*/
@PostMapping(value = "del.json", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<String> del(@ValidatorItem String id) {
HttpServletRequest request = getRequest();
public IJsonMessage<String> del(@ValidatorItem String id, HttpServletRequest request) {
this.checkDataBind(id, request, "删除");
//
{
@ -185,8 +184,7 @@ public class NodeEditController extends BaseServerController {
*/
@GetMapping(value = "unbind.json", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<String> unbind(String id) {
HttpServletRequest request = getRequest();
public IJsonMessage<String> unbind(String id, HttpServletRequest request) {
this.checkDataBind(id, request, "解绑");
//
projectInfoCacheService.delCache(id, request);
@ -206,8 +204,8 @@ public class NodeEditController extends BaseServerController {
@GetMapping(value = "sync-to-workspace", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
@SystemPermission()
public IJsonMessage<String> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId) {
String nowWorkspaceId = nodeService.getCheckUserWorkspace(getRequest());
public IJsonMessage<String> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId, HttpServletRequest request) {
String nowWorkspaceId = nodeService.getCheckUserWorkspace(request);
//
nodeService.checkUserWorkspace(toWorkspaceId);
nodeService.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId);
@ -224,8 +222,7 @@ public class NodeEditController extends BaseServerController {
*/
@GetMapping(value = "sort-item", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId) {
HttpServletRequest request = getRequest();
public IJsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId, HttpServletRequest request) {
if (StrUtil.equalsIgnoreCase(method, "top")) {
nodeService.sortToTop(id, request);
} else if (StrUtil.equalsIgnoreCase(method, "up")) {

View File

@ -73,18 +73,6 @@ public class NodeProjectInfoController extends BaseServerController {
this.triggerTokenLogServer = triggerTokenLogServer;
}
/**
* @return json
* @author Hotstrip
* load node project list
* 加载节点项目列表
*/
@PostMapping(value = "node_project_list", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<PageResultDto<ProjectInfoCacheModel>> nodeProjectList() {
PageResultDto<ProjectInfoCacheModel> resultDto = projectInfoCacheService.listPageNode(getRequest());
return JsonMessage.success("success", resultDto);
}
/**
* load node project list
@ -94,8 +82,8 @@ public class NodeProjectInfoController extends BaseServerController {
* @author Hotstrip
*/
@PostMapping(value = "project_list", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<PageResultDto<ProjectInfoCacheModel>> projectList() {
PageResultDto<ProjectInfoCacheModel> resultDto = projectInfoCacheService.listPage(getRequest());
public IJsonMessage<PageResultDto<ProjectInfoCacheModel>> projectList(HttpServletRequest request) {
PageResultDto<ProjectInfoCacheModel> resultDto = projectInfoCacheService.listPage(request);
return JsonMessage.success("success", resultDto);
}
@ -107,8 +95,8 @@ public class NodeProjectInfoController extends BaseServerController {
* @author Hotstrip
*/
@GetMapping(value = "project_list_all", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<List<ProjectInfoCacheModel>> projectListAll() {
List<ProjectInfoCacheModel> projectInfoCacheModels = projectInfoCacheService.listByWorkspace(getRequest());
public IJsonMessage<List<ProjectInfoCacheModel>> projectListAll(HttpServletRequest request) {
List<ProjectInfoCacheModel> projectInfoCacheModels = projectInfoCacheService.listByWorkspace(request);
return JsonMessage.success("", projectInfoCacheModels);
}
@ -131,10 +119,10 @@ public class NodeProjectInfoController extends BaseServerController {
*/
@GetMapping(value = "sync_project", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(cls = ClassFeature.PROJECT, method = MethodFeature.DEL)
public IJsonMessage<Object> syncProject(String nodeId) {
public IJsonMessage<Object> syncProject(String nodeId, HttpServletRequest request) {
NodeModel nodeModel = nodeService.getByKey(nodeId);
Assert.notNull(nodeModel, "对应的节点不存在");
int count = projectInfoCacheService.delCache(nodeId, getRequest());
int count = projectInfoCacheService.delCache(nodeId, request);
String msg = projectInfoCacheService.syncExecuteNode(nodeModel);
return JsonMessage.success("主动清除:" + count + StrUtil.SPACE + msg);
}
@ -164,8 +152,7 @@ public class NodeProjectInfoController extends BaseServerController {
*/
@GetMapping(value = "project-sort-item", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId) {
HttpServletRequest request = getRequest();
public IJsonMessage<String> sortItem(@ValidatorItem String id, @ValidatorItem String method, String compareId, HttpServletRequest request) {
if (StrUtil.equalsIgnoreCase(method, "top")) {
projectInfoCacheService.sortToTop(id, request);
} else if (StrUtil.equalsIgnoreCase(method, "up")) {
@ -186,28 +173,28 @@ public class NodeProjectInfoController extends BaseServerController {
*/
@RequestMapping(value = "project-trigger-url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Map<String, String>> getTriggerUrl(String id, String rest) {
ProjectInfoCacheModel item = projectInfoCacheService.getByKey(id, getRequest());
public IJsonMessage<Map<String, String>> getTriggerUrl(String id, String rest, HttpServletRequest request) {
ProjectInfoCacheModel item = projectInfoCacheService.getByKey(id, request);
UserModel user = getUser();
ProjectInfoCacheModel updateItem;
if (StrUtil.isEmpty(item.getTriggerToken()) || StrUtil.isNotEmpty(rest)) {
updateItem = new ProjectInfoCacheModel();
updateItem.setId(id);
updateItem.setTriggerToken(triggerTokenLogServer.restToken(item.getTriggerToken(), projectInfoCacheService.typeName(),
item.getId(), user.getId()));
item.getId(), user.getId()));
projectInfoCacheService.updateById(updateItem);
} else {
updateItem = item;
}
Map<String, String> map = this.getBuildToken(updateItem);
Map<String, String> map = this.getBuildToken(updateItem, request);
return JsonMessage.success(StrUtil.isEmpty(rest) ? "ok" : "重置成功", map);
}
private Map<String, String> getBuildToken(ProjectInfoCacheModel item) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(getRequest(), ServerConst.PROXY_PATH);
private Map<String, String> getBuildToken(ProjectInfoCacheModel item, HttpServletRequest request) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(request, ServerConst.PROXY_PATH);
String url = ServerOpenApi.SERVER_PROJECT_TRIGGER_URL.
replace("{id}", item.getId()).
replace("{token}", item.getTriggerToken());
replace("{id}", item.getId()).
replace("{token}", item.getTriggerToken());
String triggerBuildUrl = String.format("/%s/%s", contextPath, url);
Map<String, String> map = new HashMap<>(10);
map.put("triggerUrl", FileUtil.normalize(triggerBuildUrl));

View File

@ -148,8 +148,8 @@ public class NodeUpdateController extends BaseServerController {
@SystemPermission
@Feature(method = MethodFeature.UPLOAD)
public IJsonMessage<String> uploadAgent(String sliceId,
Integer totalSlice,
String fileSumMd5) throws IOException {
Integer totalSlice,
String fileSumMd5) throws IOException {
File agentPath = serverConfig.getAgentPath();
File userTempPath = serverConfig.getUserTempPath();
@ -190,7 +190,7 @@ public class NodeUpdateController extends BaseServerController {
}
@GetMapping(value = "fast_install.json", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<JSONObject> fastInstall() {
public IJsonMessage<JSONObject> fastInstall(HttpServletRequest request) {
boolean beta = RemoteVersion.betaRelease();
InputStream inputStream = ExtConfigBean.getConfigResourceInputStream(beta ? "/fast-install-beta.json" : "/fast-install-release.json");
String json = IoUtil.read(inputStream, CharsetUtil.CHARSET_UTF_8);
@ -202,7 +202,7 @@ public class NodeUpdateController extends BaseServerController {
JSONArray jsonArray = JSONArray.parseArray(json);
jsonObject.put("shUrls", jsonArray);
//
String contextPath = UrlRedirectUtil.getHeaderProxyPath(getRequest(), ServerConst.PROXY_PATH);
String contextPath = UrlRedirectUtil.getHeaderProxyPath(request, ServerConst.PROXY_PATH);
String url = String.format("/%s/%s", contextPath, ServerOpenApi.RECEIVE_PUSH);
jsonObject.put("url", FileUtil.normalize(url));
return JsonMessage.success("", jsonObject);
@ -211,19 +211,21 @@ public class NodeUpdateController extends BaseServerController {
@GetMapping(value = "pull_fast_install_result.json", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<Collection<JSONObject>> pullFastInstallResult(String removeId) {
Collection<JSONObject> jsonObjects = NodeInfoController.listReceiveCache(removeId);
jsonObjects = jsonObjects.stream().map(jsonObject -> {
JSONObject clone = jsonObject.clone();
clone.remove("canUseNode");
return clone;
}).collect(Collectors.toList());
jsonObjects = jsonObjects.stream()
.map(jsonObject -> {
JSONObject clone = jsonObject.clone();
clone.remove("canUseNode");
return clone;
})
.collect(Collectors.toList());
return JsonMessage.success("", jsonObjects);
}
@GetMapping(value = "confirm_fast_install.json", produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<Collection<JSONObject>> confirmFastInstall(HttpServletRequest request,
@ValidatorItem String id,
@ValidatorItem String ip,
int port) {
@ValidatorItem String id,
@ValidatorItem String ip,
int port) {
JSONObject receiveCache = NodeInfoController.getReceiveCache(id);
Assert.notNull(receiveCache, "没有对应的缓存信息");
JSONArray jsonArray = receiveCache.getJSONArray("canUseNode");

View File

@ -23,6 +23,7 @@
package org.dromara.jpom.controller.node.manage.file;
import cn.keepbx.jpom.IJsonMessage;
import org.dromara.jpom.common.BaseServerController;
import org.dromara.jpom.common.forward.NodeForward;
import org.dromara.jpom.common.forward.NodeUrl;
@ -57,8 +58,8 @@ public class ProjectFileBackupController extends BaseServerController {
* @return list
*/
@RequestMapping(value = "list-backup", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String listBackup(String id) {
return NodeForward.request(getNode(), getRequest(), NodeUrl.MANAGE_FILE_BACKUP_LIST_BACKUP).toString();
public IJsonMessage<Object> listBackup(String id, HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.MANAGE_FILE_BACKUP_LIST_BACKUP);
}
/**
@ -70,8 +71,8 @@ public class ProjectFileBackupController extends BaseServerController {
* @return list
*/
@RequestMapping(value = "backup-item-files", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String backupItemFiles(String id, String path, @ValidatorItem String backupId) {
return NodeForward.request(getNode(), getRequest(), NodeUrl.MANAGE_FILE_BACKUP_LIST_ITEM_FILES).toString();
public IJsonMessage<Object> backupItemFiles(String id, String path, @ValidatorItem String backupId, HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.MANAGE_FILE_BACKUP_LIST_ITEM_FILES);
}
/**
@ -99,8 +100,8 @@ public class ProjectFileBackupController extends BaseServerController {
* @return msg
*/
@RequestMapping(value = "backup-delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String deleteFile(String id, @ValidatorItem String backupId, @ValidatorItem String filename, String levelName, HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.MANAGE_FILE_BACKUP_DELETE).toString();
public IJsonMessage<Object> deleteFile(String id, @ValidatorItem String backupId, @ValidatorItem String filename, String levelName, HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.MANAGE_FILE_BACKUP_DELETE);
}
/**
@ -114,7 +115,7 @@ public class ProjectFileBackupController extends BaseServerController {
* @return msg
*/
@RequestMapping(value = "backup-recover", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public String recoverFile(String id, @ValidatorItem String backupId, String type, String filename, String levelName, HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.MANAGE_FILE_BACKUP_RECOVER).toString();
public IJsonMessage<Object> recoverFile(String id, @ValidatorItem String backupId, String type, String filename, String levelName, HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.MANAGE_FILE_BACKUP_RECOVER);
}
}

View File

@ -66,8 +66,8 @@ public class ProjectFileControl extends BaseServerController {
*/
@RequestMapping(value = "getFileList", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(cls = ClassFeature.PROJECT_FILE, method = MethodFeature.LIST)
public IJsonMessage<Object> getFileList() {
return NodeForward.request(getNode(), getRequest(), NodeUrl.Manage_File_GetFileList);
public IJsonMessage<Object> getFileList(HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.Manage_File_GetFileList);
}
/**

View File

@ -60,7 +60,7 @@ public class LogBackController extends BaseServerController {
this.projectInfoCacheService = projectInfoCacheService;
}
@RequestMapping(value = "export.html", method = RequestMethod.GET)
@RequestMapping(value = "export", method = RequestMethod.GET)
@ResponseBody
@Feature(method = MethodFeature.DOWNLOAD)
public void export(HttpServletRequest request, HttpServletResponse response) {
@ -77,8 +77,8 @@ public class LogBackController extends BaseServerController {
@RequestMapping(value = "log-back-list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Feature(method = MethodFeature.LIST)
public IJsonMessage<JSONObject> logBackList() {
JSONObject jsonObject = NodeForward.requestData(getNode(), NodeUrl.Manage_Log_logBack, getRequest(), JSONObject.class);
public IJsonMessage<JSONObject> logBackList(HttpServletRequest request) {
JSONObject jsonObject = NodeForward.requestData(getNode(), NodeUrl.Manage_Log_logBack, request, JSONObject.class);
return JsonMessage.success("success", jsonObject);
}
@ -92,8 +92,8 @@ public class LogBackController extends BaseServerController {
@RequestMapping(value = "logBack_delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Feature(method = MethodFeature.DEL)
public String clear(HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.Manage_Log_logBack_delete).toString();
public IJsonMessage<Object> clear(HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.Manage_Log_logBack_delete);
}
@RequestMapping(value = "logSize", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ -111,7 +111,7 @@ public class LogBackController extends BaseServerController {
@RequestMapping(value = "resetLog", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Feature(method = MethodFeature.DEL)
public String resetLog() {
return NodeForward.request(getNode(), getRequest(), NodeUrl.Manage_Log_ResetLog).toString();
public IJsonMessage<Object> resetLog(HttpServletRequest request) {
return NodeForward.request(getNode(), request, NodeUrl.Manage_Log_ResetLog);
}
}

View File

@ -73,18 +73,6 @@ public class NodeScriptController extends BaseServerController {
this.triggerTokenLogServer = triggerTokenLogServer;
}
/**
* get script list
*
* @return json
* @author Hotstrip
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<PageResultDto<NodeScriptCacheModel>> scriptList(HttpServletRequest request) {
PageResultDto<NodeScriptCacheModel> pageResultDto = nodeScriptServer.listPageNode(request);
return JsonMessage.success("success", pageResultDto);
}
/**
* load node script list
* 加载节点脚本列表
@ -200,12 +188,12 @@ public class NodeScriptController extends BaseServerController {
} else {
updateInfo = item;
}
Map<String, String> map = this.getBuildToken(updateInfo);
Map<String, String> map = this.getBuildToken(updateInfo, request);
return JsonMessage.success(StrUtil.isEmpty(rest) ? "ok" : "重置成功", map);
}
private Map<String, String> getBuildToken(NodeScriptCacheModel item) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(getRequest(), ServerConst.PROXY_PATH);
private Map<String, String> getBuildToken(NodeScriptCacheModel item, HttpServletRequest request) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(request, ServerConst.PROXY_PATH);
String url = ServerOpenApi.NODE_SCRIPT_TRIGGER_URL.
replace("{id}", item.getId()).
replace("{token}", item.getTriggerToken());

View File

@ -66,8 +66,8 @@ public class NodeScriptLogController extends BaseServerController {
* @return json
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<PageResultDto<NodeScriptExecuteLogCacheModel>> scriptList() {
PageResultDto<NodeScriptExecuteLogCacheModel> pageResultDto = nodeScriptExecuteLogServer.listPageNode(getRequest());
public IJsonMessage<PageResultDto<NodeScriptExecuteLogCacheModel>> scriptList(HttpServletRequest request) {
PageResultDto<NodeScriptExecuteLogCacheModel> pageResultDto = nodeScriptExecuteLogServer.listPage(request);
return JsonMessage.success("", pageResultDto);
}
@ -78,9 +78,9 @@ public class NodeScriptLogController extends BaseServerController {
*/
@RequestMapping(value = "log", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public String log() {
public IJsonMessage<Object> log(HttpServletRequest request) {
NodeModel node = getNode();
return NodeForward.request(node, getRequest(), NodeUrl.SCRIPT_LOG).toString();
return NodeForward.request(node, request, NodeUrl.SCRIPT_LOG);
}
/**

View File

@ -66,8 +66,8 @@ public class LogReadController extends BaseServerController {
*/
@PostMapping(value = "list", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<LogReadModel>> list() {
PageResultDto<LogReadModel> pageResultDto = logReadServer.listPage(getRequest());
public IJsonMessage<PageResultDto<LogReadModel>> list(HttpServletRequest request) {
PageResultDto<LogReadModel> pageResultDto = logReadServer.listPage(request);
return JsonMessage.success("success", pageResultDto);
}
@ -79,8 +79,7 @@ public class LogReadController extends BaseServerController {
*/
@RequestMapping(value = "del.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<String> del(String id) {
HttpServletRequest request = getRequest();
public IJsonMessage<String> del(String id, HttpServletRequest request) {
int byKey = logReadServer.delByKey(id, request);
return JsonMessage.success("操作成功");
}
@ -95,7 +94,7 @@ public class LogReadController extends BaseServerController {
*/
@RequestMapping(value = "save.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<String> save(@RequestBody JSONObject jsonObject) {
public IJsonMessage<String> save(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
Assert.notNull(jsonObject, "请传入参数");
String id = jsonObject.getString("id");
String name = jsonObject.getString("name");
@ -115,7 +114,6 @@ public class LogReadController extends BaseServerController {
if (StrUtil.isEmpty(id)) {
logReadServer.insert(logReadModel);
} else {
HttpServletRequest request = getRequest();
logReadServer.updateById(logReadModel, request);
}
return JsonMessage.success("修改成功");
@ -136,12 +134,12 @@ public class LogReadController extends BaseServerController {
*/
@RequestMapping(value = "update-cache.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<String> updateCache(@RequestBody JSONObject jsonObject) {
public IJsonMessage<String> updateCache(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
Assert.notNull(jsonObject, "请传入参数");
String id = jsonObject.getString("id");
Assert.hasText(id, "请传入参数");
LogReadModel.CacheDta cacheDta = jsonObject.toJavaObject(LogReadModel.CacheDta.class);
HttpServletRequest request = getRequest();
LogReadModel logReadModel = new LogReadModel();
logReadModel.setId(id);
logReadModel.setCacheData(JSONArray.toJSONString(cacheDta));

View File

@ -36,6 +36,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* 分发日志
*
@ -56,8 +58,8 @@ public class OutGivingLogController extends BaseServerController {
@RequestMapping(value = "log_list_data.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<OutGivingLog>> listData() {
PageResultDto<OutGivingLog> pageResult = dbOutGivingLogService.listPage(getRequest());
public IJsonMessage<PageResultDto<OutGivingLog>> listData(HttpServletRequest request) {
PageResultDto<OutGivingLog> pageResult = dbOutGivingLogService.listPage(request);
return JsonMessage.success("获取成功", pageResult);
}
}

View File

@ -204,9 +204,10 @@ public class OutGivingProjectController extends BaseServerController {
String sliceId,
Integer totalSlice,
Integer nowSlice,
String fileSumMd5) throws IOException {
String fileSumMd5,
HttpServletRequest request) throws IOException {
// 状态判断
this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"));
this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"), request);
File userTempPath = serverConfig.getUserTempPath();
// 保存文件
this.uploadSharding(file, userTempPath.getAbsolutePath(), sliceId, totalSlice, nowSlice, fileSumMd5);
@ -230,8 +231,8 @@ public class OutGivingProjectController extends BaseServerController {
String selectProject,
String sliceId,
Integer totalSlice,
String fileSumMd5) throws IOException {
this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"));
String fileSumMd5, HttpServletRequest request) throws IOException {
this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"), request);
AfterOpt afterOpt1 = BaseEnum.getEnum(AfterOpt.class, Convert.toInt(afterOpt, 0));
Assert.notNull(afterOpt1, "请选择分发后的操作");
//
@ -268,8 +269,8 @@ public class OutGivingProjectController extends BaseServerController {
return JsonMessage.success("上传成功,开始分发!");
}
private OutGivingModel check(String id, BiConsumer<OutGivingModel.Status, OutGivingModel> consumer) {
OutGivingModel outGivingModel = outGivingServer.getByKey(id, getRequest());
private OutGivingModel check(String id, BiConsumer<OutGivingModel.Status, OutGivingModel> consumer, HttpServletRequest request) {
OutGivingModel outGivingModel = outGivingServer.getByKey(id, request);
Assert.notNull(outGivingModel, "上传失败,没有找到对应的分发项目");
// 检查状态
Integer statusCode = outGivingModel.getStatus();
@ -295,7 +296,7 @@ public class OutGivingProjectController extends BaseServerController {
HttpServletRequest request) {
Assert.hasText(url, "填写下载地址");
Assert.state(StrUtil.length(url) <= 200, "url 长度不能超过 200");
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"));
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"), request);
AfterOpt afterOpt1 = BaseEnum.getEnum(AfterOpt.class, Convert.toInt(afterOpt, 0));
Assert.notNull(afterOpt1, "请选择分发后的操作");
// 验证远程 地址
@ -332,7 +333,7 @@ public class OutGivingProjectController extends BaseServerController {
String selectProject,
HttpServletRequest request) {
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"));
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"), request);
AfterOpt afterOpt1 = BaseEnum.getEnum(AfterOpt.class, Convert.toInt(afterOpt, 0));
Assert.notNull(afterOpt1, "请选择分发后的操作");
@ -389,7 +390,7 @@ public class OutGivingProjectController extends BaseServerController {
String selectProject,
HttpServletRequest request) {
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"));
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"), request);
AfterOpt afterOpt1 = BaseEnum.getEnum(AfterOpt.class, Convert.toInt(afterOpt, 0));
Assert.notNull(afterOpt1, "请选择分发后的操作");
FileStorageModel storageModel = fileStorageService.getByKey(fileId, request);
@ -422,7 +423,7 @@ public class OutGivingProjectController extends BaseServerController {
String selectProject,
HttpServletRequest request) {
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"));
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status != OutGivingModel.Status.ING, "当前还在分发中,请等待分发结束"), request);
AfterOpt afterOpt1 = BaseEnum.getEnum(AfterOpt.class, Convert.toInt(afterOpt, 0));
Assert.notNull(afterOpt1, "请选择分发后的操作");
StaticFileStorageModel storageModel = staticFileStorageService.getByKey(fileId);
@ -475,8 +476,8 @@ public class OutGivingProjectController extends BaseServerController {
@PostMapping(value = "cancel", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EXECUTE)
public IJsonMessage<String> cancel(@ValidatorItem String id) {
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status == OutGivingModel.Status.ING, "当前状态不是分发中"));
public IJsonMessage<String> cancel(@ValidatorItem String id, HttpServletRequest request) {
OutGivingModel outGivingModel = this.check(id, (status, outGivingModel1) -> Assert.state(status == OutGivingModel.Status.ING, "当前状态不是分发中"), request);
OutGivingRun.cancel(outGivingModel.getId(), getUser());
//
return JsonMessage.success("取消成功");

View File

@ -106,15 +106,15 @@ public class OutGivingProjectEditController extends BaseServerController {
*/
@RequestMapping(value = "save_project", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<String> save(@ValidatorItem String id, String type) {
public IJsonMessage<String> save(@ValidatorItem String id, String type, HttpServletRequest request) {
if ("add".equalsIgnoreCase(type)) {
//boolean general = StringUtil.isGeneral(id, 2, 20);
//Assert.state(general, "分发id 不能为空并且长度在2-20英文字母 、数字和下划线)");
String checkId = StrUtil.replace(id, StrUtil.DASHED, StrUtil.UNDERLINE);
Validator.validateGeneral(checkId, 2, Const.ID_MAX_LEN, "分发id 不能为空并且长度在2-20英文字母 、数字和下划线)");
return addOutGiving(id);
return addOutGiving(id, request);
} else {
return updateGiving(id);
return updateGiving(id, request);
}
}
@ -126,8 +126,7 @@ public class OutGivingProjectEditController extends BaseServerController {
*/
@RequestMapping(value = "delete_project", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<String> delete(String id, String thorough) {
HttpServletRequest request = getRequest();
public IJsonMessage<String> delete(String id, String thorough, HttpServletRequest request) {
OutGivingModel outGivingModel = outGivingServer.getByKey(id, request);
Assert.notNull(outGivingModel, "没有对应的分发项目");
@ -159,7 +158,8 @@ public class OutGivingProjectEditController extends BaseServerController {
return JsonMessage.success("删除成功");
}
private IJsonMessage<String> addOutGiving(String id) {
private IJsonMessage<String> addOutGiving(String id, HttpServletRequest request) {
// 全局判断 id
OutGivingModel outGivingModel = outGivingServer.getByKey(id);
Assert.isNull(outGivingModel, "分发id已经存在啦");
@ -167,7 +167,7 @@ public class OutGivingProjectEditController extends BaseServerController {
outGivingModel.setOutGivingProject(true);
outGivingModel.setId(id);
//
List<Tuple> tuples = doData(outGivingModel, false);
List<Tuple> tuples = doData(outGivingModel, false, request);
outGivingServer.insert(outGivingModel);
IJsonMessage<String> error = saveNodeData(outGivingModel, tuples, false);
@ -175,10 +175,10 @@ public class OutGivingProjectEditController extends BaseServerController {
}
private IJsonMessage<String> updateGiving(String id) {
OutGivingModel outGivingModel = outGivingServer.getByKey(id, getRequest());
private IJsonMessage<String> updateGiving(String id, HttpServletRequest request) {
OutGivingModel outGivingModel = outGivingServer.getByKey(id, request);
Assert.notNull(outGivingModel, "没有找到对应的分发id");
List<Tuple> tuples = doData(outGivingModel, true);
List<Tuple> tuples = doData(outGivingModel, true, request);
outGivingServer.updateById(outGivingModel);
IJsonMessage<String> error = saveNodeData(outGivingModel, tuples, true);
@ -278,7 +278,7 @@ public class OutGivingProjectEditController extends BaseServerController {
* @param edit 是否为编辑模式
* @return String为有异常
*/
private JSONObject getDefData(OutGivingModel outGivingModel, boolean edit) {
private JSONObject getDefData(OutGivingModel outGivingModel, boolean edit, HttpServletRequest request) {
JSONObject defData = new JSONObject();
defData.put("id", outGivingModel.getId());
defData.put("name", outGivingModel.getName());
@ -299,7 +299,7 @@ public class OutGivingProjectEditController extends BaseServerController {
defData.put("dslContent", getParameter("dslContent"));
}
String whitelistDirectory = getParameter("whitelistDirectory");
ServerWhitelist configDeNewInstance = outGivingWhitelistService.getServerWhitelistData(getRequest());
ServerWhitelist configDeNewInstance = outGivingWhitelistService.getServerWhitelistData(request);
List<String> whitelistServerOutGiving = configDeNewInstance.getOutGiving();
Assert.state(AgentWhitelist.checkPath(whitelistServerOutGiving, whitelistDirectory), "请选择正确的项目路径,或者还没有配置授权");
@ -325,7 +325,7 @@ public class OutGivingProjectEditController extends BaseServerController {
* @param outGivingModel 分发实体
* @param edit 是否为编辑模式
*/
private List<Tuple> doData(OutGivingModel outGivingModel, boolean edit) {
private List<Tuple> doData(OutGivingModel outGivingModel, boolean edit, HttpServletRequest request) {
outGivingModel.setName(getParameter("name"));
outGivingModel.setGroup(getParameter("group"));
Assert.hasText(outGivingModel.getName(), "分发名称不能为空");
@ -336,7 +336,7 @@ public class OutGivingProjectEditController extends BaseServerController {
//
String nodeIdsStr = getParameter("nodeIds");
List<String> nodeIds = StrUtil.splitTrim(nodeIdsStr, StrUtil.COMMA);
//List<NodeModel> nodeModelList = nodeService.listByWorkspace(getRequest());
//List<NodeModel> nodeModelList = nodeService.listByWorkspace(request);
Assert.notEmpty(nodeIds, "没有任何节点信息");
//
@ -344,7 +344,7 @@ public class OutGivingProjectEditController extends BaseServerController {
AfterOpt afterOpt1 = BaseEnum.getEnum(AfterOpt.class, Convert.toInt(afterOpt, 0));
Assert.notNull(afterOpt1, "请选择分发后的操作");
outGivingModel.setAfterOpt(afterOpt1.getCode());
JSONObject defData = getDefData(outGivingModel, edit);
JSONObject defData = getDefData(outGivingModel, edit, request);
//
List<OutGivingModel> outGivingModels = outGivingServer.list();

View File

@ -96,8 +96,8 @@ public class ScriptController extends BaseServerController {
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<ScriptModel>> scriptList() {
PageResultDto<ScriptModel> pageResultDto = scriptServer.listPage(getRequest());
public IJsonMessage<PageResultDto<ScriptModel>> scriptList(HttpServletRequest request) {
PageResultDto<ScriptModel> pageResultDto = scriptServer.listPage(request);
return JsonMessage.success("success", pageResultDto);
}
@ -116,13 +116,13 @@ public class ScriptController extends BaseServerController {
@RequestMapping(value = "save.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<String> save(String id,
@ValidatorItem String context,
@ValidatorItem String name,
String autoExecCron,
String defArgs,
String description,
String nodeIds,
HttpServletRequest request) {
@ValidatorItem String context,
@ValidatorItem String name,
String autoExecCron,
String defArgs,
String description,
String nodeIds,
HttpServletRequest request) {
ScriptModel scriptModel = new ScriptModel();
scriptModel.setId(id);
scriptModel.setContext(context);
@ -269,8 +269,8 @@ public class ScriptController extends BaseServerController {
@GetMapping(value = "sync-to-workspace", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
@SystemPermission()
public IJsonMessage<String> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId) {
String nowWorkspaceId = nodeService.getCheckUserWorkspace(getRequest());
public IJsonMessage<String> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId, HttpServletRequest request) {
String nowWorkspaceId = nodeService.getCheckUserWorkspace(request);
//
scriptServer.checkUserWorkspace(toWorkspaceId);
scriptServer.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId);
@ -298,12 +298,12 @@ public class ScriptController extends BaseServerController {
} else {
updateInfo = item;
}
Map<String, String> map = this.getBuildToken(updateInfo);
Map<String, String> map = this.getBuildToken(updateInfo, request);
return JsonMessage.success(StrUtil.isEmpty(rest) ? "ok" : "重置成功", map);
}
private Map<String, String> getBuildToken(ScriptModel item) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(getRequest(), ServerConst.PROXY_PATH);
private Map<String, String> getBuildToken(ScriptModel item, HttpServletRequest request) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(request, ServerConst.PROXY_PATH);
String url = ServerOpenApi.SERVER_SCRIPT_TRIGGER_URL.
replace("{id}", item.getId()).
replace("{token}", item.getTriggerToken());

View File

@ -86,8 +86,8 @@ public class CommandInfoController extends BaseServerController {
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<CommandModel>> page() {
PageResultDto<CommandModel> page = commandService.listPage(getRequest());
public IJsonMessage<PageResultDto<CommandModel>> page(HttpServletRequest request) {
PageResultDto<CommandModel> page = commandService.listPage(request);
return JsonMessage.success("", page);
}
@ -149,12 +149,12 @@ public class CommandInfoController extends BaseServerController {
*/
@RequestMapping(value = "del", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<Object> del(String id) {
public IJsonMessage<Object> del(String id, HttpServletRequest request) {
File logFileDir = CommandExecLogModel.logFileDir(id);
boolean fastDel = CommandUtil.systemFastDel(logFileDir);
Assert.state(!fastDel, "清理日志文件失败");
//
HttpServletRequest request = getRequest();
commandService.delByKey(id, request);
commandExecLogService.delByWorkspace(request, entity -> entity.set("commandId", id));
return JsonMessage.success("操作成功");
@ -175,8 +175,8 @@ public class CommandInfoController extends BaseServerController {
@RequestMapping(value = "batch", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EXECUTE)
public IJsonMessage<String> batch(String id,
String params,
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "运行节点不能为空") String nodes) throws IOException {
String params,
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "运行节点不能为空") String nodes) throws IOException {
Assert.hasText(id, "请选择执行的命令");
Assert.hasText(nodes, "请选择执行节点");
String batchId = commandService.executeBatch(id, params, nodes);
@ -193,8 +193,8 @@ public class CommandInfoController extends BaseServerController {
@GetMapping(value = "sync-to-workspace", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
@SystemPermission()
public IJsonMessage<Object> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId) {
String nowWorkspaceId = nodeService.getCheckUserWorkspace(getRequest());
public IJsonMessage<Object> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId, HttpServletRequest request) {
String nowWorkspaceId = nodeService.getCheckUserWorkspace(request);
//
commandService.checkUserWorkspace(toWorkspaceId);
commandService.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId);
@ -209,8 +209,8 @@ public class CommandInfoController extends BaseServerController {
*/
@RequestMapping(value = "trigger-url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Map<String, String>> getTriggerUrl(String id, String rest) {
CommandModel item = commandService.getByKey(id, getRequest());
public IJsonMessage<Map<String, String>> getTriggerUrl(String id, String rest, HttpServletRequest request) {
CommandModel item = commandService.getByKey(id, request);
UserModel user = getUser();
CommandModel updateInfo;
if (StrUtil.isEmpty(item.getTriggerToken()) || StrUtil.isNotEmpty(rest)) {
@ -222,12 +222,12 @@ public class CommandInfoController extends BaseServerController {
} else {
updateInfo = item;
}
Map<String, String> map = this.getBuildToken(updateInfo);
Map<String, String> map = this.getBuildToken(updateInfo, request);
return JsonMessage.success(StrUtil.isEmpty(rest) ? "ok" : "重置成功", map);
}
private Map<String, String> getBuildToken(CommandModel item) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(getRequest(), ServerConst.PROXY_PATH);
private Map<String, String> getBuildToken(CommandModel item, HttpServletRequest request) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(request, ServerConst.PROXY_PATH);
String url = ServerOpenApi.SSH_COMMAND_TRIGGER_URL.
replace("{id}", item.getId()).
replace("{token}", item.getTriggerToken());

View File

@ -42,6 +42,7 @@ import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.List;
@ -70,8 +71,8 @@ public class CommandLogController extends BaseServerController {
*/
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<CommandExecLogModel>> page() {
PageResultDto<CommandExecLogModel> page = commandExecLogService.listPage(getRequest());
public IJsonMessage<PageResultDto<CommandExecLogModel>> page(HttpServletRequest request) {
PageResultDto<CommandExecLogModel> page = commandExecLogService.listPage(request);
return JsonMessage.success("", page);
}
@ -87,8 +88,8 @@ public class CommandLogController extends BaseServerController {
*/
@RequestMapping(value = "del", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<String> del(String id) {
CommandExecLogModel execLogModel = commandExecLogService.getByKey(id);
public IJsonMessage<String> del(String id, HttpServletRequest request) {
CommandExecLogModel execLogModel = commandExecLogService.getByKey(id, request);
Assert.notNull(execLogModel, "没有对应的记录");
File logFile = execLogModel.logFile();
boolean fastDel = CommandUtil.systemFastDel(logFile);
@ -122,8 +123,10 @@ public class CommandLogController extends BaseServerController {
*/
@GetMapping(value = "batch_list", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<List<CommandExecLogModel>> batchList(@ValidatorItem String commandId, @ValidatorItem String batchId) {
public IJsonMessage<List<CommandExecLogModel>> batchList(@ValidatorItem String commandId, @ValidatorItem String batchId, HttpServletRequest request) {
CommandExecLogModel commandExecLogModel = new CommandExecLogModel();
String workspace = commandExecLogService.getCheckUserWorkspace(request);
commandExecLogModel.setWorkspaceId(workspace);
commandExecLogModel.setCommandId(commandId);
commandExecLogModel.setBatchId(batchId);
List<CommandExecLogModel> commandExecLogModels = commandExecLogService.listByBean(commandExecLogModel);
@ -147,8 +150,8 @@ public class CommandLogController extends BaseServerController {
@RequestMapping(value = "log", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<JSONObject> log(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据") String id,
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "line") int line) {
CommandExecLogModel item = commandExecLogService.getByKey(id, getRequest());
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "line") int line, HttpServletRequest request) {
CommandExecLogModel item = commandExecLogService.getByKey(id, request);
Assert.notNull(item, "没有对应数据");
File file = item.logFile();
@ -178,8 +181,8 @@ public class CommandLogController extends BaseServerController {
@RequestMapping(value = "download_log", method = RequestMethod.GET)
@ResponseBody
@Feature(method = MethodFeature.DOWNLOAD)
public void downloadLog(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据") String logId, HttpServletResponse response) {
CommandExecLogModel item = commandExecLogService.getByKey(logId);
public void downloadLog(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据") String logId, HttpServletRequest request, HttpServletResponse response) {
CommandExecLogModel item = commandExecLogService.getByKey(logId, request);
Assert.notNull(item, "没有对应数据");
File logFile = item.logFile();
if (!FileUtil.exist(logFile)) {

View File

@ -86,9 +86,9 @@ public class LogManageController extends BaseServerController {
@RequestMapping(value = "log_del.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage<String> logData(String nodeId,
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "path错误") String path) {
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "path错误") String path, HttpServletRequest request) {
if (StrUtil.isNotEmpty(nodeId)) {
return NodeForward.request(getNode(), getRequest(), NodeUrl.DelSystemLog);
return NodeForward.request(getNode(), request, NodeUrl.DelSystemLog);
}
File file = FileUtil.file(LogbackConfig.getPath(), path);
// 判断修改时间

View File

@ -56,6 +56,7 @@ import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@ -138,8 +139,8 @@ public class WorkspaceController extends BaseServerController {
*/
@PostMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<WorkspaceModel>> list() {
PageResultDto<WorkspaceModel> listPage = workspaceService.listPage(getRequest());
public IJsonMessage<PageResultDto<WorkspaceModel>> list(HttpServletRequest request) {
PageResultDto<WorkspaceModel> listPage = workspaceService.listPage(request);
return JsonMessage.success("", listPage);
}

View File

@ -265,7 +265,7 @@ public class WorkspaceEnvVarController extends BaseServerController {
*/
@RequestMapping(value = "trigger-url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Map<String, String>> getTriggerUrl(@ValidatorItem String id, @ValidatorItem String workspaceId, String rest) {
public IJsonMessage<Map<String, String>> getTriggerUrl(@ValidatorItem String id, @ValidatorItem String workspaceId, String rest, HttpServletRequest request) {
workspaceEnvVarService.checkUserWorkspace(workspaceId);
WorkspaceEnvVarModel item = workspaceEnvVarService.getByKey(id);
Assert.notNull(item, "没有对应的环境变量");
@ -283,12 +283,12 @@ public class WorkspaceEnvVarController extends BaseServerController {
} else {
updateInfo = item;
}
Map<String, String> map = this.getBuildToken(updateInfo);
Map<String, String> map = this.getBuildToken(updateInfo, request);
return JsonMessage.success(StrUtil.isEmpty(rest) ? "ok" : "重置成功", map);
}
private Map<String, String> getBuildToken(WorkspaceEnvVarModel item) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(getRequest(), ServerConst.PROXY_PATH);
private Map<String, String> getBuildToken(WorkspaceEnvVarModel item, HttpServletRequest request) {
String contextPath = UrlRedirectUtil.getHeaderProxyPath(request, ServerConst.PROXY_PATH);
String url = ServerOpenApi.SERVER_ENV_VAR_TRIGGER_URL.
replace("{id}", item.getId()).
replace("{token}", item.getTriggerToken());

View File

@ -46,6 +46,7 @@ import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
@ -78,8 +79,8 @@ public class UserListController extends BaseServerController {
*/
@RequestMapping(value = "get_user_list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<UserModel>> getUserList() {
PageResultDto<UserModel> userModelPageResultDto = userService.listPage(getRequest());
public IJsonMessage<PageResultDto<UserModel>> getUserList(HttpServletRequest request) {
PageResultDto<UserModel> userModelPageResultDto = userService.listPage(request);
userModelPageResultDto.each(userModel -> {
boolean bindMfa = userService.hasBindMfa(userModel.getId());
if (bindMfa) {

View File

@ -48,6 +48,7 @@ import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@ -81,8 +82,8 @@ public class UserPermissionGroupController extends BaseServerController {
*/
@RequestMapping(value = "get-list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<UserPermissionGroupBean>> getUserList() {
PageResultDto<UserPermissionGroupBean> userModelPageResultDto = userPermissionGroupServer.listPage(getRequest());
public IJsonMessage<PageResultDto<UserPermissionGroupBean>> getUserList(HttpServletRequest request) {
PageResultDto<UserPermissionGroupBean> userModelPageResultDto = userPermissionGroupServer.listPage(request);
return new JsonMessage<>(200, "", userModelPageResultDto);
}
@ -106,11 +107,11 @@ public class UserPermissionGroupController extends BaseServerController {
@PostMapping(value = "edit", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<String> edit(String id,
@ValidatorItem String name,
String description,
String prohibitExecute,
String allowExecute,
@ValidatorItem String workspace) {
@ValidatorItem String name,
String description,
String prohibitExecute,
String allowExecute,
@ValidatorItem String workspace) {
UserPermissionGroupBean userPermissionGroupBean = new UserPermissionGroupBean();
userPermissionGroupBean.setName(name);
userPermissionGroupBean.setDescription(description);

View File

@ -126,7 +126,7 @@ public abstract class BaseSshFileController extends BaseServerController {
*/
protected abstract <T> T checkConfigPathChildren(String id, String allowPathParent, String nextPath, BiFunction<MachineSshModel, ItemConfig, T> function);
@RequestMapping(value = "download.html", method = RequestMethod.GET)
@RequestMapping(value = "download", method = RequestMethod.GET)
@Feature(method = MethodFeature.DOWNLOAD)
public void download(@ValidatorItem String id,
@ValidatorItem String allowPathParent,

View File

@ -82,8 +82,8 @@ public class NodeScriptTriggerApiController extends BaseJpomController {
* @return json
*/
@RequestMapping(value = ServerOpenApi.NODE_SCRIPT_TRIGGER_URL, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<JSONObject> trigger2(@PathVariable String id, @PathVariable String token) {
NodeScriptCacheModel item = nodeScriptServer.getByKey(id);
public IJsonMessage<JSONObject> trigger2(@PathVariable String id, @PathVariable String token, HttpServletRequest request) {
NodeScriptCacheModel item = nodeScriptServer.getByKey(id, request);
Assert.notNull(item, "没有对应数据");
Assert.state(StrUtil.equals(token, item.getTriggerToken()), "触发token错误,或者已经失效");
//
@ -95,7 +95,7 @@ public class NodeScriptTriggerApiController extends BaseJpomController {
NodeModel nodeModel = nodeService.getByKey(item.getNodeId());
JSONObject reqData = new JSONObject();
reqData.put("id", item.getScriptId());
reqData.put("params", JSONObject.toJSONString(ServletUtil.getParamMap(getRequest())));
reqData.put("params", JSONObject.toJSONString(ServletUtil.getParamMap(request)));
JsonMessage<String> jsonMessage = NodeForward.request(nodeModel, NodeUrl.SCRIPT_EXEC, reqData);
//
JSONObject jsonObject = new JSONObject();

View File

@ -96,7 +96,7 @@ public class ProjectTriggerApiController extends BaseJpomController {
//
NodeModel nodeModel = nodeService.getByKey(item.getNodeId());
return NodeForward.request(nodeModel, resolveAction,
"id", item.getProjectId());
"id", item.getProjectId(), "opt", action);
}
/**

View File

@ -84,8 +84,8 @@ public class ServerScriptTriggerApiController extends BaseJpomController {
* @return json
*/
@RequestMapping(value = ServerOpenApi.SERVER_SCRIPT_TRIGGER_URL, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<JSONObject> trigger2(@PathVariable String id, @PathVariable String token) {
ScriptModel item = scriptServer.getByKey(id);
public IJsonMessage<JSONObject> trigger2(@PathVariable String id, @PathVariable String token, HttpServletRequest request) {
ScriptModel item = scriptServer.getByKey(id, request);
Assert.notNull(item, "没有对应数据");
Assert.state(StrUtil.equals(token, item.getTriggerToken()), "触发token错误,或者已经失效");
//
@ -96,7 +96,7 @@ public class ServerScriptTriggerApiController extends BaseJpomController {
try {
BaseServerController.resetInfo(userModel);
// 解析参数
Map<String, String> paramMap = ServletUtil.getParamMap(getRequest());
Map<String, String> paramMap = ServletUtil.getParamMap(request);
Map<String, String> newParamMap = new HashMap<>(10);
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
String key = StrUtil.format("trigger_{}", entry.getKey());

View File

@ -31,23 +31,20 @@ import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.BaseServerController;
import org.dromara.jpom.common.Const;
import org.dromara.jpom.common.ServerConst;
import org.dromara.jpom.exception.AgentAuthorizeException;
import org.dromara.jpom.exception.AgentException;
import org.dromara.jpom.model.BaseNodeModel;
import org.dromara.jpom.model.PageResultDto;
import org.dromara.jpom.model.data.NodeModel;
import org.dromara.jpom.model.data.WorkspaceModel;
import org.dromara.jpom.model.user.UserModel;
import org.dromara.jpom.service.node.NodeService;
import org.dromara.jpom.service.system.WorkspaceService;
import org.dromara.jpom.exception.AgentException;
import org.dromara.jpom.exception.AgentAuthorizeException;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
@ -74,25 +71,18 @@ public abstract class BaseNodeService<T extends BaseNodeModel> extends BaseGloba
this.dataName = dataName;
}
public PageResultDto<T> listPageNode(HttpServletRequest request) {
// 验证工作空间权限
Map<String, String> paramMap = ServletUtil.getParamMap(request);
@Override
public List<T> listByWorkspace(HttpServletRequest request) {
String workspaceId = this.getCheckUserWorkspace(request);
// 验证节点
String nodeId = paramMap.get(BaseServerController.NODE_ID);
Assert.notNull(nodeId, "没有选择节点ID");
NodeService nodeService = SpringUtil.getBean(NodeService.class);
NodeModel nodeModel = nodeService.getByKey(nodeId);
Assert.notNull(nodeModel, "不存在对应的节点");
Assert.state(StrUtil.equals(workspaceId, nodeModel.getWorkspaceId()), "节点的工作空间和操作的工作空间补一致");
paramMap.remove("workspaceId");
paramMap.put("nodeId", nodeId);
paramMap.put("workspaceId:in", workspaceId + StrUtil.COMMA + ServerConst.WORKSPACE_GLOBAL);
return super.listPage(paramMap);
Map<String, String> paramMap = ServletUtil.getParamMap(request);
String nodeId = paramMap.get("nodeId");
Entity entity = Entity.create();
entity.set("workspaceId", CollUtil.newArrayList(workspaceId, ServerConst.WORKSPACE_GLOBAL));
Opt.ofBlankAble(nodeId).ifPresent(s -> entity.set("nodeId", s));
List<Entity> entities = super.queryList(entity);
return super.entityToBeanList(entities);
}
/**
* 同步所有节点的项目
*/

View File

@ -214,7 +214,7 @@ export function geteBuildHistory(params) {
* @param {*} logId
*/
export function downloadBuildLog(logId) {
return loadRouterBase("/build/history/download_log.html", {
return loadRouterBase("/build/history/download_log", {
logId: logId,
});
}
@ -224,7 +224,7 @@ export function downloadBuildLog(logId) {
* @param {*} logId
*/
export function downloadBuildFile(logId) {
return loadRouterBase("/build/history/download_file.html", {
return loadRouterBase("/build/history/download_file", {
logId: logId,
});
}

View File

@ -2,18 +2,6 @@ import axios from "./config";
/************************** */
/**
* script 列表
* @param {String} nodeId 节点 ID
*/
export function getScriptList(params) {
return axios({
url: "/node/script/list",
method: "post",
data: params,
});
}
/**
* script 服务端中的所有列表
*/

View File

@ -46,11 +46,14 @@ export function getRuningProjectInfo(params, noTip) {
* id: 项目 ID
* } params
*/
export function getProjectData(params) {
export function getProjectData(params, loading) {
return axios({
url: "/node/manage/getProjectData.json",
method: "post",
data: params,
headers: {
loading: loading === false ? "no" : "",
},
});
}
@ -98,6 +101,8 @@ export function editProject(params) {
logPath: params.logPath,
autoStart: params.autoStart,
dslContent: params.dslContent,
dslEnv: params.dslEnv,
linkId: params.linkId,
};
return axios({
url: "/node/manage/saveProject",
@ -294,7 +299,7 @@ export function getProjectLogSize(params) {
* } params
*/
export function downloadProjectLogFile(params) {
return loadRouterBase("/node/manage/log/export.html", params);
return loadRouterBase("/node/manage/log/export", params);
}
/**
@ -496,16 +501,22 @@ export function getProjectGroupAll() {
/**
* 所有的运行模式
*/
export const runModeList = ["Dsl", "ClassPath", "Jar", "JarWar", "JavaExtDirsCp", "File"];
export const runModeList = ["Dsl", "ClassPath", "Jar", "JarWar", "JavaExtDirsCp", "File", "Link"];
export const runModeObj = {
Dsl: "自定义脚本项目python、nodejs、go、接口探活、es【推荐】",
ClassPath: "Java 项目java -classpath",
Jar: "Java 项目java -jar xxx",
JavaExtDirsCp: "Java 项目java -Djava.ext.dirs=lib -cp conf:run.jar $MAIN_CLASS",
File: "静态文件项目(前端、日志等)",
JarWar: "Java 项目java -jar Springboot war【不推荐】",
};
export const runModeArray = [
{ name: "Dsl", desc: "自定义脚本项目python、nodejs、go、接口探活、es【推荐】" },
{ name: "ClassPath", desc: "Java 项目java -classpath" },
{ name: "Jar", desc: "Java 项目java -jar xxx" },
{ name: "JavaExtDirsCp", desc: "Java 项目java -Djava.ext.dirs=lib -cp conf:run.jar $MAIN_CLASS" },
{ name: "File", desc: "静态文件项目(前端、日志等)" },
{
name: "Link",
desc: "软链项目(类似于项目副本使用相关路径的文件)",
// 仅有节点有此项目(节点分发不支持)
onlyNode: true,
},
{ name: "JarWar", desc: "Java 项目java -jar Springboot war【不推荐】" },
];
/**
* java 项目的运行模式
@ -515,7 +526,7 @@ export const javaModes = ["ClassPath", "Jar", "JarWar", "JavaExtDirsCp"];
/**
* 有状态管理的运行模式
*/
export const noFileModes = ["ClassPath", "Jar", "JarWar", "JavaExtDirsCp", "Dsl"];
export const noFileModes = ["ClassPath", "Jar", "JarWar", "JavaExtDirsCp", "Dsl", "Link"];
/*
* 下载导入模板

View File

@ -47,15 +47,6 @@ export function getNodeListWithVersion(params) {
// });
// }
// 节点 + 项目列表
export function getNodeProjectList(params) {
return axios({
url: "/node/node_project_list",
method: "post",
data: params,
});
}
// 节点 + 项目列表
export function getProjectList(params, loading) {
return axios({
@ -69,11 +60,11 @@ export function getProjectList(params, loading) {
}
// 节点 + 项目列表
export function getProjectListAll() {
export function getProjectListAll(params) {
return axios({
url: "/node/project_list_all",
method: "get",
params: {},
params,
});
}

View File

@ -53,7 +53,7 @@ export function getFileList(baseUrl, params) {
* @param {id, path, name} params
*/
export function downloadFile(baseUrl, params) {
return loadRouterBase(baseUrl + "download.html", params);
return loadRouterBase(baseUrl + "download", params);
}
/**
@ -120,15 +120,15 @@ export function renameFileFolder(baseUrl, params) {
/**
* 修改文件权限
* @param {*} baseUrl
* @param {*} baseUrl
* @param {
* String id,
* String allowPathParent,
* String nextPath,
* String fileName,
* String permissionValue
* } params
* @returns
* } params
* @returns
*/
export function changeFilePermission(baseUrl, params) {
return axios({
@ -141,23 +141,23 @@ export function changeFilePermission(baseUrl, params) {
/**
* 权限字符串转权限对象
* @param {String} str "lrwxr-xr-x"
* @returns
* @returns
*/
export function parsePermissions(str) {
let permissions = {owner: {}, group: {}, others: {}};
let permissions = { owner: {}, group: {}, others: {} };
let chars = str.split('');
permissions.owner.read = (chars[1] === "r");
permissions.owner.write = (chars[2] === "w");
permissions.owner.execute = (chars[3] === "x");
let chars = str.split("");
permissions.owner.read = chars[1] === "r";
permissions.owner.write = chars[2] === "w";
permissions.owner.execute = chars[3] === "x";
permissions.group.read = (chars[4] === "r");
permissions.group.write = (chars[5] === "w");
permissions.group.execute = (chars[6] === "x");
permissions.group.read = chars[4] === "r";
permissions.group.write = chars[5] === "w";
permissions.group.execute = chars[6] === "x";
permissions.others.read = (chars[7] === "r");
permissions.others.write = (chars[8] === "w");
permissions.others.execute = (chars[9] === "x");
permissions.others.read = chars[7] === "r";
permissions.others.write = chars[8] === "w";
permissions.others.execute = chars[9] === "x";
return permissions;
}
@ -169,7 +169,7 @@ export function parsePermissions(str) {
* group: { read: false, write: false, execute: false, },
* others: { read: false, write: false, execute: false, },
* } permissions
* @returns
* @returns
*/
export function calcFilePermissionValue(permissions) {
let value = 0;

View File

@ -363,14 +363,14 @@
</template>
<a-select v-model="temp.runMode" placeholder="请选择运行方式">
<a-select-option v-for="(val, key) in runModeObj" :key="key">
<template v-if="val.indexOf('不推荐') > -1">
<a-select-option v-for="item in runModeArray.filter((item) => item.onlyNode !== true)" :key="item.name">
<template v-if="item.desc.indexOf('不推荐') > -1">
<s>
<b>[{{ key }}]</b> {{ val }}
<b>[{{ item.name }}]</b> {{ item.desc }}
</s>
</template>
<template v-else>
<b>[{{ key }}]</b> {{ val }}
<b>[{{ item.name }}]</b> {{ item.desc }}
</template>
</a-select-option>
</a-select>
@ -480,7 +480,7 @@
<template slot="title">
<ul>
<li>日志目录是指控制台日志存储目录</li>
<li>默认是在项目文件夹父级</li>
<li>默认是在插件端数据目录/${projectId}/${projectId}.log</li>
<li>可选择的列表和项目授权目录是一致的即相同配置</li>
</ul>
</template>
@ -488,7 +488,7 @@
</a-tooltip>
</template>
<a-select v-model="temp.logPath" placeholder="请选择日志目录">
<a-select-option key="" value="">默认是在项目文件夹父级</a-select-option>
<a-select-option key="" value="">默认是在插件端数据目录/${projectId}/${projectId}.log</a-select-option>
<a-select-option v-for="access in accessList" :key="access">{{ access }}</a-select-option>
</a-select>
</a-form-model-item>
@ -699,7 +699,7 @@ import {
cancelOutgiving,
} from "@/api/dispatch";
import { getNodeListAll, getProjectListAll } from "@/api/node";
import { getProjectData, javaModes, noFileModes, runModeObj, getProjectGroupAll } from "@/api/node-project";
import { getProjectData, javaModes, noFileModes, runModeArray, getProjectGroupAll } from "@/api/node-project";
import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, PROJECT_DSL_DEFATUL, randomStr, itemGroupBy, parseTime } from "@/utils/const";
import scriptPage from "@/pages/script/script-list";
import CustomSelect from "@/components/customSelect";
@ -722,7 +722,7 @@ export default {
statusMap,
javaModes,
noFileModes,
runModeObj,
runModeArray,
dispatchStatusMap,
PROJECT_DSL_DEFATUL,
list: [],

View File

@ -163,12 +163,12 @@ export default {
clearInterval(this.heart);
},
//
loadProject() {
loadProject(loading) {
const params = {
id: this.projectId,
nodeId: this.nodeId,
};
getProjectData(params).then((res) => {
getProjectData(params, loading).then((res) => {
if (res.code === 200) {
this.project = { ...this.project, ...res.data };
@ -218,6 +218,10 @@ export default {
// status
this.project = { ...this.project, status: true };
}
if (res.op === "reload") {
// reload
this.loadProject();
}
} else {
this.project = { ...this.project, status: false };
}

View File

@ -51,75 +51,78 @@
<a-icon v-show="temp.type !== 'edit'" type="question-circle" theme="filled" />
</a-tooltip>
</template>
<a-select v-model="temp.runMode" placeholder="请选择运行方式">
<a-select-option v-for="(val, key) in runModeObj" :key="key">
<template v-if="val.indexOf('不推荐') > -1">
<a-select v-model="temp.runMode" placeholder="请选择运行方式" @change="changeRunMode">
<a-select-option v-for="item in runModeArray" :key="item.name">
<template v-if="item.desc.indexOf('不推荐') > -1">
<s>
<b>[{{ key }}]</b> {{ val }}
<b>[{{ item.name }}]</b> {{ item.desc }}
</s>
</template>
<template v-else>
<b>[{{ key }}]</b> {{ val }}
<b>[{{ item.name }}]</b> {{ item.desc }}
</template>
</a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item prop="whitelistDirectory" class="jpom-node-project-whitelist">
<template slot="label">
<a-tooltip>
项目路径
<template slot="title">
<ul>
<li>授权路径是指项目文件存放到服务中的文件夹</li>
<li>可以到节点管理中的插件端配置=>授权配置修改</li>
<li>项目文件夹是项目实际存放的目录名称</li>
<li>项目文件会存放到 <br />&nbsp;&nbsp;<b>项目授权路径+项目文件夹</b></li>
</ul>
</template>
<a-icon v-show="temp.type !== 'edit'" type="question-circle" theme="filled" />
</a-tooltip>
</template>
<template #help>
需要提前为机器配置授权目录
<a-button
type="link"
size="small"
icon="info-circle"
@click="
() => {
configDir = true;
}
"
>
快速配置
</a-button>
</template>
<a-input-group compact>
<a-select style="width: 50%" v-model="temp.whitelistDirectory" placeholder="请选择项目授权路径">
<a-select-option v-for="access in accessList" :key="access">
<a-tooltip :title="access">{{ access }}</a-tooltip>
<template v-if="temp.runMode === 'Link'">
<a-form-model-item label="软链的项目" prop="linkId">
<a-select v-model="temp.linkId" placeholder="请选择软链的项目" @change="changeLinkId">
<a-select-option v-for="item in projectList" :key="item.projectId" :disabled="item.runMode === 'File' || item.runMode === 'Link'">
<template>
<b>[{{ item.runMode }}]</b> {{ item.name }}
</template>
</a-select-option>
</a-select>
<a-input style="width: 50%" v-model="temp.lib" placeholder="项目存储的文件夹" />
</a-input-group>
<template #extra>
<!-- <span class="lib-exist" v-show="temp.libExist">{{ temp.libExistMsg }}</span> -->
</template>
</a-form-model-item>
<!-- <a-form-model-item prop="lib">
</a-form-model-item>
</template>
<template v-else>
<a-form-model-item prop="whitelistDirectory">
<template slot="label">
项目文件夹
<a-tooltip v-show="temp.type !== 'edit'">
<a-tooltip>
项目路径
<template slot="title">
<ul></ul>
<ul>
<li>授权路径是指项目文件存放到服务中的文件夹</li>
<li>可以到节点管理中的插件端配置=>授权配置修改</li>
<li>项目文件夹是项目实际存放的目录名称</li>
<li>项目文件会存放到 <br />&nbsp;&nbsp;<b>项目授权路径+项目文件夹</b></li>
</ul>
</template>
<a-icon type="question-circle" theme="filled" />
<a-icon v-show="temp.type !== 'edit'" type="question-circle" theme="filled" />
</a-tooltip>
</template>
</a-form-model-item> -->
<a-form-model-item v-show="filePath !== ''" label="项目完整目录">
<a-alert :message="filePath" type="success" />
</a-form-model-item>
<template #help>
需要提前为机器配置授权目录
<a-button
type="link"
size="small"
icon="info-circle"
@click="
() => {
configDir = true;
}
"
>
快速配置
</a-button>
</template>
<a-input-group compact>
<a-select style="width: 50%" v-model="temp.whitelistDirectory" placeholder="请选择项目授权路径">
<a-select-option v-for="access in accessList" :key="access">
<a-tooltip :title="access">{{ access }}</a-tooltip>
</a-select-option>
</a-select>
<a-input style="width: 50%" v-model="temp.lib" placeholder="项目存储的文件夹" />
</a-input-group>
<template #extra>
<!-- <span class="lib-exist" v-show="temp.libExist">{{ temp.libExistMsg }}</span> -->
</template>
</a-form-model-item>
<a-form-model-item v-show="filePath !== ''" label="项目完整目录">
<a-alert :message="filePath" type="success" />
</a-form-model-item>
</template>
<a-form-model-item v-show="temp.runMode === 'Dsl'" prop="dslContent">
<template slot="label">
<a-tooltip>
@ -160,14 +163,14 @@
</a-tab-pane>
</a-tabs>
</a-form-model-item>
<a-form-model-item v-show="noFileModes.includes(temp.runMode)">
<a-form-model-item v-show="noFileModes.includes(temp.runMode) && temp.runMode !== 'Link'">
<template slot="label">
<a-tooltip>
日志目录
<template slot="title">
<ul>
<li>日志目录是指控制台日志存储目录</li>
<li>默认是在项目文件夹父级</li>
<li>默认是在插件端数据目录/${projectId}/${projectId}.log</li>
<li>可选择的列表和项目授权目录是一致的即相同配置</li>
</ul>
</template>
@ -175,23 +178,34 @@
</a-tooltip>
</template>
<a-select v-model="temp.logPath" placeholder="请选择项目授权路径">
<a-select-option key="" value="">默认是在项目文件夹父级</a-select-option>
<a-select-option key="" value="">默认是在插件端数据目录/${projectId}/${projectId}.log</a-select-option>
<a-select-option v-for="access in accessList" :key="access">{{ access }}</a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item label="Main Class" prop="mainClass" v-show="javaModes.includes(temp.runMode) && temp.runMode !== 'Jar'">
<a-form-model-item
label="Main Class"
prop="mainClass"
v-show="(javaModes.includes(temp.runMode) && temp.runMode !== 'Jar') || (javaModes.includes(linkProjectData.runMode) && linkProjectData.runMode !== 'Jar')"
>
<a-input v-model="temp.mainClass" placeholder="程序运行的 main 类(jar 模式运行可以不填)" />
</a-form-model-item>
<a-form-model-item label="JavaExtDirsCp" prop="javaExtDirsCp" v-show="javaModes.includes(temp.runMode) && temp.runMode === 'JavaExtDirsCp'">
<a-form-model-item
label="JavaExtDirsCp"
prop="javaExtDirsCp"
v-show="(javaModes.includes(temp.runMode) && temp.runMode === 'JavaExtDirsCp') || (javaModes.includes(linkProjectData.runMode) && linkProjectData.runMode === 'JavaExtDirsCp')"
>
<a-input v-model="temp.javaExtDirsCp" placeholder="-Dext.dirs=xxx: -cp xx 填写【xxx:xx】" />
</a-form-model-item>
<a-form-model-item label="JVM 参数" prop="jvm" v-show="javaModes.includes(temp.runMode)">
<a-form-model-item label="JVM 参数" prop="jvm" v-show="javaModes.includes(temp.runMode) || javaModes.includes(linkProjectData.runMode)">
<a-textarea v-model="temp.jvm" :auto-size="{ minRows: 3, maxRows: 3 }" placeholder="jvm参数,非必填.如:-Xms512m -Xmx512m" />
</a-form-model-item>
<a-form-model-item label="args 参数" prop="args" v-show="javaModes.includes(temp.runMode)">
<a-form-model-item label="args 参数" prop="args" v-show="javaModes.includes(temp.runMode) || javaModes.includes(linkProjectData.runMode)">
<a-textarea v-model="temp.args" :auto-size="{ minRows: 3, maxRows: 3 }" placeholder="Main 函数 args 参数,非必填. 如:--server.port=8080" />
</a-form-model-item>
<a-form-model-item v-if="temp.runMode === 'Dsl' || linkProjectData.runMode === 'Dsl'" prop="dslEnv" label="DSL环境变量">
<a-input v-model="temp.dslEnv" placeholder="DSL环境变量,如key1=values1&keyvalue2" />
</a-form-model-item>
<a-form-model-item prop="autoStart" v-show="noFileModes.includes(temp.runMode)">
<template slot="label">
@ -205,10 +219,8 @@
<a-switch v-model="temp.autoStart" checked-children="" un-checked-children="" />
插件端启动时自动检查项目如未启动将尝试启动
</a-form-model-item>
<a-form-model-item v-if="temp.runMode === 'Dsl'" prop="dslEnv" label="DSL环境变量">
<a-input v-model="temp.dslEnv" placeholder="DSL环境变量,如key1=values1&keyvalue2" />
</a-form-model-item>
<a-form-model-item prop="token" v-show="noFileModes.includes(temp.runMode)" class="jpom-node-project-token">
<a-form-model-item prop="token" v-show="noFileModes.includes(temp.runMode)">
<template slot="label">
<a-tooltip>
WebHooks
@ -224,9 +236,7 @@
</template>
<a-input v-model="temp.token" placeholder="项目启动,停止,重启,文件变动都将请求对应的地址,非必填GET请求" />
</a-form-model-item>
<a-form-model-item v-if="temp.log" v-show="temp.type === 'edit' && javaModes.includes(temp.runMode)" label="日志路径" prop="log">
<a-alert :message="temp.log" type="success" />
</a-form-model-item>
<a-form-model-item v-if="temp.runCommand" v-show="temp.type === 'edit' && javaModes.includes(temp.runMode)" label="运行命令" prop="runCommand">
<a-alert :message="temp.runCommand || '无'" type="success" />
</a-form-model-item>
@ -276,17 +286,8 @@ import codeEditor from "@/components/codeEditor";
import { PROJECT_DSL_DEFATUL, randomStr } from "@/utils/const";
import whiteList from "@/pages/node/node-layout/system/white-list.vue";
import {
editProject,
getProjectAccessList,
getProjectData,
javaModes,
// nodeJudgeLibExist,
runModeObj,
noFileModes,
runModeList,
getProjectGroupAll,
} from "@/api/node-project";
import { editProject, getProjectAccessList, getProjectData, javaModes, runModeArray, noFileModes, getProjectGroupAll } from "@/api/node-project";
import { getProjectListAll } from "@/api/node";
export default {
props: {
@ -309,8 +310,8 @@ export default {
return {
accessList: [],
groupList: [],
runModeObj,
runModeList,
runModeArray,
projectList: [],
javaModes,
noFileModes,
PROJECT_DSL_DEFATUL,
@ -324,6 +325,7 @@ export default {
whitelistDirectory: [{ required: true, message: "请选择项目授权路径", trigger: "blur" }],
lib: [{ required: true, message: "请输入项目文件夹", trigger: "blur" }],
},
linkProjectData: {},
};
},
computed: {
@ -368,6 +370,9 @@ export default {
this.temp = { ...this.temp, ...this.data, type: "add" };
}
}
if (this.temp.runMode === "Link") {
this.listProjectList();
}
});
} else {
//
@ -377,7 +382,30 @@ export default {
};
}
},
//
changeLinkId() {
this.linkProjectData = this.projectList.find((item) => item.projectId === this.temp.linkId) || {};
},
//
changeRunMode() {
if (this.temp.runMode === "Link") {
this.listProjectList();
}
},
//
listProjectList() {
if (this.projectList.length) {
return;
}
getProjectListAll({
nodeId: this.nodeId,
}).then((res) => {
if (res.code === 200) {
this.projectList = res.data || [];
this.changeLinkId();
}
});
},
//
loadAccesList() {
getProjectAccessList(this.nodeId).then((res) => {

View File

@ -314,8 +314,8 @@ export default {
},
data() {
return {
ZIP_ACCEPT: ZIP_ACCEPT,
noFileModes: noFileModes,
ZIP_ACCEPT,
noFileModes,
loading: false,
treeList: [],
fileList: [],

View File

@ -80,8 +80,8 @@
<a-icon type="fullscreen" />
</a-button>
</a-tooltip>
<a-tooltip slot="path" slot-scope="text, item" placement="topLeft" :title="item.whitelistDirectory + item.lib">
<span>{{ item.whitelistDirectory + item.lib }}</span>
<a-tooltip slot="path" slot-scope="text, item" placement="topLeft" :title="(item.whitelistDirectory || '') + (item.lib || '')">
<span>{{ (item.whitelistDirectory || "") + (item.lib || "") }}</span>
</a-tooltip>
<a-tooltip slot="tooltip" slot-scope="text" placement="topLeft" :title="text">
@ -412,10 +412,10 @@ export default {
projList: [],
projectStatusMap: {},
groupList: [],
runModeList: runModeList,
runModeList,
selectedRowKeys: [],
listQuery: Object.assign({}, PAGE_DEFAULT_LIST_QUERY),
noFileModes: noFileModes,
noFileModes,
nodeMap: {},
drawerTitle: "",
loading: true,