diff --git a/CHANGELOG.md b/CHANGELOG.md index 68c7e82c6..35cbafe27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ 8. Jpom 数据路径默认为程序运行的路径(感谢@〓下页) 9. 首页进程监听表格显示端口号(感谢@洋芋) 10. 保存时检查Oss信息是否正确 +11. Jpom管理命令新增判断`JAVA_HOME`环境变量 ### 解决BUG、优化功能 @@ -23,6 +24,7 @@ 4. 优化未加载到tools.jar的提示(感谢@№譜樋) 5. 构建按钮移动到文件管理页面中 6. 优化nginx列表显示数据、取消nginx快捷配置 +7. 证书管理页面交互优化 ----------------------------------------------------------- diff --git a/src/main/java/cn/keepbx/jpom/common/BaseOperService.java b/src/main/java/cn/keepbx/jpom/common/BaseOperService.java index 652f2a417..1c6903b4c 100644 --- a/src/main/java/cn/keepbx/jpom/common/BaseOperService.java +++ b/src/main/java/cn/keepbx/jpom/common/BaseOperService.java @@ -38,6 +38,15 @@ public abstract class BaseOperService extends BaseDataService { */ public abstract void addItem(T t); + /** + * 修改实体 + * + * @param t 实体 + * @return false 修改失败 + * @throws Exception 异常 + */ + public abstract boolean updateItem(T t) throws Exception; + protected JSONArray formatToArray(JSONObject jsonObject) { if (jsonObject == null) { return new JSONArray(); diff --git a/src/main/java/cn/keepbx/jpom/controller/LoginControl.java b/src/main/java/cn/keepbx/jpom/controller/LoginControl.java index e5567a77c..9e1bba7a9 100644 --- a/src/main/java/cn/keepbx/jpom/controller/LoginControl.java +++ b/src/main/java/cn/keepbx/jpom/controller/LoginControl.java @@ -178,7 +178,7 @@ public class LoginControl extends BaseController { return JsonMessage.getString(rCode, "登录失败,请输入正确的密码和账号,多次失败将锁定账号"); } } finally { - userService.updateUser(userModel); + userService.updateItem(userModel); } } } diff --git a/src/main/java/cn/keepbx/jpom/controller/manage/BuildController.java b/src/main/java/cn/keepbx/jpom/controller/manage/BuildController.java index 8c974ed48..6854f6c10 100644 --- a/src/main/java/cn/keepbx/jpom/controller/manage/BuildController.java +++ b/src/main/java/cn/keepbx/jpom/controller/manage/BuildController.java @@ -86,7 +86,7 @@ public class BuildController extends BaseController { ZipUtil.unzip(file, lib); // 修改使用状态 projectInfoModel.setUseLibDesc("build"); - projectInfoService.updateProject(projectInfoModel); + projectInfoService.updateItem(projectInfoModel); String result = commandService.execCommand(CommandService.CommandOp.restart, projectInfoModel); return JsonMessage.getString(200, "安装成功,已自动重启,当前状态是:" + result); } diff --git a/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java b/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java index 3c43d0490..39dc9baad 100644 --- a/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java +++ b/src/main/java/cn/keepbx/jpom/controller/manage/EditProjectController.java @@ -236,7 +236,7 @@ public class EditProjectController extends BaseController { exits.setToken(projectInfo.getToken()); // moveTo(exits, projectInfo); - projectInfoService.updateProject(exits); + projectInfoService.updateItem(exits); return JsonMessage.getString(200, "修改成功"); } catch (Exception e) { DefaultSystemLog.ERROR().error(e.getMessage(), e); diff --git a/src/main/java/cn/keepbx/jpom/controller/manage/file/ProjectFileControl.java b/src/main/java/cn/keepbx/jpom/controller/manage/file/ProjectFileControl.java index 00cc03006..7dbb3d394 100644 --- a/src/main/java/cn/keepbx/jpom/controller/manage/file/ProjectFileControl.java +++ b/src/main/java/cn/keepbx/jpom/controller/manage/file/ProjectFileControl.java @@ -143,7 +143,7 @@ public class ProjectFileControl extends BaseController { } // 修改使用状态 pim.setUseLibDesc("upload"); - projectInfoService.updateProject(pim); + projectInfoService.updateItem(pim); return JsonMessage.getString(200, "上传成功"); } diff --git a/src/main/java/cn/keepbx/jpom/controller/system/ssl/CertificateController.java b/src/main/java/cn/keepbx/jpom/controller/system/ssl/CertificateController.java index df2b8e403..7928cd8c4 100644 --- a/src/main/java/cn/keepbx/jpom/controller/system/ssl/CertificateController.java +++ b/src/main/java/cn/keepbx/jpom/controller/system/ssl/CertificateController.java @@ -13,8 +13,10 @@ import cn.keepbx.jpom.model.CertModel; import cn.keepbx.jpom.model.UserModel; import cn.keepbx.jpom.service.system.CertService; import cn.keepbx.jpom.service.system.WhitelistDirectoryService; +import cn.keepbx.jpom.system.ConfigBean; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @@ -24,7 +26,11 @@ import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** * 证书管理 @@ -49,87 +55,166 @@ public class CertificateController extends BaseController { /** - * 新增证书 + * 保存证书 + * + * @return json */ - @RequestMapping(value = "/addCertificate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @RequestMapping(value = "/saveCertificate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody - public String addCertificate() { - try { - CertModel certModel = getCertModel(); - certService.addItem(certModel); - } catch (Exception e) { - DefaultSystemLog.ERROR().error("证书文件", e); - return JsonMessage.getString(400, e.getMessage()); - } - return JsonMessage.getString(200, "上传成功"); - } + public String saveCertificate() { - /** - * 修改证书 - */ - @RequestMapping(value = "/updateCertificate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) - @ResponseBody - public String updateCertificate() { + String data = getParameter("data"); + JSONObject jsonObject = JSONObject.parseObject(data); + String type = jsonObject.getString("type"); + String id = jsonObject.getString("id"); try { - CertModel certModel = getCertModel(); - boolean b = certService.updateCert(certModel); - if (!b) { - return JsonMessage.getString(400, "修改失败"); + CertModel certModel; + if ("add".equalsIgnoreCase(type)) { + if (certService.getItem(id) != null) { + return JsonMessage.getString(405, "证书id已经存在啦"); + } + certModel = new CertModel(); + String error = getCertModel(certModel, jsonObject); + if (error != null) { + return error; + } + if (!hasFile()) { + return JsonMessage.getString(405, "请选择证书包文件"); + } + error = getCertFile(certModel, true); + if (error != null) { + return error; + } + certService.addItem(certModel); + } else { + certModel = certService.getItem(id); + if (certModel == null) { + return JsonMessage.getString(404, "没有找到对应证书文件"); + } + String name = jsonObject.getString("name"); + if (StrUtil.isEmpty(name)) { + return JsonMessage.getString(400, "请填写证书名称"); + } + certModel.setName(name); + if (ServletFileUpload.isMultipartContent(getRequest()) && hasFile()) { + String error = getCertFile(certModel, false); + if (error != null) { + return error; + } + } + if (!certService.updateItem(certModel)) { + return JsonMessage.getString(406, "修改失败"); + } } } catch (Exception e) { DefaultSystemLog.ERROR().error("证书文件", e); return JsonMessage.getString(400, e.getMessage()); } - return JsonMessage.getString(200, "修改成功"); + return JsonMessage.getString(200, "提交成功"); } + /** * 获取证书信息 + * + * @param certModel 实体 + * @return 错误消息 */ - private CertModel getCertModel() throws Exception { - String id = getParameter("id"); - String path = getParameter("path"); - String name = getParameter("name"); + private String getCertModel(CertModel certModel, JSONObject jsonObject) { + String id = jsonObject.getString("id"); + String path = jsonObject.getString("path"); + String name = jsonObject.getString("name"); if (StrUtil.isEmpty(id)) { - throw new RuntimeException("证书id异常"); + return JsonMessage.getString(400, "请填写证书id"); } if (Validator.isChinese(id)) { - throw new RuntimeException("证书id不能使用中文"); + return JsonMessage.getString(400, "证书id不能使用中文"); } if (StrUtil.isEmpty(name)) { - throw new RuntimeException("请填写证书名称"); + return JsonMessage.getString(400, "请填写证书名称"); } if (!whitelistDirectoryService.checkCertificateDirectory(path)) { - throw new RuntimeException("请选择正确的项目路径,或者还没有配置白名单"); + return JsonMessage.getString(400, "请选择正确的项目路径,或者还没有配置白名单"); } - String temporary = path + "/" + id + "/"; - File file = FileUtil.file(temporary); - if (!file.exists()) { - boolean mkdirs = file.mkdirs(); - if (!mkdirs) { - throw new RuntimeException("创建" + path + "目录失败,请手动创建"); - } - } - MultipartFileBuilder cert = createMultipart().addFieldName("cert").setSavePath(temporary).setUseOriginalFilename(true); - String certPath = cert.save(); - - MultipartFileBuilder key = createMultipart().addFieldName("key").setSavePath(temporary).setUseOriginalFilename(true); - String keyPath = key.save(); - //解析证书 - JSONObject jsonObject = CertModel.decodeCert(certPath, keyPath); - if (jsonObject == null) { - throw new RuntimeException("解析证书失败"); - } - CertModel certModel = new CertModel(); certModel.setId(id); certModel.setWhitePath(path); - certModel.setCert(certPath); - certModel.setKey(keyPath); certModel.setName(name); - certModel.setDomain(jsonObject.getString("domain")); - certModel.setExpirationTime(jsonObject.getLongValue("expirationTime")); - certModel.setEffectiveTime(jsonObject.getLongValue("effectiveTime")); - return certModel; + return null; + } + + private String getCertFile(CertModel certModel, boolean add) throws IOException { + String certPath = null; + String pemPath = null, keyPath = null; + try { + String path = ConfigBean.getInstance().getTempPathName(); + MultipartFileBuilder cert = createMultipart().addFieldName("file").setSavePath(path); + certPath = cert.save(); + ZipFile zipFile = new ZipFile(certPath); + Enumeration zipEntryEnumeration = zipFile.entries(); + + while (zipEntryEnumeration.hasMoreElements()) { + ZipEntry zipEntry = zipEntryEnumeration.nextElement(); + if (zipEntry.isDirectory()) { + continue; + } + String keyName = zipEntry.getName(); + if (pemPath == null && StrUtil.endWith(keyName, ".pem", true)) { + String filePathItem = String.format("%s/%s/%s", path, certModel.getId(), keyName); + InputStream inputStream = zipFile.getInputStream(zipEntry); + FileUtil.writeFromStream(inputStream, filePathItem); + pemPath = filePathItem; + } + // + if (keyPath == null && StrUtil.endWith(keyName, ".key", true)) { + String filePathItem = String.format("%s/%s/%s", path, certModel.getId(), keyName); + InputStream inputStream = zipFile.getInputStream(zipEntry); + FileUtil.writeFromStream(inputStream, filePathItem); + keyPath = filePathItem; + } + if (pemPath != null && keyPath != null) { + break; + } + } + if (pemPath == null || keyPath == null) { + return JsonMessage.getString(405, "证书包中文件不完整,需要包含key、pem"); + } + JSONObject jsonObject = CertModel.decodeCert(pemPath, keyPath); + if (jsonObject == null) { + return JsonMessage.getString(405, "解析证书失败"); + } + String domain = jsonObject.getString("domain"); + if (add) { + List array = certService.list(); + if (array != null) { + for (CertModel certModel1 : array) { + if (StrUtil.emptyToDefault(domain, "").equals(certModel1.getDomain())) { + return JsonMessage.getString(405, "证书的域名已经存在啦"); + } + } + } + } else { + if (!StrUtil.emptyToDefault(domain, "").equals(certModel.getDomain())) { + return JsonMessage.getString(405, "新证书的域名不一致"); + } + } + // 移动位置 + String temporary = certModel.getWhitePath() + "/" + certModel.getId() + "/"; + File pemFile = FileUtil.file(temporary + certModel.getId() + ".pem"); + File keyFile = FileUtil.file(temporary + certModel.getId() + ".key"); + FileUtil.move(FileUtil.file(pemPath), pemFile, true); + FileUtil.move(FileUtil.file(keyPath), keyFile, true); + certModel.setCert(pemFile.getAbsolutePath()); + certModel.setKey(keyFile.getAbsolutePath()); + // + certModel.setDomain(domain); + certModel.setExpirationTime(jsonObject.getLongValue("expirationTime")); + certModel.setEffectiveTime(jsonObject.getLongValue("effectiveTime")); + } finally { + if (certPath != null) { + FileUtil.del(certPath); + } + } + return null; } @@ -173,18 +258,14 @@ public class CertificateController extends BaseController { @RequestMapping(value = "/export", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @ResponseBody public String export(String id) { - try { - CertModel item = certService.getItem(id); - if (null == item) { - return JsonMessage.getString(400, "导出失败"); - } - String parent = FileUtil.file(item.getCert()).getParent(); - File zip = ZipUtil.zip(parent); - ServletUtil.write(getResponse(), zip); - FileUtil.del(zip); - } catch (IOException e) { + CertModel item = certService.getItem(id); + if (null == item) { return JsonMessage.getString(400, "导出失败"); } + String parent = FileUtil.file(item.getCert()).getParent(); + File zip = ZipUtil.zip(parent); + ServletUtil.write(getResponse(), zip); + FileUtil.del(zip); return JsonMessage.getString(400, "导出成功"); } } diff --git a/src/main/java/cn/keepbx/jpom/controller/user/UserInfoController.java b/src/main/java/cn/keepbx/jpom/controller/user/UserInfoController.java index edf2189eb..628adb9e0 100644 --- a/src/main/java/cn/keepbx/jpom/controller/user/UserInfoController.java +++ b/src/main/java/cn/keepbx/jpom/controller/user/UserInfoController.java @@ -54,7 +54,7 @@ public class UserInfoController extends BaseController { return JsonMessage.getString(500, "旧密码不正确!"); } userModel.setPassword(newPwd); - if (!userService.updateUser(userModel)) { + if (!userService.updateItem(userModel)) { return JsonMessage.getString(500, "修改失败!"); } // 如果修改成功,则销毁会话 @@ -84,7 +84,7 @@ public class UserInfoController extends BaseController { UserModel userModel = getUser(); userModel = userService.getItem(userModel.getId()); userModel.setName(name); - if (userService.updateUser(userModel)) { + if (userService.updateItem(userModel)) { setSessionAttribute(LoginInterceptor.SESSION_NAME, userModel); return JsonMessage.getString(200, "修改成功"); } @@ -245,7 +245,7 @@ public class UserInfoController extends BaseController { if (msg != null) { return msg; } - boolean b = userService.updateUser(userModel); + boolean b = userService.updateItem(userModel); if (b) { return JsonMessage.getString(200, "修改成功"); } @@ -270,7 +270,7 @@ public class UserInfoController extends BaseController { return JsonMessage.getString(400, "修改失败:-1"); } userModel.unLock(); - boolean b = userService.updateUser(userModel); + boolean b = userService.updateItem(userModel); if (b) { return JsonMessage.getString(200, "解锁成功"); } diff --git a/src/main/java/cn/keepbx/jpom/model/CertModel.java b/src/main/java/cn/keepbx/jpom/model/CertModel.java index 706f2f8ed..d4bb8f8a1 100644 --- a/src/main/java/cn/keepbx/jpom/model/CertModel.java +++ b/src/main/java/cn/keepbx/jpom/model/CertModel.java @@ -112,7 +112,7 @@ public class CertModel extends BaseModel { // 数据持久化到文件中 CertService certService = SpringUtil.getBean(CertService.class); - certService.updateCert(this); + certService.updateItem(this); } } diff --git a/src/main/java/cn/keepbx/jpom/service/manage/CommandService.java b/src/main/java/cn/keepbx/jpom/service/manage/CommandService.java index 37360dc5b..efe139fb5 100644 --- a/src/main/java/cn/keepbx/jpom/service/manage/CommandService.java +++ b/src/main/java/cn/keepbx/jpom/service/manage/CommandService.java @@ -76,7 +76,7 @@ public class CommandService { ProjectInfoModel modify = projectInfoService.getItem(projectInfoModel.getId()); modify.setRunLibDesc(projectInfoModel.getUseLibDesc()); try { - projectInfoService.updateProject(modify); + projectInfoService.updateItem(modify); } catch (Exception ignored) { } } diff --git a/src/main/java/cn/keepbx/jpom/service/manage/ProjectInfoService.java b/src/main/java/cn/keepbx/jpom/service/manage/ProjectInfoService.java index 72bd88971..cdea00d15 100644 --- a/src/main/java/cn/keepbx/jpom/service/manage/ProjectInfoService.java +++ b/src/main/java/cn/keepbx/jpom/service/manage/ProjectInfoService.java @@ -77,9 +77,11 @@ public class ProjectInfoService extends BaseOperService { * * @param projectInfo 项目信息 */ - public void updateProject(ProjectInfoModel projectInfo) throws Exception { + @Override + public boolean updateItem(ProjectInfoModel projectInfo) throws Exception { projectInfo.setModifyTime(DateUtil.now()); updateJson(ConfigBean.PROJECT, projectInfo.toJson()); + return true; } diff --git a/src/main/java/cn/keepbx/jpom/service/manage/ProjectRecoverService.java b/src/main/java/cn/keepbx/jpom/service/manage/ProjectRecoverService.java index 05f169e1c..10dc65c2d 100644 --- a/src/main/java/cn/keepbx/jpom/service/manage/ProjectRecoverService.java +++ b/src/main/java/cn/keepbx/jpom/service/manage/ProjectRecoverService.java @@ -55,4 +55,8 @@ public class ProjectRecoverService extends BaseOperService return getJsonObjectById(ConfigBean.PROJECT_RECOVER, id, ProjectRecoverModel.class); } + @Override + public boolean updateItem(ProjectRecoverModel projectRecoverModel) throws Exception { + return false; + } } diff --git a/src/main/java/cn/keepbx/jpom/service/system/CertService.java b/src/main/java/cn/keepbx/jpom/service/system/CertService.java index ed87f1f09..74f1c6e57 100644 --- a/src/main/java/cn/keepbx/jpom/service/system/CertService.java +++ b/src/main/java/cn/keepbx/jpom/service/system/CertService.java @@ -11,7 +11,6 @@ import com.alibaba.fastjson.JSONObject; import org.springframework.stereotype.Service; import java.io.File; -import java.io.IOException; import java.util.List; /** @@ -47,10 +46,11 @@ public class CertService extends BaseOperService { } @Override - public CertModel getItem(String id) throws IOException { + public CertModel getItem(String id) { return getJsonObjectById(ConfigBean.CERT, id, CertModel.class); } + /** * 删除证书 * @@ -84,7 +84,8 @@ public class CertService extends BaseOperService { * * @param certModel 证书 */ - public boolean updateCert(CertModel certModel) { + @Override + public boolean updateItem(CertModel certModel) { try { updateJson(ConfigBean.CERT, certModel.toJson()); } catch (Exception e) { diff --git a/src/main/java/cn/keepbx/jpom/service/system/NginxService.java b/src/main/java/cn/keepbx/jpom/service/system/NginxService.java index 2102087fd..e792161fb 100644 --- a/src/main/java/cn/keepbx/jpom/service/system/NginxService.java +++ b/src/main/java/cn/keepbx/jpom/service/system/NginxService.java @@ -93,6 +93,11 @@ public class NginxService extends BaseOperService { } + @Override + public boolean updateItem(Object o) throws Exception { + return false; + } + /** * 获取域名 * diff --git a/src/main/java/cn/keepbx/jpom/service/user/UserService.java b/src/main/java/cn/keepbx/jpom/service/user/UserService.java index f1299d9fa..d888b4d42 100644 --- a/src/main/java/cn/keepbx/jpom/service/user/UserService.java +++ b/src/main/java/cn/keepbx/jpom/service/user/UserService.java @@ -120,7 +120,7 @@ public class UserService extends BaseOperService { * @return 用户信息 */ @Override - public UserModel getItem(String userId) throws IOException { + public UserModel getItem(String userId) { return getJsonObjectById(ConfigBean.USER, userId, UserModel.class); } @@ -155,7 +155,8 @@ public class UserService extends BaseOperService { * * @return String */ - public boolean updateUser(UserModel userModel) { + @Override + public boolean updateItem(UserModel userModel) { try { updateJson(ConfigBean.USER, userModel.toJson()); return true; diff --git a/src/main/java/cn/keepbx/jpom/socket/LogWebSocketHandle.java b/src/main/java/cn/keepbx/jpom/socket/LogWebSocketHandle.java index 764511827..10eeb65e7 100644 --- a/src/main/java/cn/keepbx/jpom/socket/LogWebSocketHandle.java +++ b/src/main/java/cn/keepbx/jpom/socket/LogWebSocketHandle.java @@ -167,7 +167,7 @@ public class LogWebSocketHandle { // 记录操作人 projectInfoModel = projectInfoService.getItem(projectId); projectInfoModel.logModifyUser(userModel); - projectInfoService.updateProject(projectInfoModel); + projectInfoService.updateItem(projectInfoModel); } } // diff --git a/src/main/resources/vm/system/certificate.vm b/src/main/resources/vm/system/certificate.vm index 4ac2d48b9..8769867ce 100644 --- a/src/main/resources/vm/system/certificate.vm +++ b/src/main/resources/vm/system/certificate.vm @@ -6,7 +6,7 @@ 证书管理