mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-12-04 12:58:24 +08:00
ssh 编辑文件准备
This commit is contained in:
parent
cf2ba2e088
commit
85b9ff705a
@ -1,12 +1,10 @@
|
||||
package io.jpom.controller.manage;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
@ -36,7 +34,6 @@ import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@ -61,28 +58,21 @@ public class ProjectFileControl extends BaseAgentController {
|
||||
public String getFileList(String id, String path) {
|
||||
// 查询项目路径
|
||||
ProjectInfoModel pim = projectInfoService.getItem(id);
|
||||
if (pim == null) {
|
||||
return JsonMessage.getString(500, "查询失败:项目不存在");
|
||||
}
|
||||
Assert.notNull(pim, "查询失败:项目不存在");
|
||||
String lib = pim.allLib();
|
||||
File fileDir = FileUtil.file(lib, StrUtil.emptyToDefault(path, FileUtil.FILE_SEPARATOR));
|
||||
if (!fileDir.exists()) {
|
||||
return JsonMessage.getString(500, "目录不存在");
|
||||
}
|
||||
Assert.state(FileUtil.exist(fileDir), "目录不存在");
|
||||
//
|
||||
File[] filesAll = fileDir.listFiles();
|
||||
if (filesAll == null) {
|
||||
return JsonMessage.getString(500, "目录是空");
|
||||
}
|
||||
Assert.notEmpty(filesAll, "目录是空");
|
||||
JSONArray arrayFile = FileUtils.parseInfo(filesAll, false, lib);
|
||||
AgentWhitelist whitelist = whitelistDirectoryService.getWhitelist();
|
||||
List<String> allowEditSuffix = whitelist.getAllowEditSuffix();
|
||||
if (CollUtil.isNotEmpty(allowEditSuffix)) {
|
||||
for (Object o : arrayFile) {
|
||||
JSONObject jsonObject = (JSONObject) o;
|
||||
String filename = jsonObject.getString("filename");
|
||||
jsonObject.put("textFileEdit", this.checkSilentFileSuffix(filename));
|
||||
}
|
||||
for (Object o : arrayFile) {
|
||||
JSONObject jsonObject = (JSONObject) o;
|
||||
String filename = jsonObject.getString("filename");
|
||||
jsonObject.put("textFileEdit", AgentWhitelist.checkSilentFileSuffix(whitelist.getAllowEditSuffix(), filename));
|
||||
}
|
||||
|
||||
return JsonMessage.getString(200, "查询成功", arrayFile);
|
||||
}
|
||||
|
||||
@ -119,7 +109,7 @@ public class ProjectFileControl extends BaseAgentController {
|
||||
try {
|
||||
CompressionFileUtil.unCompress(file, lib);
|
||||
} finally {
|
||||
if (!file.delete()) {
|
||||
if (!FileUtil.del(file)) {
|
||||
DefaultSystemLog.getLog().error("删除文件失败:" + file.getPath());
|
||||
}
|
||||
}
|
||||
@ -228,63 +218,6 @@ public class ProjectFileControl extends BaseAgentController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 静默判断是否可以编辑对应的文件
|
||||
*
|
||||
* @param filename 文件名
|
||||
* @return true 可以编辑
|
||||
*/
|
||||
private boolean checkSilentFileSuffix(String filename) {
|
||||
AgentWhitelist whitelist = whitelistDirectoryService.getWhitelist();
|
||||
if (whitelist == null) {
|
||||
return false;
|
||||
}
|
||||
List<String> allowEditSuffix = whitelist.getAllowEditSuffix();
|
||||
if (CollUtil.isEmpty(allowEditSuffix)) {
|
||||
return false;
|
||||
}
|
||||
Charset charset = this.parserFileSuffixMap(allowEditSuffix, filename);
|
||||
return charset != null;
|
||||
}
|
||||
|
||||
private Charset parserFileSuffixMap(List<String> allowEditSuffix, String filename) {
|
||||
Map<String, Charset> map = CollStreamUtil.toMap(allowEditSuffix, s -> {
|
||||
List<String> split = StrUtil.split(s, StrUtil.AT);
|
||||
return CollUtil.getFirst(split);
|
||||
}, s -> {
|
||||
List<String> split = StrUtil.split(s, StrUtil.AT);
|
||||
if (split.size() > 1) {
|
||||
String last = CollUtil.getLast(split);
|
||||
return CharsetUtil.charset(last);
|
||||
} else {
|
||||
return CharsetUtil.defaultCharset();
|
||||
}
|
||||
});
|
||||
Set<Map.Entry<String, Charset>> entries = map.entrySet();
|
||||
for (Map.Entry<String, Charset> entry : entries) {
|
||||
if (StrUtil.endWithIgnoreCase(filename, StrUtil.DOT + entry.getKey())) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件可以编辑的 文件编码格式
|
||||
*
|
||||
* @param filename 文件名
|
||||
* @return charset 不能编辑情况会抛出异常
|
||||
*/
|
||||
private Charset checkFileSuffix(String filename) {
|
||||
AgentWhitelist whitelist = whitelistDirectoryService.getWhitelist();
|
||||
List<String> allowEditSuffix = whitelist.getAllowEditSuffix();
|
||||
Assert.notEmpty(allowEditSuffix, "没有配置可允许编辑的后缀");
|
||||
Charset charset = this.parserFileSuffixMap(allowEditSuffix, filename);
|
||||
Assert.notNull(charset, "不允许编辑的文件后缀");
|
||||
return charset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 读取文件内容 (只能处理文本文件)
|
||||
*
|
||||
@ -297,7 +230,8 @@ public class ProjectFileControl extends BaseAgentController {
|
||||
ProjectInfoModel pim = getProjectInfoModel();
|
||||
filePath = StrUtil.emptyToDefault(filePath, File.separator);
|
||||
// 判断文件后缀
|
||||
Charset charset = this.checkFileSuffix(filename);
|
||||
AgentWhitelist whitelist = whitelistDirectoryService.getWhitelist();
|
||||
Charset charset = AgentWhitelist.checkFileSuffix(whitelist.getAllowEditSuffix(), filename);
|
||||
File file = FileUtil.file(pim.allLib(), filePath, filename);
|
||||
String ymlString = FileUtil.readString(file, charset);
|
||||
return JsonMessage.getString(200, "", ymlString);
|
||||
@ -316,7 +250,8 @@ public class ProjectFileControl extends BaseAgentController {
|
||||
ProjectInfoModel pim = getProjectInfoModel();
|
||||
filePath = StrUtil.emptyToDefault(filePath, File.separator);
|
||||
// 判断文件后缀
|
||||
Charset charset = this.checkFileSuffix(filename);
|
||||
AgentWhitelist whitelist = whitelistDirectoryService.getWhitelist();
|
||||
Charset charset = AgentWhitelist.checkFileSuffix(whitelist.getAllowEditSuffix(), filename);
|
||||
FileUtil.writeString(fileText, FileUtil.file(pim.allLib(), filePath, filename), charset);
|
||||
return JsonMessage.getString(200, "文件写入成功");
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ public class WhitelistDirectoryController extends BaseJpomController {
|
||||
//
|
||||
List<String> certificateList = AgentWhitelist.parseToList(certificate, "证书路径白名单不能为空");
|
||||
List<String> nList = AgentWhitelist.parseToList(nginx, "nginx路径白名单不能为空");
|
||||
List<String> allowEditSuffixList = AgentWhitelist.parseToList(allowEditSuffix, "运行编辑的文件后缀不能为空");
|
||||
List<String> allowRemoteDownloadHostList = AgentWhitelist.parseToList(allowRemoteDownloadHost, "运行远程下载的 host 不能配置为空");
|
||||
List<String> allowEditSuffixList = AgentWhitelist.parseToList(allowEditSuffix, "允许编辑的文件后缀不能为空");
|
||||
List<String> allowRemoteDownloadHostList = AgentWhitelist.parseToList(allowRemoteDownloadHost, "允许远程下载的 host 不能配置为空");
|
||||
return save(list, certificateList, nList, allowEditSuffixList, allowRemoteDownloadHostList).toString();
|
||||
}
|
||||
//
|
||||
|
@ -17,114 +17,117 @@ import java.io.File;
|
||||
*/
|
||||
public class FileUtils {
|
||||
|
||||
private static JSONObject fileToJson(File file) {
|
||||
JSONObject jsonObject = new JSONObject(6);
|
||||
if (file.isDirectory()) {
|
||||
jsonObject.put("isDirectory", true);
|
||||
long sizeFile = FileUtil.size(file);
|
||||
jsonObject.put("fileSize", FileUtil.readableFileSize(sizeFile));
|
||||
} else {
|
||||
jsonObject.put("fileSize", FileUtil.readableFileSize(file.length()));
|
||||
}
|
||||
jsonObject.put("filename", file.getName());
|
||||
long mTime = file.lastModified();
|
||||
jsonObject.put("modifyTimeLong", mTime);
|
||||
jsonObject.put("modifyTime", DateUtil.date(mTime).toString());
|
||||
return jsonObject;
|
||||
}
|
||||
private static JSONObject fileToJson(File file) {
|
||||
JSONObject jsonObject = new JSONObject(6);
|
||||
if (file.isDirectory()) {
|
||||
jsonObject.put("isDirectory", true);
|
||||
long sizeFile = FileUtil.size(file);
|
||||
jsonObject.put("fileSize", FileUtil.readableFileSize(sizeFile));
|
||||
} else {
|
||||
jsonObject.put("fileSize", FileUtil.readableFileSize(file.length()));
|
||||
}
|
||||
jsonObject.put("filename", file.getName());
|
||||
long mTime = file.lastModified();
|
||||
jsonObject.put("modifyTimeLong", mTime);
|
||||
jsonObject.put("modifyTime", DateUtil.date(mTime).toString());
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件信息解析排序
|
||||
*
|
||||
* @param files 文件数组
|
||||
* @param time 是否安装时间排序
|
||||
* @param startPath 开始路径
|
||||
* @return 排序后的json
|
||||
*/
|
||||
public static JSONArray parseInfo(File[] files, boolean time, String startPath) {
|
||||
int size = files.length;
|
||||
JSONArray arrayFile = new JSONArray(size);
|
||||
for (File file : files) {
|
||||
JSONObject jsonObject = FileUtils.fileToJson(file);
|
||||
//
|
||||
if (startPath != null) {
|
||||
String levelName = StringUtil.delStartPath(file, startPath, false);
|
||||
jsonObject.put("levelName", levelName);
|
||||
}
|
||||
//
|
||||
arrayFile.add(jsonObject);
|
||||
}
|
||||
arrayFile.sort((o1, o2) -> {
|
||||
JSONObject jsonObject1 = (JSONObject) o1;
|
||||
JSONObject jsonObject2 = (JSONObject) o2;
|
||||
if (time) {
|
||||
return jsonObject2.getLong("modifyTimeLong").compareTo(jsonObject1.getLong("modifyTimeLong"));
|
||||
}
|
||||
return jsonObject1.getString("filename").compareTo(jsonObject2.getString("filename"));
|
||||
});
|
||||
final int[] i = {0};
|
||||
arrayFile.forEach(o -> {
|
||||
JSONObject jsonObject = (JSONObject) o;
|
||||
jsonObject.put("index", ++i[0]);
|
||||
});
|
||||
return arrayFile;
|
||||
}
|
||||
/**
|
||||
* 对文件信息解析排序
|
||||
*
|
||||
* @param files 文件数组
|
||||
* @param time 是否安装时间排序
|
||||
* @param startPath 开始路径
|
||||
* @return 排序后的json
|
||||
*/
|
||||
public static JSONArray parseInfo(File[] files, boolean time, String startPath) {
|
||||
if (files == null) {
|
||||
return new JSONArray();
|
||||
}
|
||||
int size = files.length;
|
||||
JSONArray arrayFile = new JSONArray(size);
|
||||
for (File file : files) {
|
||||
JSONObject jsonObject = FileUtils.fileToJson(file);
|
||||
//
|
||||
if (startPath != null) {
|
||||
String levelName = StringUtil.delStartPath(file, startPath, false);
|
||||
jsonObject.put("levelName", levelName);
|
||||
}
|
||||
//
|
||||
arrayFile.add(jsonObject);
|
||||
}
|
||||
arrayFile.sort((o1, o2) -> {
|
||||
JSONObject jsonObject1 = (JSONObject) o1;
|
||||
JSONObject jsonObject2 = (JSONObject) o2;
|
||||
if (time) {
|
||||
return jsonObject2.getLong("modifyTimeLong").compareTo(jsonObject1.getLong("modifyTimeLong"));
|
||||
}
|
||||
return jsonObject1.getString("filename").compareTo(jsonObject2.getString("filename"));
|
||||
});
|
||||
final int[] i = {0};
|
||||
arrayFile.forEach(o -> {
|
||||
JSONObject jsonObject = (JSONObject) o;
|
||||
jsonObject.put("index", ++i[0]);
|
||||
});
|
||||
return arrayFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断路径是否满足jdk 条件
|
||||
*
|
||||
* @param path 路径
|
||||
* @return 判断存在java文件
|
||||
*/
|
||||
public static boolean isJdkPath(String path) {
|
||||
String fileName = getJdkJavaPath(path, false);
|
||||
File newPath = new File(fileName);
|
||||
return newPath.exists() && newPath.isFile();
|
||||
}
|
||||
/**
|
||||
* 判断路径是否满足jdk 条件
|
||||
*
|
||||
* @param path 路径
|
||||
* @return 判断存在java文件
|
||||
*/
|
||||
public static boolean isJdkPath(String path) {
|
||||
String fileName = getJdkJavaPath(path, false);
|
||||
File newPath = new File(fileName);
|
||||
return newPath.exists() && newPath.isFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取java 文件路径
|
||||
*
|
||||
* @param path path
|
||||
* @param w 是否使用javaw
|
||||
* @return 完整路径
|
||||
*/
|
||||
public static String getJdkJavaPath(String path, boolean w) {
|
||||
String fileName;
|
||||
if (SystemUtil.getOsInfo().isWindows()) {
|
||||
fileName = w ? "javaw.exe" : "java.exe";
|
||||
} else {
|
||||
fileName = w ? "javaw" : "java";
|
||||
}
|
||||
File newPath = FileUtil.file(path, "bin", fileName);
|
||||
return FileUtil.getAbsolutePath(newPath);
|
||||
}
|
||||
/**
|
||||
* 获取java 文件路径
|
||||
*
|
||||
* @param path path
|
||||
* @param w 是否使用javaw
|
||||
* @return 完整路径
|
||||
*/
|
||||
public static String getJdkJavaPath(String path, boolean w) {
|
||||
String fileName;
|
||||
if (SystemUtil.getOsInfo().isWindows()) {
|
||||
fileName = w ? "javaw.exe" : "java.exe";
|
||||
} else {
|
||||
fileName = w ? "javaw" : "java";
|
||||
}
|
||||
File newPath = FileUtil.file(path, "bin", fileName);
|
||||
return FileUtil.getAbsolutePath(newPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jdk 版本
|
||||
*
|
||||
* @param path jdk 路径
|
||||
* @return 获取成功返回版本号
|
||||
*/
|
||||
public static String getJdkVersion(String path) {
|
||||
String newPath = getJdkJavaPath(path, false);
|
||||
if (path.contains(StrUtil.SPACE)) {
|
||||
newPath = String.format("\"%s\"", newPath);
|
||||
}
|
||||
String command = CommandUtil.execSystemCommand(newPath + " -version");
|
||||
String[] split = StrUtil.splitToArray(command, StrUtil.LF);
|
||||
if (split == null || split.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
String[] strings = StrUtil.splitToArray(split[0], "\"");
|
||||
if (strings == null || strings.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
return strings[1];
|
||||
}
|
||||
/**
|
||||
* 获取jdk 版本
|
||||
*
|
||||
* @param path jdk 路径
|
||||
* @return 获取成功返回版本号
|
||||
*/
|
||||
public static String getJdkVersion(String path) {
|
||||
String newPath = getJdkJavaPath(path, false);
|
||||
if (path.contains(StrUtil.SPACE)) {
|
||||
newPath = String.format("\"%s\"", newPath);
|
||||
}
|
||||
String command = CommandUtil.execSystemCommand(newPath + " -version");
|
||||
String[] split = StrUtil.splitToArray(command, StrUtil.LF);
|
||||
if (split == null || split.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
String[] strings = StrUtil.splitToArray(split[0], "\"");
|
||||
if (strings == null || strings.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
return strings[1];
|
||||
}
|
||||
|
||||
|
||||
public static String getJarSeparator() {
|
||||
return SystemUtil.getOsInfo().isWindows() ? ";" : ":";
|
||||
}
|
||||
public static String getJarSeparator() {
|
||||
return SystemUtil.getOsInfo().isWindows() ? ";" : ":";
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package io.jpom.model.data;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.text.StrSplitter;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@ -12,10 +14,8 @@ import io.jpom.system.ExtConfigBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 白名单
|
||||
@ -205,4 +205,60 @@ public class AgentWhitelist extends BaseJsonModel {
|
||||
Assert.notEmpty(list, errorMsg);
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件可以编辑的 文件编码格式
|
||||
*
|
||||
* @param filename 文件名
|
||||
* @return charset 不能编辑情况会抛出异常
|
||||
*/
|
||||
public static Charset checkFileSuffix(List<String> allowEditSuffix, String filename) {
|
||||
Assert.notEmpty(allowEditSuffix, "没有配置可允许编辑的后缀");
|
||||
Charset charset = AgentWhitelist.parserFileSuffixMap(allowEditSuffix, filename);
|
||||
Assert.notNull(charset, "不允许编辑的文件后缀");
|
||||
return charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 静默判断是否可以编辑对应的文件
|
||||
*
|
||||
* @param filename 文件名
|
||||
* @return true 可以编辑
|
||||
*/
|
||||
public static boolean checkSilentFileSuffix(List<String> allowEditSuffix, String filename) {
|
||||
if (CollUtil.isEmpty(allowEditSuffix)) {
|
||||
return false;
|
||||
}
|
||||
Charset charset = AgentWhitelist.parserFileSuffixMap(allowEditSuffix, filename);
|
||||
return charset != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件名 和 可以配置列表 获取编码格式
|
||||
*
|
||||
* @param allowEditSuffix 允许编辑的配置
|
||||
* @param filename 文件名
|
||||
* @return 没有匹配到 返回 null,没有配置编码格式即使用系统默认编码格式
|
||||
*/
|
||||
public static Charset parserFileSuffixMap(List<String> allowEditSuffix, String filename) {
|
||||
Map<String, Charset> map = CollStreamUtil.toMap(allowEditSuffix, s -> {
|
||||
List<String> split = StrUtil.split(s, StrUtil.AT);
|
||||
return CollUtil.getFirst(split);
|
||||
}, s -> {
|
||||
List<String> split = StrUtil.split(s, StrUtil.AT);
|
||||
if (split.size() > 1) {
|
||||
String last = CollUtil.getLast(split);
|
||||
return CharsetUtil.charset(last);
|
||||
} else {
|
||||
return CharsetUtil.defaultCharset();
|
||||
}
|
||||
});
|
||||
Set<Map.Entry<String, Charset>> entries = map.entrySet();
|
||||
for (Map.Entry<String, Charset> entry : entries) {
|
||||
if (StrUtil.endWithIgnoreCase(filename, StrUtil.DOT + entry.getKey())) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import com.jcraft.jsch.Session;
|
||||
import io.jpom.common.BaseServerController;
|
||||
import io.jpom.common.interceptor.OptLog;
|
||||
import io.jpom.model.BaseModel;
|
||||
import io.jpom.model.data.AgentWhitelist;
|
||||
import io.jpom.model.data.NodeModel;
|
||||
import io.jpom.model.data.SshModel;
|
||||
import io.jpom.model.log.SshTerminalExecuteLog;
|
||||
@ -27,6 +28,7 @@ import io.jpom.service.dblog.SshTerminalExecuteLogService;
|
||||
import io.jpom.service.node.ssh.SshService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@ -112,21 +114,20 @@ public class SshController extends BaseServerController {
|
||||
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "port错误") int port,
|
||||
String charset, String fileDirs,
|
||||
String id, String type, String notAllowedCommand) {
|
||||
// 优先判断参数 如果是 password 在修改时可以不填写
|
||||
if (connectType == SshModel.ConnectType.PASS && StrUtil.isEmpty(password) && "add".equals(type)) {
|
||||
return JsonMessage.getString(405, "请填写登录密码");
|
||||
}
|
||||
if (connectType == SshModel.ConnectType.PUBKEY && StrUtil.isEmpty(privateKey)) {
|
||||
return JsonMessage.getString(405, "请填写证书内容");
|
||||
}
|
||||
SshModel sshModel;
|
||||
if ("edit".equals(type)) {
|
||||
sshModel = sshService.getItem(id);
|
||||
if (sshModel == null) {
|
||||
return JsonMessage.getString(500, "不存在对应ssh");
|
||||
// 优先判断参数 如果是 password 在修改时可以不填写
|
||||
boolean add = "add".equals(type);
|
||||
if (add) {
|
||||
if (connectType == SshModel.ConnectType.PASS && StrUtil.isEmpty(password)) {
|
||||
return JsonMessage.getString(405, "请填写登录密码");
|
||||
}
|
||||
if (connectType == SshModel.ConnectType.PUBKEY && StrUtil.isEmpty(privateKey)) {
|
||||
return JsonMessage.getString(405, "请填写证书内容");
|
||||
}
|
||||
} else {
|
||||
sshModel = new SshModel();
|
||||
} else {
|
||||
sshModel = sshService.getItem(id);
|
||||
Assert.notNull(sshModel, "不存在对应ssh");
|
||||
}
|
||||
// 目录
|
||||
if (StrUtil.isEmpty(fileDirs)) {
|
||||
@ -152,7 +153,10 @@ public class SshController extends BaseServerController {
|
||||
sshModel.setName(name);
|
||||
sshModel.setNotAllowedCommand(notAllowedCommand);
|
||||
sshModel.setConnectType(connectType);
|
||||
|
||||
// 获取允许编辑的后缀
|
||||
String allowEditSuffix = getParameter("allowEditSuffix");
|
||||
List<String> allowEditSuffixList = AgentWhitelist.parseToList(allowEditSuffix, "允许编辑的文件后缀不能为空");
|
||||
sshModel.setAllowEditSuffix(allowEditSuffixList);
|
||||
try {
|
||||
Charset.forName(charset);
|
||||
sshModel.setCharset(charset);
|
||||
|
@ -19,6 +19,7 @@ import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.jcraft.jsch.SftpException;
|
||||
import io.jpom.common.BaseServerController;
|
||||
import io.jpom.model.data.AgentWhitelist;
|
||||
import io.jpom.model.data.SshModel;
|
||||
import io.jpom.plugin.ClassFeature;
|
||||
import io.jpom.plugin.Feature;
|
||||
@ -188,6 +189,7 @@ public class SshFileController extends BaseServerController {
|
||||
private JSONArray listDir(SshModel sshModel, String path, String children) throws SftpException {
|
||||
Session session = null;
|
||||
ChannelSftp channel = null;
|
||||
List<String> allowEditSuffix = sshModel.getAllowEditSuffix();
|
||||
try {
|
||||
session = SshService.getSession(sshModel);
|
||||
channel = (ChannelSftp) JschUtil.openChannel(session, ChannelType.SFTP);
|
||||
@ -201,28 +203,31 @@ public class SshFileController extends BaseServerController {
|
||||
}
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (ChannelSftp.LsEntry lsEntry : vector) {
|
||||
if (StrUtil.DOT.equals(lsEntry.getFilename()) || StrUtil.DOUBLE_DOT.equals(lsEntry.getFilename())) {
|
||||
String filename = lsEntry.getFilename();
|
||||
if (StrUtil.DOT.equals(filename) || StrUtil.DOUBLE_DOT.equals(filename)) {
|
||||
continue;
|
||||
}
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("name", lsEntry.getFilename());
|
||||
jsonObject.put("name", filename);
|
||||
jsonObject.put("id", IdUtil.fastSimpleUUID());
|
||||
int mTime = lsEntry.getAttrs().getMTime();
|
||||
String format = DateUtil.format(DateUtil.date(mTime * 1000L), DatePattern.NORM_DATETIME_MINUTE_PATTERN);
|
||||
jsonObject.put("modifyTime", format);
|
||||
if (lsEntry.getAttrs().isDir()) {
|
||||
jsonObject.put("dir", true);
|
||||
jsonObject.put("title", lsEntry.getFilename());
|
||||
jsonObject.put("title", filename);
|
||||
} else {
|
||||
jsonObject.put("title", lsEntry.getFilename());
|
||||
jsonObject.put("title", filename);
|
||||
long fileSize = lsEntry.getAttrs().getSize();
|
||||
jsonObject.put("size", FileUtil.readableFileSize(fileSize));
|
||||
// 允许编辑
|
||||
jsonObject.put("textFileEdit", AgentWhitelist.checkSilentFileSuffix(allowEditSuffix, filename));
|
||||
}
|
||||
//
|
||||
if (StrUtil.isEmpty(children)) {
|
||||
jsonObject.put("parentDir", lsEntry.getFilename());
|
||||
jsonObject.put("parentDir", filename);
|
||||
} else {
|
||||
jsonObject.put("parentDir", FileUtil.normalize(StrUtil.format("{}/{}", children, lsEntry.getFilename())));
|
||||
jsonObject.put("parentDir", FileUtil.normalize(StrUtil.format("{}/{}", children, filename)));
|
||||
}
|
||||
jsonArray.add(jsonObject);
|
||||
}
|
||||
|
@ -46,6 +46,11 @@ public class SshModel extends BaseModel {
|
||||
*/
|
||||
private String notAllowedCommand;
|
||||
|
||||
/**
|
||||
* 运行编辑的后缀文件
|
||||
*/
|
||||
private List<String> allowEditSuffix;
|
||||
|
||||
public String getNotAllowedCommand() {
|
||||
return notAllowedCommand;
|
||||
}
|
||||
@ -158,6 +163,14 @@ public class SshModel extends BaseModel {
|
||||
return charset;
|
||||
}
|
||||
|
||||
public List<String> getAllowEditSuffix() {
|
||||
return allowEditSuffix;
|
||||
}
|
||||
|
||||
public void setAllowEditSuffix(List<String> allowEditSuffix) {
|
||||
this.allowEditSuffix = allowEditSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否包含禁止命令
|
||||
*
|
||||
|
@ -45,7 +45,8 @@ export function editSsh(params) {
|
||||
privateKey: params.privateKey,
|
||||
charset: params.charset,
|
||||
fileDirs: params.fileDirs,
|
||||
notAllowedCommand: params.notAllowedCommand
|
||||
notAllowedCommand: params.notAllowedCommand,
|
||||
allowEditSuffix: params.allowEditSuffix,
|
||||
}
|
||||
return axios({
|
||||
url: '/node/ssh/save.json',
|
||||
|
@ -34,7 +34,7 @@
|
||||
<span>{{ text }}</span>
|
||||
</a-tooltip>
|
||||
<template slot="operation" slot-scope="text, record">
|
||||
<a-button type="primary" @click="handlePreview(record)">查看</a-button>
|
||||
<a-button type="primary" :disabled="!record.textFileEdit" @click="handlePreview(record)">编辑</a-button>
|
||||
<a-button type="primary" @click="handleDownload(record)">下载</a-button>
|
||||
<a-button type="danger" @click="handleDelete(record)">删除</a-button>
|
||||
</template>
|
||||
|
@ -85,6 +85,15 @@
|
||||
<a-form-model-item label="禁止命令" prop="notAllowedCommand">
|
||||
<a-textarea v-model="temp.notAllowedCommand" :auto-size="{ minRows: 3, maxRows: 5 }" placeholder="禁止命令是不允许在终端执行的名,多个逗号隔开" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="文件后缀" prop="suffix">
|
||||
<a-input
|
||||
v-model="temp.allowEditSuffix"
|
||||
type="textarea"
|
||||
:rows="5"
|
||||
style="resize: none"
|
||||
placeholder="请输入允许编辑文件的后缀及文件编码,不设置编码则默认取系统编码,示例:设置编码:txt@utf-8, 不设置编码:txt"
|
||||
/>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-modal>
|
||||
<!-- 安装节点 -->
|
||||
|
Loading…
Reference in New Issue
Block a user