mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-12-02 03:48:05 +08:00
基本功能完成
This commit is contained in:
parent
e349e0503f
commit
839b1d21dd
@ -26,6 +26,11 @@ public abstract class BaseAgentController extends BaseJpomController {
|
||||
return StrUtil.emptyToDefault(name, StrUtil.DASHED);
|
||||
}
|
||||
|
||||
protected boolean isSystemUser() {
|
||||
String val = ServletUtil.getHeaderIgnoreCase(getRequest(), "Jpom-Server-SystemUserRole");
|
||||
return Boolean.valueOf(val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取拦截器中缓存的项目信息
|
||||
|
@ -0,0 +1,27 @@
|
||||
package cn.keepbx.jpom.controller;
|
||||
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.keepbx.jpom.common.BaseAgentController;
|
||||
import cn.keepbx.jpom.model.system.JpomManifest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author jiangzeyin
|
||||
* @date 2019/4/17
|
||||
*/
|
||||
@RestController
|
||||
public class IndexController extends BaseAgentController {
|
||||
|
||||
@RequestMapping(value = {"index", "", "index.html", "/"}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String index() {
|
||||
return "Jpom-Agent";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "info", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String info() {
|
||||
return JsonMessage.getString(200, "", JpomManifest.getInstance());
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
package cn.keepbx.jpom.controller.monitor;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.keepbx.jpom.common.BaseAgentController;
|
||||
import cn.keepbx.jpom.common.commander.AbstractProjectCommander;
|
||||
import cn.keepbx.jpom.common.commander.AbstractSystemCommander;
|
||||
import cn.keepbx.jpom.model.system.NetstatModel;
|
||||
import cn.keepbx.jpom.model.system.ProcessModel;
|
||||
import cn.keepbx.jpom.system.AgentConfigBean;
|
||||
import cn.keepbx.jpom.util.CommandUtil;
|
||||
import cn.keepbx.jpom.util.JvmUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.sun.tools.attach.VirtualMachine;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 内存查看
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/manage/")
|
||||
public class InternalController extends BaseAgentController {
|
||||
|
||||
/**
|
||||
* 获取内存信息
|
||||
*/
|
||||
@RequestMapping(value = "internal_data", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String getInternal(String tag) throws Exception {
|
||||
int pid = AbstractProjectCommander.getInstance().getPid(tag);
|
||||
if (pid <= 0) {
|
||||
return JsonMessage.getString(400, "");
|
||||
}
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
ProcessModel item = AbstractSystemCommander.getInstance().getPidInfo(pid);
|
||||
jsonObject.put("process", item);
|
||||
JSONObject beanMem = getBeanMem(tag);
|
||||
jsonObject.put("beanMem", beanMem);
|
||||
//获取端口信息
|
||||
List<NetstatModel> netstatModels = AbstractProjectCommander.getInstance().listNetstat(pid);
|
||||
jsonObject.put("netstat", netstatModels);
|
||||
return JsonMessage.getString(200, "", jsonObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jvm内存
|
||||
*
|
||||
* @param tag tag
|
||||
* @return JSONObject
|
||||
*/
|
||||
private JSONObject getBeanMem(String tag) {
|
||||
try {
|
||||
VirtualMachine virtualMachine = JvmUtil.getVirtualMachine(tag);
|
||||
MemoryMXBean memoryMXBean = JvmUtil.getMemoryMXBean(virtualMachine);
|
||||
if (memoryMXBean == null) {
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("mount", memoryMXBean.getObjectPendingFinalizationCount());
|
||||
//堆内存
|
||||
MemoryUsage memory = memoryMXBean.getHeapMemoryUsage();
|
||||
//非堆内存
|
||||
MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
|
||||
long used = memory.getUsed();
|
||||
long max = memory.getMax();
|
||||
//未定义
|
||||
if (-1 == max) {
|
||||
max = memory.getCommitted();
|
||||
}
|
||||
//计算使用内存占最大内存的百分比
|
||||
double v = new BigDecimal(used).divide(new BigDecimal(max), 2, BigDecimal.ROUND_HALF_UP).doubleValue() * 100;
|
||||
jsonObject.put("heapUsed", FileUtil.readableFileSize(used));
|
||||
jsonObject.put("heapProportion", String.format("%.2f", v) + "%");
|
||||
jsonObject.put("heapCommitted", FileUtil.readableFileSize(memory.getCommitted()));
|
||||
long nonUsed = nonHeapMemoryUsage.getUsed();
|
||||
long nonMax = nonHeapMemoryUsage.getMax();
|
||||
long nonCommitted = nonHeapMemoryUsage.getCommitted();
|
||||
if (-1 == nonMax) {
|
||||
nonMax = nonCommitted;
|
||||
}
|
||||
jsonObject.put("nonHeapUsed", FileUtil.readableFileSize(nonUsed));
|
||||
double proportion = new BigDecimal(nonUsed).divide(new BigDecimal(nonMax), 2, BigDecimal.ROUND_HALF_UP).doubleValue() * 100;
|
||||
jsonObject.put("nonHeapProportion", String.format("%.2f", proportion) + "%");
|
||||
jsonObject.put("nonHeapCommitted", FileUtil.readableFileSize(nonCommitted));
|
||||
return jsonObject;
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导出堆栈信息
|
||||
*/
|
||||
@RequestMapping(value = "internal_stack", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public String stack(String tag) throws Exception {
|
||||
String fileName = AgentConfigBean.getInstance().getTempPathName() + "/" + tag + "_java_cpu.txt";
|
||||
fileName = FileUtil.normalize(fileName);
|
||||
try {
|
||||
int pid = AbstractProjectCommander.getInstance().getPid(tag);
|
||||
if (pid <= 0) {
|
||||
return JsonMessage.getString(400, "未运行");
|
||||
}
|
||||
String command = String.format("jstack %s >> %s ", pid, fileName);
|
||||
CommandUtil.execSystemCommand(command);
|
||||
downLoad(getResponse(), fileName);
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
// getResponse().sendRedirect("internal?tag=" + tag);
|
||||
}
|
||||
return JsonMessage.getString(200, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出内存信息
|
||||
*/
|
||||
@RequestMapping(value = "internal_ram", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public String ram(String tag) throws Exception {
|
||||
String fileName = AgentConfigBean.getInstance().getTempPathName() + "/" + tag + "_java_ram.txt";
|
||||
fileName = FileUtil.normalize(fileName);
|
||||
try {
|
||||
int pid = AbstractProjectCommander.getInstance().getPid(tag);
|
||||
if (pid <= 0) {
|
||||
return JsonMessage.getString(400, "未运行");
|
||||
}
|
||||
String command = String.format("jmap -histo:live %s >> %s", pid, fileName);
|
||||
CommandUtil.execSystemCommand(command);
|
||||
downLoad(getResponse(), fileName);
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
// getResponse().sendRedirect("internal?tag=" + tag);
|
||||
}
|
||||
return JsonMessage.getString(200, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*
|
||||
* @param response response
|
||||
* @param fileName 文件名字
|
||||
*/
|
||||
private void downLoad(HttpServletResponse response, String fileName) {
|
||||
//获取项目根路径
|
||||
File file = new File(fileName);
|
||||
ServletUtil.write(response, file);
|
||||
FileUtil.del(file);
|
||||
}
|
||||
}
|
@ -0,0 +1,263 @@
|
||||
package cn.keepbx.jpom.controller.system;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.jiangzeyin.controller.multipart.MultipartFileBuilder;
|
||||
import cn.keepbx.jpom.common.BaseAgentController;
|
||||
import cn.keepbx.jpom.model.data.CertModel;
|
||||
import cn.keepbx.jpom.service.WhitelistDirectoryService;
|
||||
import cn.keepbx.jpom.service.system.CertService;
|
||||
import cn.keepbx.jpom.system.AgentConfigBean;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 证书管理
|
||||
*
|
||||
* @author Arno
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/system/certificate")
|
||||
public class CertificateController extends BaseAgentController {
|
||||
|
||||
@Resource
|
||||
private CertService certService;
|
||||
@Resource
|
||||
private WhitelistDirectoryService whitelistDirectoryService;
|
||||
|
||||
|
||||
/**
|
||||
* 保存证书
|
||||
*
|
||||
* @return json
|
||||
*/
|
||||
@RequestMapping(value = "/saveCertificate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String saveCertificate() {
|
||||
String data = getParameter("data");
|
||||
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
String type = jsonObject.getString("type");
|
||||
String id = jsonObject.getString("id");
|
||||
try {
|
||||
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, "提交成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取证书信息
|
||||
*
|
||||
* @param certModel 实体
|
||||
* @return 错误消息
|
||||
*/
|
||||
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)) {
|
||||
return JsonMessage.getString(400, "请填写证书id");
|
||||
}
|
||||
if (Validator.isChinese(id)) {
|
||||
return JsonMessage.getString(400, "证书id不能使用中文");
|
||||
}
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
return JsonMessage.getString(400, "请填写证书名称");
|
||||
}
|
||||
if (!whitelistDirectoryService.checkCertificateDirectory(path)) {
|
||||
return JsonMessage.getString(400, "请选择正确的项目路径,或者还没有配置白名单");
|
||||
}
|
||||
certModel.setId(id);
|
||||
certModel.setWhitePath(path);
|
||||
certModel.setName(name);
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getCertFile(CertModel certModel, boolean add) throws IOException {
|
||||
String certPath = null;
|
||||
String pemPath = null, keyPath = null;
|
||||
try {
|
||||
String path = AgentConfigBean.getInstance().getTempPathName();
|
||||
MultipartFileBuilder cert = createMultipart().addFieldName("file").setSavePath(path);
|
||||
certPath = cert.save();
|
||||
ZipFile zipFile = new ZipFile(certPath);
|
||||
Enumeration<? extends ZipEntry> 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<CertModel> 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");
|
||||
if (add) {
|
||||
if (pemFile.exists()) {
|
||||
return JsonMessage.getString(405, pemFile.getAbsolutePath() + " 已经被占用啦");
|
||||
}
|
||||
if (keyFile.exists()) {
|
||||
return JsonMessage.getString(405, keyFile.getAbsolutePath() + " 已经被占用啦");
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 证书列表
|
||||
*/
|
||||
@RequestMapping(value = "/getCertList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String getCertList() {
|
||||
List<CertModel> array = certService.list();
|
||||
return JsonMessage.getString(200, "", array);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除证书
|
||||
*
|
||||
* @param id id
|
||||
* @return json
|
||||
*/
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String delete(String id) {
|
||||
if (StrUtil.isEmpty(id)) {
|
||||
return JsonMessage.getString(400, "删除失败");
|
||||
}
|
||||
if (!isSystemUser()) {
|
||||
return JsonMessage.getString(400, "你没有操作权限");
|
||||
}
|
||||
boolean b = certService.delete(id);
|
||||
if (!b) {
|
||||
return JsonMessage.getString(400, "删除失败");
|
||||
}
|
||||
return JsonMessage.getString(200, "删除成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导出证书
|
||||
*/
|
||||
@RequestMapping(value = "/export", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String export(String id) {
|
||||
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, "导出成功");
|
||||
}
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
package cn.keepbx.jpom.controller.system;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.keepbx.jpom.common.BaseAgentController;
|
||||
import cn.keepbx.jpom.service.WhitelistDirectoryService;
|
||||
import cn.keepbx.jpom.service.system.NginxService;
|
||||
import cn.keepbx.jpom.util.CommandUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.odiszapc.nginxparser.NgxBlock;
|
||||
import com.github.odiszapc.nginxparser.NgxConfig;
|
||||
import com.github.odiszapc.nginxparser.NgxEntry;
|
||||
import com.github.odiszapc.nginxparser.NgxParam;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author jiangzeyin
|
||||
* @date 2019/4/17
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/system/nginx")
|
||||
public class NginxController extends BaseAgentController {
|
||||
|
||||
@Resource
|
||||
private NginxService nginxService;
|
||||
@Resource
|
||||
private WhitelistDirectoryService whitelistDirectoryService;
|
||||
|
||||
/**
|
||||
* 配置列表
|
||||
*/
|
||||
@RequestMapping(value = "list_data.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
@ResponseBody
|
||||
public String list() {
|
||||
JSONArray array = nginxService.list();
|
||||
return JsonMessage.getString(200, "", array);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "item_data", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public String itemData(String path, String name, String type) {
|
||||
name = pathSafe(name);
|
||||
if (whitelistDirectoryService.checkNgxDirectory(path)) {
|
||||
File file = FileUtil.file(path, name);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
String string = FileUtil.readUtf8String(file);
|
||||
jsonObject.put("context", string);
|
||||
jsonObject.put("name", nginxService.paresName(path, file.getAbsolutePath()));
|
||||
jsonObject.put("whitePath", path);
|
||||
return JsonMessage.getString(200, "", jsonObject);
|
||||
// setAttribute("data", jsonObject);
|
||||
}
|
||||
return JsonMessage.getString(400, "错误");
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增或修改配置
|
||||
*
|
||||
* @param name 文件名
|
||||
* @param whitePath 白名单路径
|
||||
*/
|
||||
@RequestMapping(value = "updateNgx", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
@ResponseBody
|
||||
public String updateNgx(String name, String whitePath, String context, String genre) {
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
return JsonMessage.getString(400, "请填写文件名");
|
||||
}
|
||||
if (!name.endsWith(".conf")) {
|
||||
return JsonMessage.getString(400, "文件后缀必须为\".conf\"");
|
||||
}
|
||||
if (!checkPathSafe(name)) {
|
||||
return JsonMessage.getString(400, "文件名存在非法字符");
|
||||
}
|
||||
if (!whitelistDirectoryService.checkNgxDirectory(whitePath)) {
|
||||
return JsonMessage.getString(400, "请选择正确的白名单");
|
||||
}
|
||||
//nginx文件
|
||||
File file = FileUtil.file(whitePath, name);
|
||||
if ("add".equals(genre) && file.exists()) {
|
||||
return JsonMessage.getString(400, "该文件已存在");
|
||||
}
|
||||
if (StrUtil.isEmpty(context)) {
|
||||
return JsonMessage.getString(400, "请填写配置信息");
|
||||
}
|
||||
InputStream inputStream = new ByteArrayInputStream(context.getBytes());
|
||||
try {
|
||||
NgxConfig conf = NgxConfig.read(inputStream);
|
||||
List<NgxEntry> list = conf.findAll(NgxBlock.class, "server");
|
||||
if (list == null || list.size() <= 0) {
|
||||
return JsonMessage.getString(404, "内容解析为空");
|
||||
}
|
||||
for (NgxEntry ngxEntry : list) {
|
||||
NgxBlock ngxBlock = (NgxBlock) ngxEntry;
|
||||
// 检查日志路径
|
||||
NgxParam accessLog = ngxBlock.findParam("access_log");
|
||||
if (accessLog != null) {
|
||||
FileUtil.mkParentDirs(accessLog.getValue());
|
||||
}
|
||||
accessLog = ngxBlock.findParam("error_log");
|
||||
if (accessLog != null) {
|
||||
FileUtil.mkParentDirs(accessLog.getValue());
|
||||
}
|
||||
// 检查证书文件
|
||||
NgxParam sslCertificate = ngxBlock.findParam("ssl_certificate");
|
||||
if (sslCertificate != null && !FileUtil.exist(sslCertificate.getValue())) {
|
||||
return JsonMessage.getString(404, "证书文件ssl_certificate,不存在");
|
||||
}
|
||||
NgxParam sslCertificateKey = ngxBlock.findParam("ssl_certificate_key");
|
||||
if (sslCertificateKey != null && !FileUtil.exist(sslCertificateKey.getValue())) {
|
||||
return JsonMessage.getString(404, "证书文件ssl_certificate_key,不存在");
|
||||
}
|
||||
if (!checkRootRole(ngxBlock)) {
|
||||
return JsonMessage.getString(405, "非系统管理员,不能配置静态资源代理");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
DefaultSystemLog.ERROR().error("解析失败", e);
|
||||
return JsonMessage.getString(500, "解析失败");
|
||||
}
|
||||
try {
|
||||
FileUtil.writeString(context, file, CharsetUtil.UTF_8);
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
return JsonMessage.getString(400, "操作失败:" + e.getMessage());
|
||||
}
|
||||
String msg = this.reloadNginx();
|
||||
return JsonMessage.getString(200, "提交成功" + msg);
|
||||
}
|
||||
|
||||
private String reloadNginx() {
|
||||
try {
|
||||
String msg = CommandUtil.execSystemCommand("nginx -s reload");
|
||||
if (StrUtil.isNotEmpty(msg)) {
|
||||
DefaultSystemLog.LOG().info(msg);
|
||||
return "(" + msg + ")";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error("reload nginx error", e);
|
||||
}
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限检查 防止非系统管理员配置静态资源访问
|
||||
*
|
||||
* @return false 不正确
|
||||
*/
|
||||
private boolean checkRootRole(NgxBlock ngxBlock) {
|
||||
// UserModel userModel = getUser();
|
||||
List<NgxEntry> locationAll = ngxBlock.findAll(NgxBlock.class, "location");
|
||||
if (locationAll != null) {
|
||||
for (NgxEntry ngxEntry1 : locationAll) {
|
||||
NgxBlock ngxBlock1 = (NgxBlock) ngxEntry1;
|
||||
NgxParam locationMain = ngxBlock1.findParam("root");
|
||||
if (locationMain == null) {
|
||||
locationMain = ngxBlock1.findParam("alias");
|
||||
}
|
||||
if (locationMain != null && !isSystemUser()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除配置
|
||||
*
|
||||
* @param path 文件路径
|
||||
*/
|
||||
@RequestMapping(value = "delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
@ResponseBody
|
||||
public String delete(String path, String name) {
|
||||
if (!whitelistDirectoryService.checkNgxDirectory(path)) {
|
||||
return JsonMessage.getString(400, "非法操作");
|
||||
}
|
||||
path = pathSafe(path);
|
||||
name = pathSafe(name);
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
return JsonMessage.getString(400, "删除失败,请正常操作");
|
||||
}
|
||||
File file = FileUtil.file(path, name);
|
||||
try {
|
||||
FileUtil.rename(file, file.getName() + "_back", false, true);
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error("删除nginx", e);
|
||||
return JsonMessage.getString(400, "删除失败:" + e.getMessage());
|
||||
}
|
||||
String msg = this.reloadNginx();
|
||||
return JsonMessage.getString(200, "删除成功" + msg);
|
||||
}
|
||||
}
|
@ -26,6 +26,8 @@ import java.util.Date;
|
||||
* @author Arno
|
||||
*/
|
||||
public class CertModel extends BaseModel {
|
||||
|
||||
private static final String KEY = "Jpom 管理系统";
|
||||
private String name;
|
||||
/**
|
||||
* 证书文件
|
||||
@ -146,10 +148,10 @@ public class CertModel extends BaseModel {
|
||||
PrivateKey privateKey = BCUtil.readPrivateKey(ResourceUtil.getStream(key));
|
||||
PublicKey publicKey = BCUtil.readPublicKey(ResourceUtil.getStream(file));
|
||||
RSA rsa = new RSA(privateKey, publicKey);
|
||||
String str = UserModel.SYSTEM_OCCUPY_NAME;
|
||||
String encryptStr = rsa.encryptBase64(str, KeyType.PublicKey);
|
||||
// String str = KEY;
|
||||
String encryptStr = rsa.encryptBase64(KEY, KeyType.PublicKey);
|
||||
String decryptStr = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
|
||||
if (!str.equals(decryptStr)) {
|
||||
if (!KEY.equals(decryptStr)) {
|
||||
throw new JpomRuntimeException("证书和私钥证书不匹配");
|
||||
}
|
||||
try {
|
@ -1,5 +1,7 @@
|
||||
package cn.keepbx.jpom.service;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.keepbx.jpom.common.BaseDataService;
|
||||
import cn.keepbx.jpom.model.data.Whitelist;
|
||||
@ -8,6 +10,7 @@ import cn.keepbx.jpom.util.JsonFileUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -30,6 +33,14 @@ public class WhitelistDirectoryService extends BaseDataService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<String> getNgxDirectory() {
|
||||
Whitelist whitelist = getWhitelist();
|
||||
if (whitelist == null) {
|
||||
return null;
|
||||
}
|
||||
return whitelist.getNginx();
|
||||
}
|
||||
|
||||
public boolean checkProjectDirectory(String path) {
|
||||
Whitelist whitelist = getWhitelist();
|
||||
if (whitelist == null) {
|
||||
@ -41,22 +52,44 @@ public class WhitelistDirectoryService extends BaseDataService {
|
||||
}
|
||||
return list.contains(path);
|
||||
}
|
||||
//
|
||||
// public boolean checkNgxDirectory(String path) {
|
||||
// List<String> list = getNgxDirectory();
|
||||
// if (list == null) {
|
||||
// return false;
|
||||
// }
|
||||
// return list.contains(path);
|
||||
// }
|
||||
//
|
||||
// public boolean checkCertificateDirectory(String path) {
|
||||
// List<String> list = getCertificateDirectory();
|
||||
// if (list == null) {
|
||||
// return false;
|
||||
// }
|
||||
// return list.contains(path);
|
||||
// }
|
||||
|
||||
public boolean checkNgxDirectory(String path) {
|
||||
List<String> list = getNgxDirectory();
|
||||
if (list == null) {
|
||||
return false;
|
||||
}
|
||||
return checkPath(list, path);
|
||||
}
|
||||
|
||||
private boolean checkPath(List<String> list, String path) {
|
||||
if (StrUtil.isEmpty(path)) {
|
||||
return false;
|
||||
}
|
||||
File file1, file2 = FileUtil.file(path);
|
||||
for (String item : list) {
|
||||
file1 = FileUtil.file(item);
|
||||
if (FileUtil.pathEquals(file1, file2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<String> getCertificateDirectory() {
|
||||
Whitelist whitelist = getWhitelist();
|
||||
if (whitelist == null) {
|
||||
return null;
|
||||
}
|
||||
return whitelist.getCertificate();
|
||||
}
|
||||
|
||||
public boolean checkCertificateDirectory(String path) {
|
||||
List<String> list = getCertificateDirectory();
|
||||
if (list == null) {
|
||||
return false;
|
||||
}
|
||||
return checkPath(list, path);
|
||||
}
|
||||
|
||||
// private JSONArray getItemArray(String key) {
|
||||
// try {
|
||||
|
@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.keepbx.jpom.common.BaseOperService;
|
||||
import cn.keepbx.jpom.model.data.CertModel;
|
||||
import cn.keepbx.jpom.system.ServerConfigBean;
|
||||
import cn.keepbx.jpom.system.AgentConfigBean;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -27,7 +27,7 @@ public class CertService extends BaseOperService<CertModel> {
|
||||
*/
|
||||
@Override
|
||||
public void addItem(CertModel certModel) {
|
||||
saveJson(ServerConfigBean.CERT, certModel.toJson());
|
||||
saveJson(AgentConfigBean.CERT, certModel.toJson());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +37,7 @@ public class CertService extends BaseOperService<CertModel> {
|
||||
*/
|
||||
@Override
|
||||
public List<CertModel> list() {
|
||||
JSONObject jsonObject = getJSONObject(ServerConfigBean.CERT);
|
||||
JSONObject jsonObject = getJSONObject(AgentConfigBean.CERT);
|
||||
if (jsonObject == null) {
|
||||
return null;
|
||||
}
|
||||
@ -47,7 +47,7 @@ public class CertService extends BaseOperService<CertModel> {
|
||||
|
||||
@Override
|
||||
public CertModel getItem(String id) {
|
||||
return getJsonObjectById(ServerConfigBean.CERT, id, CertModel.class);
|
||||
return getJsonObjectById(AgentConfigBean.CERT, id, CertModel.class);
|
||||
}
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ public class CertService extends BaseOperService<CertModel> {
|
||||
return true;
|
||||
}
|
||||
String keyPath = certModel.getCert();
|
||||
deleteJson(ServerConfigBean.CERT, id);
|
||||
deleteJson(AgentConfigBean.CERT, id);
|
||||
if (StrUtil.isNotEmpty(keyPath)) {
|
||||
// 删除证书文件
|
||||
File parentFile = FileUtil.file(keyPath).getParentFile();
|
||||
@ -84,7 +84,7 @@ public class CertService extends BaseOperService<CertModel> {
|
||||
@Override
|
||||
public boolean updateItem(CertModel certModel) {
|
||||
try {
|
||||
updateJson(ServerConfigBean.CERT, certModel.toJson());
|
||||
updateJson(AgentConfigBean.CERT, certModel.toJson());
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
return false;
|
@ -6,6 +6,8 @@ import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.keepbx.jpom.common.BaseOperService;
|
||||
import cn.keepbx.jpom.model.data.Whitelist;
|
||||
import cn.keepbx.jpom.service.WhitelistDirectoryService;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.odiszapc.nginxparser.NgxBlock;
|
||||
@ -31,7 +33,11 @@ public class NginxService extends BaseOperService {
|
||||
|
||||
@Override
|
||||
public JSONArray list() {
|
||||
List<String> ngxDirectory = whitelistDirectoryService.getNgxDirectory(null);
|
||||
Whitelist whitelist = whitelistDirectoryService.getWhitelist();
|
||||
if (whitelist == null) {
|
||||
return null;
|
||||
}
|
||||
List<String> ngxDirectory = whitelist.getNginx();
|
||||
if (ngxDirectory == null) {
|
||||
return null;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package cn.keepbx.jpom.socket;
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.jiangzeyin.common.spring.SpringUtil;
|
||||
@ -17,23 +18,28 @@ import javax.websocket.*;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author jiangzeyin
|
||||
* @date 2019/4/16
|
||||
*/
|
||||
@ServerEndpoint(value = "/console/{projectId}")
|
||||
@ServerEndpoint(value = "/console/{projectId}/{optUser}")
|
||||
@Component
|
||||
public class AgentWebSocketHandle {
|
||||
|
||||
private static final ConcurrentHashMap<String, String> USER = new ConcurrentHashMap<>();
|
||||
private static ProjectInfoService projectInfoService;
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(@PathParam("projectId") String projectId, Session session) {
|
||||
public void onOpen(@PathParam("projectId") String projectId, @PathParam("optUser") String optUser, Session session) {
|
||||
System.out.println(projectId);
|
||||
try {
|
||||
// 判断项目
|
||||
if (!WebSocketConfig.SYSTEM_ID.equals(projectId)) {
|
||||
ProjectInfoService projectInfoService = SpringUtil.getBean(ProjectInfoService.class);
|
||||
if (projectInfoService == null) {
|
||||
projectInfoService = SpringUtil.getBean(ProjectInfoService.class);
|
||||
}
|
||||
ProjectInfoModel projectInfoModel = projectInfoService.getItem(projectId);
|
||||
if (projectInfoModel == null) {
|
||||
SocketSessionUtil.send(session, "获取项目信息错误");
|
||||
@ -41,6 +47,7 @@ public class AgentWebSocketHandle {
|
||||
return;
|
||||
}
|
||||
}
|
||||
USER.put(session.getId(), optUser);
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error("socket 错误", e);
|
||||
try {
|
||||
@ -50,7 +57,22 @@ public class AgentWebSocketHandle {
|
||||
DefaultSystemLog.ERROR().error(e1.getMessage(), e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getOptUserName(Session session) {
|
||||
String name = USER.get(session.getId());
|
||||
return StrUtil.emptyToDefault(name, StrUtil.DASHED);
|
||||
}
|
||||
|
||||
private boolean silentMsg(CommandOp commandOp, Session session) {
|
||||
if (commandOp == CommandOp.heart) {
|
||||
return true;
|
||||
}
|
||||
if (commandOp == CommandOp.top) {
|
||||
TopManager.addMonitor(session);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
@ -58,21 +80,21 @@ public class AgentWebSocketHandle {
|
||||
JSONObject json = JSONObject.parseObject(message);
|
||||
String op = json.getString("op");
|
||||
CommandOp commandOp = CommandOp.valueOf(op);
|
||||
if (commandOp == CommandOp.heart) {
|
||||
return;
|
||||
}
|
||||
if (commandOp == CommandOp.top) {
|
||||
TopManager.addMonitor(session);
|
||||
if (silentMsg(commandOp, session)) {
|
||||
return;
|
||||
}
|
||||
String projectId = json.getString("projectId");
|
||||
ProjectInfoService projectInfoService = SpringUtil.getBean(ProjectInfoService.class);
|
||||
projectInfoService = SpringUtil.getBean(ProjectInfoService.class);
|
||||
ProjectInfoModel projectInfoModel = projectInfoService.getItem(projectId);
|
||||
System.out.println(op + " " + projectId);
|
||||
if (projectInfoModel == null) {
|
||||
SocketSessionUtil.send(session, "没有对应项目");
|
||||
return;
|
||||
}
|
||||
runMsg(commandOp, session, projectInfoModel);
|
||||
}
|
||||
|
||||
private void runMsg(CommandOp commandOp, Session session, ProjectInfoModel projectInfoModel) throws Exception {
|
||||
ConsoleService consoleService = SpringUtil.getBean(ConsoleService.class);
|
||||
JSONObject resultData = null;
|
||||
String strResult;
|
||||
@ -121,7 +143,7 @@ public class AgentWebSocketHandle {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
resultData = JsonMessage.toJson(404, "不支持的方式:" + op);
|
||||
resultData = JsonMessage.toJson(404, "不支持的方式:" + commandOp.name());
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -132,14 +154,15 @@ public class AgentWebSocketHandle {
|
||||
} finally {
|
||||
if (logUser) {
|
||||
// 记录操作人
|
||||
projectInfoModel = projectInfoService.getItem(projectId);
|
||||
// projectInfoModel.logModifyUser(userModel);
|
||||
projectInfoModel = projectInfoService.getItem(projectInfoModel.getId());
|
||||
String name = getOptUserName(session);
|
||||
projectInfoModel.setModifyUser(name);
|
||||
projectInfoService.updateItem(projectInfoModel);
|
||||
}
|
||||
}
|
||||
//
|
||||
if (resultData != null) {
|
||||
resultData.put("op", op);
|
||||
resultData.put("op", commandOp.name());
|
||||
DefaultSystemLog.LOG().info(resultData.toString());
|
||||
SocketSessionUtil.send(session, resultData.toString());
|
||||
}
|
||||
@ -160,6 +183,7 @@ public class AgentWebSocketHandle {
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error("关闭异常", e);
|
||||
}
|
||||
USER.remove(session.getId());
|
||||
}
|
||||
|
||||
@OnError
|
||||
|
@ -36,6 +36,12 @@ public class AgentConfigBean {
|
||||
*/
|
||||
public static final String ALI_OSS = "aliOss.json";
|
||||
|
||||
/**
|
||||
* 证书文件
|
||||
*/
|
||||
public static final String CERT = "cert.json";
|
||||
|
||||
|
||||
private static AgentConfigBean agentConfigBean;
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,36 @@ public class AgentExtConfigBean {
|
||||
@Value("${whitelistDirectory.checkStartsWith:true}")
|
||||
public boolean whitelistDirectoryCheckStartsWith;
|
||||
|
||||
/**
|
||||
* 自动备份控制台日志,防止日志文件过大,目前暂只支持linux 不停服备份 如果配置none 则不自动备份 默认10分钟扫描一次
|
||||
*/
|
||||
@Value("${log.autoBackConsoleCron:0 0/10 * * * ?}")
|
||||
public String autoBackConsoleCron;
|
||||
/**
|
||||
* 当文件多大时自动备份
|
||||
*
|
||||
* @see ch.qos.logback.core.util.FileSize
|
||||
*/
|
||||
@Value("${log.autoBackSize:50MB}")
|
||||
public String autoBackSize;
|
||||
/**
|
||||
* 控制台日志保存时长单位天
|
||||
*/
|
||||
@Value("${log.saveDays:7}")
|
||||
private int logSaveDays;
|
||||
|
||||
/**
|
||||
* 配置错误或者没有,默认是7天
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getLogSaveDays() {
|
||||
if (logSaveDays <= 0) {
|
||||
return 7;
|
||||
}
|
||||
return logSaveDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*
|
||||
|
@ -1,9 +1,23 @@
|
||||
package cn.keepbx.jpom.system.init;
|
||||
|
||||
import ch.qos.logback.core.util.FileSize;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.cron.CronUtil;
|
||||
import cn.hutool.cron.Scheduler;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.jiangzeyin.common.PreLoadClass;
|
||||
import cn.jiangzeyin.common.PreLoadMethod;
|
||||
import cn.jiangzeyin.common.spring.SpringUtil;
|
||||
import cn.keepbx.jpom.common.commander.AbstractProjectCommander;
|
||||
import cn.keepbx.jpom.model.data.ProjectInfoModel;
|
||||
import cn.keepbx.jpom.service.manage.ProjectInfoService;
|
||||
import cn.keepbx.jpom.system.AgentExtConfigBean;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自动备份控制台日志,防止日志文件过大
|
||||
@ -15,7 +29,7 @@ import cn.jiangzeyin.common.PreLoadMethod;
|
||||
public class AutoBackLog {
|
||||
|
||||
private static final String ID = "auto_back_log";
|
||||
// private static ProjectInfoService projectInfoService;
|
||||
private static ProjectInfoService projectInfoService;
|
||||
|
||||
private static FileSize MAX_SIZE;
|
||||
|
||||
@ -23,55 +37,55 @@ public class AutoBackLog {
|
||||
private static void startAutoBackLog() {
|
||||
// 开启秒级表达式
|
||||
CronUtil.setMatchSecond(true);
|
||||
// if (projectInfoService == null) {
|
||||
// projectInfoService = SpringUtil.getBean(ProjectInfoService.class);
|
||||
// }
|
||||
// // 获取cron 表达式
|
||||
// String cron = StrUtil.emptyToDefault(ServerExtConfigBean.getInstance().autoBackConsoleCron, "none");
|
||||
// if ("none".equalsIgnoreCase(cron.trim())) {
|
||||
// DefaultSystemLog.LOG().info("没有配置自动备份控制台日志表达式");
|
||||
// return;
|
||||
// }
|
||||
// String size = StrUtil.emptyToDefault(ServerExtConfigBean.getInstance().autoBackSize, "50MB");
|
||||
// MAX_SIZE = FileSize.valueOf(size.trim());
|
||||
// //
|
||||
// CronUtil.schedule(ID, cron, () -> {
|
||||
// try {
|
||||
// List<ProjectInfoModel> list = projectInfoService.list();
|
||||
// if (list == null) {
|
||||
// return;
|
||||
// }
|
||||
// list.forEach(projectInfoModel -> {
|
||||
// String log = projectInfoModel.getLog();
|
||||
// File file = new File(log);
|
||||
// if (!file.exists()) {
|
||||
// return;
|
||||
// }
|
||||
// long len = file.length();
|
||||
// if (len > MAX_SIZE.getSize()) {
|
||||
// try {
|
||||
// AbstractProjectCommander.getInstance().backLog(projectInfoModel);
|
||||
// } catch (Exception ignored) {
|
||||
// }
|
||||
// }
|
||||
// // 清理过期的文件
|
||||
// File logFile = projectInfoModel.getLogBack();
|
||||
// DateTime nowTime = DateTime.now();
|
||||
// List<File> files = FileUtil.loopFiles(logFile, pathname -> {
|
||||
// DateTime dateTime = DateUtil.date(pathname.lastModified());
|
||||
// long days = DateUtil.betweenDay(dateTime, nowTime, false);
|
||||
// long saveDays = ServerExtConfigBean.getInstance().getLogSaveDays();
|
||||
// return days > saveDays;
|
||||
// });
|
||||
// files.forEach(FileUtil::del);
|
||||
// });
|
||||
// } catch (Exception e) {
|
||||
// DefaultSystemLog.ERROR().error("定时备份日志失败", e);
|
||||
// }
|
||||
// });
|
||||
// Scheduler scheduler = CronUtil.getScheduler();
|
||||
// if (!scheduler.isStarted()) {
|
||||
// CronUtil.start();
|
||||
// }
|
||||
if (projectInfoService == null) {
|
||||
projectInfoService = SpringUtil.getBean(ProjectInfoService.class);
|
||||
}
|
||||
// 获取cron 表达式
|
||||
String cron = StrUtil.emptyToDefault(AgentExtConfigBean.getInstance().autoBackConsoleCron, "none");
|
||||
if ("none".equalsIgnoreCase(cron.trim())) {
|
||||
DefaultSystemLog.LOG().info("没有配置自动备份控制台日志表达式");
|
||||
return;
|
||||
}
|
||||
String size = StrUtil.emptyToDefault(AgentExtConfigBean.getInstance().autoBackSize, "50MB");
|
||||
MAX_SIZE = FileSize.valueOf(size.trim());
|
||||
//
|
||||
CronUtil.schedule(ID, cron, () -> {
|
||||
try {
|
||||
List<ProjectInfoModel> list = projectInfoService.list();
|
||||
if (list == null) {
|
||||
return;
|
||||
}
|
||||
list.forEach(projectInfoModel -> {
|
||||
String log = projectInfoModel.getLog();
|
||||
File file = new File(log);
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
long len = file.length();
|
||||
if (len > MAX_SIZE.getSize()) {
|
||||
try {
|
||||
AbstractProjectCommander.getInstance().backLog(projectInfoModel);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
// 清理过期的文件
|
||||
File logFile = projectInfoModel.getLogBack();
|
||||
DateTime nowTime = DateTime.now();
|
||||
List<File> files = FileUtil.loopFiles(logFile, pathname -> {
|
||||
DateTime dateTime = DateUtil.date(pathname.lastModified());
|
||||
long days = DateUtil.betweenDay(dateTime, nowTime, false);
|
||||
long saveDays = AgentExtConfigBean.getInstance().getLogSaveDays();
|
||||
return days > saveDays;
|
||||
});
|
||||
files.forEach(FileUtil::del);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error("定时备份日志失败", e);
|
||||
}
|
||||
});
|
||||
Scheduler scheduler = CronUtil.getScheduler();
|
||||
if (!scheduler.isStarted()) {
|
||||
CronUtil.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import cn.keepbx.jpom.model.BaseJsonModel;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 白名单
|
||||
*
|
||||
* @author jiangzeyin
|
||||
* @date 2019/4/16
|
||||
*/
|
||||
|
@ -49,14 +49,7 @@ public abstract class BaseController extends BaseJpomController {
|
||||
}
|
||||
|
||||
public static String getOptUserName() {
|
||||
UserModel userModel = getUserModel();
|
||||
String userId;
|
||||
if (userModel.isSystemUser()) {
|
||||
userId = UserModel.SYSTEM_OCCUPY_NAME;
|
||||
} else {
|
||||
userId = userModel.getId();
|
||||
}
|
||||
return userId;
|
||||
return UserModel.getOptUserName(getUserModel());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import cn.hutool.http.HttpUtil;
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.keepbx.jpom.common.BaseController;
|
||||
import cn.keepbx.jpom.model.data.NodeModel;
|
||||
import cn.keepbx.jpom.model.data.UserModel;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -17,8 +18,11 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 节点请求转发
|
||||
*
|
||||
* @author jiangzeyin
|
||||
* @date 2019/4/16
|
||||
*/
|
||||
@ -39,10 +43,27 @@ public class NodeForward {
|
||||
return JSON.parseObject(body, JsonMessage.class);
|
||||
}
|
||||
|
||||
public static <T> T requestData(NodeModel nodeModel, NodeUrl nodeUrl, HttpServletRequest request, Class<T> tClass) {
|
||||
JsonMessage jsonMessage = request(nodeModel, request, nodeUrl);
|
||||
return toObj(jsonMessage, tClass);
|
||||
}
|
||||
|
||||
public static <T> T requestData(NodeModel nodeModel, NodeUrl nodeUrl, Class<T> tClass) {
|
||||
return requestData(nodeModel, nodeUrl, tClass, null, null);
|
||||
}
|
||||
|
||||
private static <T> T toObj(JsonMessage jsonMessage, Class<T> tClass) {
|
||||
Object data = jsonMessage.getData();
|
||||
if (jsonMessage.getCode() == 200 && null != data) {
|
||||
if (tClass == String.class) {
|
||||
return (T) data.toString();
|
||||
}
|
||||
return JSONObject.parseObject(data.toString(), tClass);
|
||||
}
|
||||
System.out.println(jsonMessage.toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T requestData(NodeModel nodeModel, NodeUrl nodeUrl, Class<T> tClass, String name, Object value, Object... parameters) {
|
||||
String url = StrUtil.format("http://{}{}", nodeModel.getUrl(), nodeUrl.getUrl());
|
||||
//
|
||||
@ -57,15 +78,7 @@ public class NodeForward {
|
||||
.execute()
|
||||
.body();
|
||||
JsonMessage jsonMessage = JSON.parseObject(body, JsonMessage.class);
|
||||
Object data = jsonMessage.getData();
|
||||
if (jsonMessage.getCode() == 200 && null != data) {
|
||||
if (tClass == String.class) {
|
||||
return (T) data.toString();
|
||||
}
|
||||
return JSONObject.parseObject(data.toString(), tClass);
|
||||
}
|
||||
System.out.println(jsonMessage.toString());
|
||||
return null;
|
||||
return toObj(jsonMessage, tClass);
|
||||
}
|
||||
|
||||
public static JsonMessage requestMultipart(NodeModel nodeModel, MultipartHttpServletRequest request, NodeUrl nodeUrl) {
|
||||
@ -111,7 +124,10 @@ public class NodeForward {
|
||||
|
||||
|
||||
private static void addUser(HttpRequest httpRequest) {
|
||||
httpRequest.header("Jpom-Server-UserName", BaseController.getOptUserName());
|
||||
UserModel userModel = BaseController.getUserModel();
|
||||
Objects.requireNonNull(userModel);
|
||||
httpRequest.header("Jpom-Server-UserName", UserModel.getOptUserName(userModel));
|
||||
httpRequest.header("Jpom-Server-SystemUserRole", String.valueOf(userModel.isSystemUser()));
|
||||
}
|
||||
|
||||
public static String getSocketUrl(NodeModel nodeModel, NodeUrl nodeUrl) {
|
||||
|
@ -5,6 +5,10 @@ package cn.keepbx.jpom.common.forward;
|
||||
* @date 2019/4/16
|
||||
*/
|
||||
public enum NodeUrl {
|
||||
/**
|
||||
* Jpom agent 信息
|
||||
*/
|
||||
Info("/info"),
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -70,6 +74,26 @@ public enum NodeUrl {
|
||||
|
||||
Manage_build_install("/manage/build_install"),
|
||||
|
||||
Manage_internal_data("/manage/internal_data"),
|
||||
Manage_internal_stack("/manage/internal_stack"),
|
||||
Manage_internal_ram("/manage/internal_ram"),
|
||||
|
||||
System_Nginx_list_data("/system/nginx/list_data.json"),
|
||||
|
||||
System_Nginx_item_data("/system/nginx/item_data"),
|
||||
|
||||
System_Nginx_updateNgx("/system/nginx/updateNgx"),
|
||||
|
||||
System_Nginx_delete("/system/nginx/delete"),
|
||||
|
||||
System_Certificate_saveCertificate("/system/certificate/saveCertificate"),
|
||||
|
||||
System_Certificate_getCertList("/system/certificate/getCertList"),
|
||||
|
||||
System_Certificate_delete("/system/certificate/delete"),
|
||||
|
||||
System_Certificate_export("/system/certificate/export"),
|
||||
|
||||
;
|
||||
|
||||
private String url;
|
||||
|
@ -1,8 +1,11 @@
|
||||
package cn.keepbx.jpom.controller.node;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.keepbx.jpom.common.BaseController;
|
||||
import cn.keepbx.jpom.common.BaseNodeController;
|
||||
import cn.keepbx.jpom.common.forward.NodeForward;
|
||||
import cn.keepbx.jpom.common.forward.NodeUrl;
|
||||
import cn.keepbx.jpom.model.data.NodeModel;
|
||||
import cn.keepbx.jpom.model.system.JpomManifest;
|
||||
import cn.keepbx.jpom.service.node.NodeService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -20,7 +23,7 @@ import java.util.List;
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "/node")
|
||||
public class NodeIndexController extends BaseController {
|
||||
public class NodeIndexController extends BaseNodeController {
|
||||
|
||||
@Resource
|
||||
private NodeService nodeService;
|
||||
@ -35,10 +38,14 @@ public class NodeIndexController extends BaseController {
|
||||
@RequestMapping(value = "index.html", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
|
||||
public String index(String nodeId) {
|
||||
NodeModel nodeModel = nodeService.getItem(nodeId);
|
||||
System.out.println(nodeModel);
|
||||
if (nodeModel != null) {
|
||||
setAttribute("node", nodeModel);
|
||||
}
|
||||
List<NodeModel> nodeModels = nodeService.list();
|
||||
setAttribute("array", nodeModels);
|
||||
//
|
||||
JpomManifest jpomManifest = NodeForward.requestData(getNode(), NodeUrl.Info, getRequest(), JpomManifest.class);
|
||||
setAttribute("jpomManifest", jpomManifest);
|
||||
return "node/index";
|
||||
}
|
||||
|
||||
|
@ -1,162 +1,50 @@
|
||||
//package cn.keepbx.jpom.controller.node.monitor;
|
||||
//
|
||||
//import cn.hutool.core.io.FileUtil;
|
||||
//import cn.hutool.extra.servlet.ServletUtil;
|
||||
//import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
//import cn.jiangzeyin.common.JsonMessage;
|
||||
//import cn.keepbx.jpom.common.BaseController;
|
||||
//import cn.keepbx.jpom.common.commander.AbstractProjectCommander;
|
||||
//import cn.keepbx.jpom.model.system.NetstatModel;
|
||||
//import cn.keepbx.jpom.system.ServerConfigBean;
|
||||
//import cn.keepbx.jpom.util.CommandUtil;
|
||||
//import cn.keepbx.jpom.util.JvmUtil;
|
||||
//import com.alibaba.fastjson.JSONObject;
|
||||
//import com.sun.tools.attach.VirtualMachine;
|
||||
//import org.springframework.http.MediaType;
|
||||
//import org.springframework.stereotype.Controller;
|
||||
//import org.springframework.web.bind.annotation.RequestMapping;
|
||||
//import org.springframework.web.bind.annotation.RequestMethod;
|
||||
//import org.springframework.web.bind.annotation.ResponseBody;
|
||||
//
|
||||
//import javax.servlet.http.HttpServletResponse;
|
||||
//import java.io.File;
|
||||
//import java.lang.management.MemoryMXBean;
|
||||
//import java.lang.management.MemoryUsage;
|
||||
//import java.math.BigDecimal;
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * 内存查看
|
||||
// *
|
||||
// * @author Administrator
|
||||
// */
|
||||
//@Controller
|
||||
//@RequestMapping(value = "/node/manage/")
|
||||
//public class InternalController extends BaseController {
|
||||
//
|
||||
// /**
|
||||
// * 获取内存信息
|
||||
// */
|
||||
// @RequestMapping(value = "internal", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
|
||||
// public String getInternal(String tag) throws Exception {
|
||||
// setAttribute("tag", tag);
|
||||
// int pid = AbstractProjectCommander.getInstance().getPid(tag);
|
||||
// if (pid > 0) {
|
||||
//// ProcessModel item = AbstractSystemCommander.getInstance().getPidInfo(pid);
|
||||
//// setAttribute("item", item);
|
||||
// JSONObject beanMem = getBeanMem(tag);
|
||||
// setAttribute("beanMem", beanMem);
|
||||
// //获取端口信息
|
||||
// List<NetstatModel> port = AbstractProjectCommander.getInstance().listNetstat(pid);
|
||||
// setAttribute("port", port);
|
||||
// }
|
||||
// return "node/manage/internal";
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取jvm内存
|
||||
// *
|
||||
// * @param tag tag
|
||||
// * @return JSONObject
|
||||
// */
|
||||
// private JSONObject getBeanMem(String tag) {
|
||||
// try {
|
||||
// VirtualMachine virtualMachine = JvmUtil.getVirtualMachine(tag);
|
||||
// MemoryMXBean memoryMXBean = JvmUtil.getMemoryMXBean(virtualMachine);
|
||||
// if (memoryMXBean == null) {
|
||||
// return null;
|
||||
// }
|
||||
// JSONObject jsonObject = new JSONObject();
|
||||
// jsonObject.put("mount", memoryMXBean.getObjectPendingFinalizationCount());
|
||||
// //堆内存
|
||||
// MemoryUsage memory = memoryMXBean.getHeapMemoryUsage();
|
||||
// //非堆内存
|
||||
// MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
|
||||
// long used = memory.getUsed();
|
||||
// long max = memory.getMax();
|
||||
// //未定义
|
||||
// if (-1 == max) {
|
||||
// max = memory.getCommitted();
|
||||
// }
|
||||
// //计算使用内存占最大内存的百分比
|
||||
// double v = new BigDecimal(used).divide(new BigDecimal(max), 2, BigDecimal.ROUND_HALF_UP).doubleValue() * 100;
|
||||
// jsonObject.put("heapUsed", FileUtil.readableFileSize(used));
|
||||
// jsonObject.put("heapProportion", String.format("%.2f", v) + "%");
|
||||
// jsonObject.put("heapCommitted", FileUtil.readableFileSize(memory.getCommitted()));
|
||||
// long nonUsed = nonHeapMemoryUsage.getUsed();
|
||||
// long nonMax = nonHeapMemoryUsage.getMax();
|
||||
// long nonCommitted = nonHeapMemoryUsage.getCommitted();
|
||||
// if (-1 == nonMax) {
|
||||
// nonMax = nonCommitted;
|
||||
// }
|
||||
// jsonObject.put("nonHeapUsed", FileUtil.readableFileSize(nonUsed));
|
||||
// double proportion = new BigDecimal(nonUsed).divide(new BigDecimal(nonMax), 2, BigDecimal.ROUND_HALF_UP).doubleValue() * 100;
|
||||
// jsonObject.put("nonHeapProportion", String.format("%.2f", proportion) + "%");
|
||||
// jsonObject.put("nonHeapCommitted", FileUtil.readableFileSize(nonCommitted));
|
||||
// return jsonObject;
|
||||
// } catch (Exception e) {
|
||||
// DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * 导出堆栈信息
|
||||
// */
|
||||
// @RequestMapping(value = "stack", method = RequestMethod.GET)
|
||||
// @ResponseBody
|
||||
// public String stack(String tag) throws Exception {
|
||||
// String fileName = ServerConfigBean.getInstance().getTempPathName() + "/" + tag + "_java_cpu.txt";
|
||||
// fileName = FileUtil.normalize(fileName);
|
||||
// try {
|
||||
// int pid = AbstractProjectCommander.getInstance().getPid(tag);
|
||||
// if (pid <= 0) {
|
||||
// return JsonMessage.getString(400, "未运行");
|
||||
// }
|
||||
// String command = String.format("jstack %s >> %s ", pid, fileName);
|
||||
// CommandUtil.execSystemCommand(command);
|
||||
// downLoad(getResponse(), fileName);
|
||||
// } catch (Exception e) {
|
||||
// DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
// getResponse().sendRedirect("internal?tag=" + tag);
|
||||
// }
|
||||
// return JsonMessage.getString(200, "");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 导出内存信息
|
||||
// */
|
||||
// @RequestMapping(value = "ram", method = RequestMethod.GET)
|
||||
// @ResponseBody
|
||||
// public String ram(String tag) throws Exception {
|
||||
// String fileName = ServerConfigBean.getInstance().getTempPathName() + "/" + tag + "_java_ram.txt";
|
||||
// fileName = FileUtil.normalize(fileName);
|
||||
// try {
|
||||
// int pid = AbstractProjectCommander.getInstance().getPid(tag);
|
||||
// if (pid <= 0) {
|
||||
// return JsonMessage.getString(400, "未运行");
|
||||
// }
|
||||
// String command = String.format("jmap -histo:live %s >> %s", pid, fileName);
|
||||
// CommandUtil.execSystemCommand(command);
|
||||
// downLoad(getResponse(), fileName);
|
||||
// } catch (Exception e) {
|
||||
// DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
// getResponse().sendRedirect("internal?tag=" + tag);
|
||||
// }
|
||||
// return JsonMessage.getString(200, "");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 下载文件
|
||||
// *
|
||||
// * @param response response
|
||||
// * @param fileName 文件名字
|
||||
// */
|
||||
// private void downLoad(HttpServletResponse response, String fileName) {
|
||||
// //获取项目根路径
|
||||
// File file = new File(fileName);
|
||||
// ServletUtil.write(response, file);
|
||||
// FileUtil.del(file);
|
||||
// }
|
||||
//}
|
||||
package cn.keepbx.jpom.controller.node.monitor;
|
||||
|
||||
import cn.keepbx.jpom.common.BaseNodeController;
|
||||
import cn.keepbx.jpom.common.forward.NodeForward;
|
||||
import cn.keepbx.jpom.common.forward.NodeUrl;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
/**
|
||||
* 内存查看
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "/node/manage/")
|
||||
public class InternalController extends BaseNodeController {
|
||||
|
||||
/**
|
||||
* 获取内存信息
|
||||
*/
|
||||
@RequestMapping(value = "internal", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
|
||||
public String getInternal(String tag) throws Exception {
|
||||
setAttribute("tag", tag);
|
||||
JSONObject data = NodeForward.requestData(getNode(), NodeUrl.Manage_internal_data, JSONObject.class, "tag", tag);
|
||||
setAttribute("data", data);
|
||||
return "node/manage/internal";
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出堆栈信息
|
||||
*/
|
||||
@RequestMapping(value = "stack", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public void stack() {
|
||||
NodeForward.requestDownload(getNode(), getRequest(), getResponse(), NodeUrl.Manage_internal_stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出内存信息
|
||||
*/
|
||||
@RequestMapping(value = "ram", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public void ram() throws Exception {
|
||||
NodeForward.requestDownload(getNode(), getRequest(), getResponse(), NodeUrl.Manage_internal_ram);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,12 @@
|
||||
package cn.keepbx.jpom.controller.node.system.nginx;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.keepbx.jpom.common.BaseNodeController;
|
||||
import cn.keepbx.jpom.common.Role;
|
||||
import cn.keepbx.jpom.common.forward.NodeForward;
|
||||
import cn.keepbx.jpom.common.forward.NodeUrl;
|
||||
import cn.keepbx.jpom.common.interceptor.UrlPermission;
|
||||
import cn.keepbx.jpom.model.data.CertModel;
|
||||
import cn.keepbx.jpom.model.data.UserModel;
|
||||
import cn.keepbx.jpom.model.data.Whitelist;
|
||||
import cn.keepbx.jpom.service.system.CertService;
|
||||
import cn.keepbx.jpom.service.system.NginxService;
|
||||
import cn.keepbx.jpom.service.system.WhitelistDirectoryService;
|
||||
import cn.keepbx.jpom.util.CommandUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.github.odiszapc.nginxparser.NgxBlock;
|
||||
import com.github.odiszapc.nginxparser.NgxConfig;
|
||||
import com.github.odiszapc.nginxparser.NgxEntry;
|
||||
import com.github.odiszapc.nginxparser.NgxParam;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -28,10 +14,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -43,21 +25,12 @@ import java.util.List;
|
||||
@RequestMapping("/node/system/nginx")
|
||||
public class NginxController extends BaseNodeController {
|
||||
|
||||
|
||||
@Resource
|
||||
private WhitelistDirectoryService whitelistDirectoryService;
|
||||
@Resource
|
||||
private CertService certService;
|
||||
|
||||
@Resource
|
||||
private NginxService nginxService;
|
||||
|
||||
@RequestMapping(value = "list.html", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
|
||||
public String ngx() {
|
||||
Whitelist ngxDirectory = whitelistDirectoryService.getData(getNode());
|
||||
setAttribute("nginx", ngxDirectory.getNginx());
|
||||
List<CertModel> certList = certService.list();
|
||||
setAttribute("cert", certList);
|
||||
return "node/system/nginx";
|
||||
}
|
||||
|
||||
@ -68,168 +41,33 @@ public class NginxController extends BaseNodeController {
|
||||
@ResponseBody
|
||||
@UrlPermission(Role.Manage)
|
||||
public String list() {
|
||||
JSONArray array = nginxService.list();
|
||||
return JsonMessage.getString(200, "", array);
|
||||
return NodeForward.request(getNode(), getRequest(), NodeUrl.System_Nginx_list_data).toString();
|
||||
}
|
||||
|
||||
@RequestMapping(value = "item.html", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
|
||||
public String setting(String path, String name, String type) {
|
||||
public String setting(String type) {
|
||||
List<String> ngxDirectory = whitelistDirectoryService.getNgxDirectory(getNode());
|
||||
setAttribute("nginx", ngxDirectory);
|
||||
List<CertModel> certList = certService.list();
|
||||
setAttribute("cert", certList);
|
||||
setAttribute("type", type);
|
||||
name = pathSafe(name);
|
||||
if (StrUtil.isNotEmpty(path) && ngxDirectory != null && ngxDirectory.contains(path)) {
|
||||
File file = FileUtil.file(path, name);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
String string = FileUtil.readUtf8String(file);
|
||||
jsonObject.put("context", string);
|
||||
jsonObject.put("name", nginxService.paresName(path, file.getAbsolutePath()));
|
||||
jsonObject.put("whitePath", path);
|
||||
setAttribute("data", jsonObject);
|
||||
}
|
||||
JSONObject data = NodeForward.requestData(getNode(), NodeUrl.System_Nginx_item_data, getRequest(), JSONObject.class);
|
||||
setAttribute("data", data);
|
||||
return "node/system/nginxSetting";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新增或修改配置
|
||||
*
|
||||
* @param name 文件名
|
||||
* @param whitePath 白名单路径
|
||||
*/
|
||||
@RequestMapping(value = "updateNgx", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
@ResponseBody
|
||||
@UrlPermission(Role.Manage)
|
||||
public String updateNgx(String name, String whitePath, String context, String genre) {
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
return JsonMessage.getString(400, "请填写文件名");
|
||||
}
|
||||
if (!name.endsWith(".conf")) {
|
||||
return JsonMessage.getString(400, "文件后缀必须为\".conf\"");
|
||||
}
|
||||
if (!checkPathSafe(name)) {
|
||||
return JsonMessage.getString(400, "文件名存在非法字符");
|
||||
}
|
||||
// if (!whitelistDirectoryService.checkNgxDirectory(whitePath)) {
|
||||
// return JsonMessage.getString(400, "请选择正确的白名单");
|
||||
// }
|
||||
//nginx文件
|
||||
File file = FileUtil.file(whitePath, name);
|
||||
if ("add".equals(genre) && file.exists()) {
|
||||
return JsonMessage.getString(400, "该文件已存在");
|
||||
}
|
||||
if (StrUtil.isEmpty(context)) {
|
||||
return JsonMessage.getString(400, "请填写配置信息");
|
||||
}
|
||||
InputStream inputStream = new ByteArrayInputStream(context.getBytes());
|
||||
try {
|
||||
NgxConfig conf = NgxConfig.read(inputStream);
|
||||
List<NgxEntry> list = conf.findAll(NgxBlock.class, "server");
|
||||
if (list == null || list.size() <= 0) {
|
||||
return JsonMessage.getString(404, "内容解析为空");
|
||||
}
|
||||
for (NgxEntry ngxEntry : list) {
|
||||
NgxBlock ngxBlock = (NgxBlock) ngxEntry;
|
||||
// 检查日志路径
|
||||
NgxParam accessLog = ngxBlock.findParam("access_log");
|
||||
if (accessLog != null) {
|
||||
FileUtil.mkParentDirs(accessLog.getValue());
|
||||
}
|
||||
accessLog = ngxBlock.findParam("error_log");
|
||||
if (accessLog != null) {
|
||||
FileUtil.mkParentDirs(accessLog.getValue());
|
||||
}
|
||||
// 检查证书文件
|
||||
NgxParam sslCertificate = ngxBlock.findParam("ssl_certificate");
|
||||
if (sslCertificate != null && !FileUtil.exist(sslCertificate.getValue())) {
|
||||
return JsonMessage.getString(404, "证书文件ssl_certificate,不存在");
|
||||
}
|
||||
NgxParam sslCertificateKey = ngxBlock.findParam("ssl_certificate_key");
|
||||
if (sslCertificateKey != null && !FileUtil.exist(sslCertificateKey.getValue())) {
|
||||
return JsonMessage.getString(404, "证书文件ssl_certificate_key,不存在");
|
||||
}
|
||||
if (!checkRootRole(ngxBlock)) {
|
||||
return JsonMessage.getString(405, "非系统管理员,不能配置静态资源代理");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
DefaultSystemLog.ERROR().error("解析失败", e);
|
||||
return JsonMessage.getString(500, "解析失败");
|
||||
}
|
||||
try {
|
||||
FileUtil.writeString(context, file, CharsetUtil.UTF_8);
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error(e.getMessage(), e);
|
||||
return JsonMessage.getString(400, "操作失败:" + e.getMessage());
|
||||
}
|
||||
String msg = this.reloadNginx();
|
||||
return JsonMessage.getString(200, "提交成功" + msg);
|
||||
public String updateNgx() {
|
||||
return NodeForward.request(getNode(), getRequest(), NodeUrl.System_Nginx_updateNgx).toString();
|
||||
}
|
||||
|
||||
private String reloadNginx() {
|
||||
try {
|
||||
String msg = CommandUtil.execSystemCommand("nginx -s reload");
|
||||
if (StrUtil.isNotEmpty(msg)) {
|
||||
DefaultSystemLog.LOG().info(msg);
|
||||
return "(" + msg + ")";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error("reload nginx error", e);
|
||||
}
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限检查 防止非系统管理员配置静态资源访问
|
||||
*
|
||||
* @return false 不正确
|
||||
*/
|
||||
private boolean checkRootRole(NgxBlock ngxBlock) {
|
||||
UserModel userModel = getUser();
|
||||
List<NgxEntry> locationAll = ngxBlock.findAll(NgxBlock.class, "location");
|
||||
if (locationAll != null) {
|
||||
for (NgxEntry ngxEntry1 : locationAll) {
|
||||
NgxBlock ngxBlock1 = (NgxBlock) ngxEntry1;
|
||||
NgxParam locationMain = ngxBlock1.findParam("root");
|
||||
if (locationMain == null) {
|
||||
locationMain = ngxBlock1.findParam("alias");
|
||||
}
|
||||
if (locationMain != null && !userModel.isSystemUser()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除配置
|
||||
*
|
||||
* @param path 文件路径
|
||||
*/
|
||||
@RequestMapping(value = "delete", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
@ResponseBody
|
||||
@UrlPermission(Role.Manage)
|
||||
public String delete(String path, String name) {
|
||||
// if (!whitelistDirectoryService.checkNgxDirectory(path)) {
|
||||
// return JsonMessage.getString(400, "非法操作");
|
||||
// }
|
||||
path = pathSafe(path);
|
||||
name = pathSafe(name);
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
return JsonMessage.getString(400, "删除失败,请正常操作");
|
||||
}
|
||||
File file = FileUtil.file(path, name);
|
||||
try {
|
||||
FileUtil.rename(file, file.getName() + "_back", false, true);
|
||||
} catch (Exception e) {
|
||||
DefaultSystemLog.ERROR().error("删除nginx", e);
|
||||
return JsonMessage.getString(400, "删除失败:" + e.getMessage());
|
||||
}
|
||||
String msg = this.reloadNginx();
|
||||
return JsonMessage.getString(200, "删除成功" + msg);
|
||||
public String delete() {
|
||||
return NodeForward.request(getNode(), getRequest(), NodeUrl.System_Nginx_delete).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,22 +1,11 @@
|
||||
package cn.keepbx.jpom.controller.node.system.ssl;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.jiangzeyin.common.DefaultSystemLog;
|
||||
import cn.jiangzeyin.common.JsonMessage;
|
||||
import cn.jiangzeyin.controller.multipart.MultipartFileBuilder;
|
||||
import cn.keepbx.jpom.common.BaseController;
|
||||
import cn.keepbx.jpom.common.BaseNodeController;
|
||||
import cn.keepbx.jpom.common.Role;
|
||||
import cn.keepbx.jpom.common.forward.NodeForward;
|
||||
import cn.keepbx.jpom.common.forward.NodeUrl;
|
||||
import cn.keepbx.jpom.common.interceptor.UrlPermission;
|
||||
import cn.keepbx.jpom.model.data.CertModel;
|
||||
import cn.keepbx.jpom.model.data.UserModel;
|
||||
import cn.keepbx.jpom.service.system.CertService;
|
||||
import cn.keepbx.jpom.system.ServerConfigBean;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
|
||||
import cn.keepbx.jpom.service.system.WhitelistDirectoryService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -24,13 +13,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 证书管理
|
||||
@ -39,17 +22,15 @@ import java.util.zip.ZipFile;
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "/node/system/certificate")
|
||||
public class CertificateController extends BaseController {
|
||||
public class CertificateController extends BaseNodeController {
|
||||
|
||||
@Resource
|
||||
private CertService certService;
|
||||
// @Resource
|
||||
// private WhitelistDirectoryService whitelistDirectoryService;
|
||||
private WhitelistDirectoryService whitelistDirectoryService;
|
||||
|
||||
@RequestMapping(value = "/list.html", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
|
||||
public String certificate() {
|
||||
// JSONArray jsonArray = whitelistDirectoryService.getCertificateDirectory();
|
||||
// setAttribute("certificate", jsonArray);
|
||||
List<String> jsonArray = whitelistDirectoryService.getCertificateDirectory(getNode());
|
||||
setAttribute("certificate", jsonArray);
|
||||
return "node/system/certificate";
|
||||
}
|
||||
|
||||
@ -63,165 +44,7 @@ public class CertificateController extends BaseController {
|
||||
@ResponseBody
|
||||
@UrlPermission(Role.Manage)
|
||||
public String saveCertificate() {
|
||||
String data = getParameter("data");
|
||||
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
String type = jsonObject.getString("type");
|
||||
String id = jsonObject.getString("id");
|
||||
try {
|
||||
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, "提交成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取证书信息
|
||||
*
|
||||
* @param certModel 实体
|
||||
* @return 错误消息
|
||||
*/
|
||||
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)) {
|
||||
return JsonMessage.getString(400, "请填写证书id");
|
||||
}
|
||||
if (Validator.isChinese(id)) {
|
||||
return JsonMessage.getString(400, "证书id不能使用中文");
|
||||
}
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
return JsonMessage.getString(400, "请填写证书名称");
|
||||
}
|
||||
// if (!whitelistDirectoryService.checkCertificateDirectory(path)) {
|
||||
// return JsonMessage.getString(400, "请选择正确的项目路径,或者还没有配置白名单");
|
||||
// }
|
||||
certModel.setId(id);
|
||||
certModel.setWhitePath(path);
|
||||
certModel.setName(name);
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getCertFile(CertModel certModel, boolean add) throws IOException {
|
||||
String certPath = null;
|
||||
String pemPath = null, keyPath = null;
|
||||
try {
|
||||
String path = ServerConfigBean.getInstance().getTempPathName();
|
||||
MultipartFileBuilder cert = createMultipart().addFieldName("file").setSavePath(path);
|
||||
certPath = cert.save();
|
||||
ZipFile zipFile = new ZipFile(certPath);
|
||||
Enumeration<? extends ZipEntry> 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<CertModel> 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");
|
||||
if (add) {
|
||||
if (pemFile.exists()) {
|
||||
return JsonMessage.getString(405, pemFile.getAbsolutePath() + " 已经被占用啦");
|
||||
}
|
||||
if (keyFile.exists()) {
|
||||
return JsonMessage.getString(405, keyFile.getAbsolutePath() + " 已经被占用啦");
|
||||
}
|
||||
}
|
||||
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;
|
||||
return NodeForward.requestMultipart(getNode(), getMultiRequest(), NodeUrl.System_Certificate_saveCertificate).toString();
|
||||
}
|
||||
|
||||
|
||||
@ -232,8 +55,7 @@ public class CertificateController extends BaseController {
|
||||
@ResponseBody
|
||||
@UrlPermission(Role.Manage)
|
||||
public String getCertList() {
|
||||
List<CertModel> array = certService.list();
|
||||
return JsonMessage.getString(200, "", array);
|
||||
return NodeForward.request(getNode(), getRequest(), NodeUrl.System_Certificate_getCertList).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,18 +68,7 @@ public class CertificateController extends BaseController {
|
||||
@ResponseBody
|
||||
@UrlPermission(Role.System)
|
||||
public String delete(String id) {
|
||||
if (StrUtil.isEmpty(id)) {
|
||||
return JsonMessage.getString(400, "删除失败");
|
||||
}
|
||||
UserModel userModel = getUser();
|
||||
if (!userModel.isSystemUser()) {
|
||||
return JsonMessage.getString(400, "你没有操作权限");
|
||||
}
|
||||
boolean b = certService.delete(id);
|
||||
if (!b) {
|
||||
return JsonMessage.getString(400, "删除失败");
|
||||
}
|
||||
return JsonMessage.getString(200, "删除成功");
|
||||
return NodeForward.request(getNode(), getRequest(), NodeUrl.System_Certificate_delete).toString();
|
||||
}
|
||||
|
||||
|
||||
@ -267,15 +78,7 @@ public class CertificateController extends BaseController {
|
||||
@RequestMapping(value = "/export", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
@ResponseBody
|
||||
@UrlPermission(Role.Manage)
|
||||
public String export(String id) {
|
||||
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, "导出成功");
|
||||
public void export(String id) {
|
||||
NodeForward.requestDownload(getNode(), getRequest(), getResponse(), NodeUrl.System_Certificate_export);
|
||||
}
|
||||
}
|
||||
|
@ -295,4 +295,14 @@ public class UserModel extends BaseModel {
|
||||
public void setModifyTime(long modifyTime) {
|
||||
this.modifyTime = modifyTime;
|
||||
}
|
||||
|
||||
public static String getOptUserName(UserModel userModel) {
|
||||
String userId;
|
||||
if (userModel.isSystemUser()) {
|
||||
userId = UserModel.SYSTEM_OCCUPY_NAME;
|
||||
} else {
|
||||
userId = userModel.getId();
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
@Component
|
||||
public class ServerWebSocketHandle {
|
||||
|
||||
|
||||
private NodeService nodeService;
|
||||
private static volatile AtomicInteger onlineCount = new AtomicInteger();
|
||||
private static final ConcurrentHashMap<String, UserModel> USER = new ConcurrentHashMap<>();
|
||||
@ -84,17 +83,14 @@ public class ServerWebSocketHandle {
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
public void onMessage(String message, Session session) throws IOException {
|
||||
UserModel userModel = USER.get(session.getId());
|
||||
if (userModel == null) {
|
||||
SocketSessionUtil.send(session, "回话信息失效,刷新网页再试");
|
||||
return;
|
||||
}
|
||||
ProxySession proxySession = getSession(session);
|
||||
proxySession.send(message);
|
||||
// UserModel userModel = USER.get(session.getId());
|
||||
// if (userModel == null) {
|
||||
// SocketSessionUtil.send(session, "回话信息失效,刷新网页再试");
|
||||
// return;
|
||||
// }
|
||||
// System.out.println(op);
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
private void destroy(Session session) {
|
||||
|
@ -1,23 +1,12 @@
|
||||
package cn.keepbx.jpom.system;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.jiangzeyin.common.spring.SpringUtil;
|
||||
import cn.keepbx.jpom.common.BaseController;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 配置信息静态变量类
|
||||
*
|
||||
* @author jiangzeyin
|
||||
* @date 2019/1/16
|
||||
*/
|
||||
@Configuration
|
||||
public class ServerConfigBean {
|
||||
|
||||
private static ServerConfigBean serverConfigBean;
|
||||
/**
|
||||
* 用户数据文件
|
||||
*/
|
||||
@ -27,36 +16,4 @@ public class ServerConfigBean {
|
||||
* 节点数据文件
|
||||
*/
|
||||
public static final String NODE = "node.json";
|
||||
|
||||
|
||||
/**
|
||||
* 证书文件
|
||||
*/
|
||||
public static final String CERT = "cert.json";
|
||||
|
||||
|
||||
/**
|
||||
* 单利模式
|
||||
*
|
||||
* @return config
|
||||
*/
|
||||
public static ServerConfigBean getInstance() {
|
||||
if (serverConfigBean == null) {
|
||||
serverConfigBean = SpringUtil.getBean(ServerConfigBean.class);
|
||||
}
|
||||
return serverConfigBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户的临时文件存储路径,如果没有登录则抛出异常
|
||||
*
|
||||
* @return 文件夹
|
||||
*/
|
||||
public String getTempPathName() {
|
||||
// File file = getTempPath();
|
||||
return null;
|
||||
// return FileUtil.normalize(file.getPath());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import java.util.concurrent.TimeUnit;
|
||||
@Configuration
|
||||
public class ServerExtConfigBean {
|
||||
|
||||
|
||||
/**
|
||||
* 系统最多能创建多少用户
|
||||
*/
|
||||
@ -29,23 +28,6 @@ public class ServerExtConfigBean {
|
||||
*/
|
||||
@Value("${user.alwaysLoginError:5}")
|
||||
public int userAlwaysLoginError;
|
||||
/**
|
||||
* 自动备份控制台日志,防止日志文件过大,目前暂只支持linux 不停服备份 如果配置none 则不自动备份 默认10分钟扫描一次
|
||||
*/
|
||||
@Value("${log.autoBackConsoleCron:0 0/10 * * * ?}")
|
||||
public String autoBackConsoleCron;
|
||||
/**
|
||||
* 当文件多大时自动备份
|
||||
*
|
||||
* @see ch.qos.logback.core.util.FileSize
|
||||
*/
|
||||
@Value("${log.autoBackSize:50MB}")
|
||||
public String autoBackSize;
|
||||
/**
|
||||
* 控制台日志保存时长单位天
|
||||
*/
|
||||
@Value("${log.saveDays:7}")
|
||||
private int logSaveDays;
|
||||
|
||||
/**
|
||||
* 当ip连续登录失败,锁定对应IP时长,单位毫秒
|
||||
@ -62,19 +44,6 @@ public class ServerExtConfigBean {
|
||||
return this.ipErrorLockTimeValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配置错误或者没有,默认是7天
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getLogSaveDays() {
|
||||
if (logSaveDays <= 0) {
|
||||
return 7;
|
||||
}
|
||||
return logSaveDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*
|
||||
|
@ -40,6 +40,11 @@
|
||||
layui.each(asyncFn, function () {
|
||||
this && this();
|
||||
})
|
||||
|
||||
$("button[op='a']").click(function () {
|
||||
var href = $(this).attr("href");
|
||||
location.href = appendNodeId(href);
|
||||
});
|
||||
});
|
||||
|
||||
function appendNodeId(url) {
|
||||
@ -194,7 +199,7 @@
|
||||
|
||||
|
||||
## 文件上传渲染
|
||||
function uploadRender(data) {
|
||||
function uploadRender(data, fn) {
|
||||
layui.use(['upload'], function () {
|
||||
var upload = layui.upload;
|
||||
var newsData = {
|
||||
@ -206,7 +211,8 @@
|
||||
data: newsData
|
||||
};
|
||||
$.extend(defData, data);
|
||||
return upload.render(defData);
|
||||
var uploadResult = upload.render(defData);
|
||||
fn && fn(uploadResult);
|
||||
});
|
||||
}
|
||||
</script>
|
@ -48,15 +48,22 @@
|
||||
<body class="layui-layout-body">
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
<div class="layui-header">
|
||||
|
||||
<div class="layui-logo">
|
||||
<a href="../index.html" class="layui-btn layui-btn-sm layui-btn-primary">
|
||||
<i class="layui-icon"></i>
|
||||
</a>
|
||||
<span title="版本时间:$!jpomManifest.timeStamp,进程ID:$!jpomManifest.pid">
|
||||
<form class="layui-form" action="">
|
||||
<div class="layui-logo" title="版本时间:$!jpomManifest.timeStamp,进程ID:$!jpomManifest.pid">
|
||||
$node.name #if($jpomManifest)<font style="font-size: 10px;">($jpomManifest.version)</font>#end
|
||||
</span>
|
||||
</div>
|
||||
## <div class="layui-form-item" style="margin-top: 10px;">
|
||||
## <label class="layui-form-label">节点列表</label>
|
||||
## <div class="layui-input-block">
|
||||
## <select name="city" lay-verify="required">
|
||||
## #foreach($itemNode in $array)
|
||||
## <option value="$itemNode.id">$itemNode.name</option>
|
||||
## #end
|
||||
## </select>
|
||||
## </div>
|
||||
## </div>
|
||||
## </span>
|
||||
</div>
|
||||
</form>
|
||||
<ul class="layui-nav layui-layout-left">
|
||||
|
||||
</ul>
|
||||
|
@ -34,7 +34,7 @@
|
||||
<button name="install" data-name="$item.shortKey" data-key="$item.key" data-id="$id"
|
||||
class="layui-btn layui-btn-danger layui-btn-sm">安装
|
||||
</button>
|
||||
<button name="download" href="build_download?key=$item.key&id=$id"
|
||||
<button op="a" href="build_download?key=$item.key&id=$id"
|
||||
class="layui-btn layui-btn-warm layui-btn-sm">下载
|
||||
</button>
|
||||
</td>
|
||||
@ -81,11 +81,6 @@
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
$("button[name='download']").click(function () {
|
||||
var href = $(this).attr("href");
|
||||
location.href = appendNodeId(href);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</html>
|
@ -25,8 +25,8 @@
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<a class="layui-btn layui-btn-sm layui-btn-normal" href="/manage/stack?tag=$!tag">导出堆栈信息</a>
|
||||
<a class="layui-btn layui-btn-sm layui-btn-normal" href="/manage/ram?tag=$!tag">导出内存信息</a>
|
||||
<button op="a" class="layui-btn layui-btn-sm layui-btn-normal" href="./stack?tag=$!tag">导出堆栈信息</button>
|
||||
<button op="a" class="layui-btn layui-btn-sm layui-btn-normal" href="./ram?tag=$!tag">导出内存信息</button>
|
||||
</div>
|
||||
<div class="info">
|
||||
<label>系统内存</label>
|
||||
@ -48,20 +48,20 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#if($item)
|
||||
#if($data.process)
|
||||
<tr>
|
||||
<td>$!item.pid</td>
|
||||
<td>$!item.command</td>
|
||||
<td>$!item.user</td>
|
||||
<td>$!item.res</td>
|
||||
<td>$!item.status</td>
|
||||
<td>$!item.cpu</td>
|
||||
<td>$!item.mem</td>
|
||||
<td>$!item.time</td>
|
||||
<td>$!item.pr</td>
|
||||
<td>$!item.ni</td>
|
||||
<td>$!item.virt</td>
|
||||
<td>$!item.shr</td>
|
||||
<td>$!data.process.pid</td>
|
||||
<td>$!data.process.command</td>
|
||||
<td>$!data.process.user</td>
|
||||
<td>$!data.process.res</td>
|
||||
<td>$!data.process.status</td>
|
||||
<td>$!data.process.cpu</td>
|
||||
<td>$!data.process.mem</td>
|
||||
<td>$!data.process.time</td>
|
||||
<td>$!data.process.pr</td>
|
||||
<td>$!data.process.ni</td>
|
||||
<td>$!data.process.virt</td>
|
||||
<td>$!data.process.shr</td>
|
||||
</tr>
|
||||
#else
|
||||
<tr>
|
||||
@ -72,7 +72,7 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
#if($beanMem)
|
||||
#if($data.beanMem)
|
||||
<div class="info">
|
||||
<label> jvm内存</label>
|
||||
<table class="layui-table" style="margin-top: 10px">
|
||||
@ -89,13 +89,13 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>$!beanMem.heapUsed</td>
|
||||
<td>$!beanMem.heapProportion</td>
|
||||
<td>$!beanMem.heapCommitted</td>
|
||||
<td>$!beanMem.nonHeapUsed</td>
|
||||
<td>$!beanMem.nonHeapProportion</td>
|
||||
<td>$!beanMem.nonHeapCommitted</td>
|
||||
<td>$!beanMem.mount</td>
|
||||
<td>$!data.beanMem.heapUsed</td>
|
||||
<td>$!data.beanMem.heapProportion</td>
|
||||
<td>$!data.beanMem.heapCommitted</td>
|
||||
<td>$!data.beanMem.nonHeapUsed</td>
|
||||
<td>$!data.beanMem.nonHeapProportion</td>
|
||||
<td>$!data.beanMem.nonHeapCommitted</td>
|
||||
<td>$!data.beanMem.mount</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -119,19 +119,19 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#if($port)
|
||||
#foreach($item in $!port)
|
||||
<tr>
|
||||
<td>$!item.name</td>
|
||||
<td>$!item.protocol</td>
|
||||
<td>$!item.local</td>
|
||||
<td>$!item.foreign</td>
|
||||
<td>$!item.status</td>
|
||||
<td>$!item.receive</td>
|
||||
<td>$!item.send</td>
|
||||
</tr>
|
||||
#end
|
||||
#else
|
||||
#foreach($item in $data.netstat)
|
||||
#set($hashNetStat=true)
|
||||
<tr>
|
||||
<td>$!item.name</td>
|
||||
<td>$!item.protocol</td>
|
||||
<td>$!item.local</td>
|
||||
<td>$!item.foreign</td>
|
||||
<td>$!item.status</td>
|
||||
<td>$!item.receive</td>
|
||||
<td>$!item.send</td>
|
||||
</tr>
|
||||
#end
|
||||
#if(!$hashNetStat)
|
||||
<tr>
|
||||
<td colspan=7 style="text-align:center">无数据</td>
|
||||
</tr>
|
||||
|
@ -44,7 +44,7 @@
|
||||
<td>$item.modifytime</td>
|
||||
<td>$item.filesize</td>
|
||||
<td>
|
||||
<button name="download" href="logBack_download?key=$item.filename&id=$data.id"
|
||||
<button op="a" href="logBack_download?key=$item.filename&id=$data.id"
|
||||
class="layui-btn layui-btn-warm layui-btn-sm">下载
|
||||
</button>
|
||||
<button name="delete" data-name="$item.filename" data-id="$data.id"
|
||||
@ -91,11 +91,6 @@
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
$("button[name='download']").click(function () {
|
||||
var href = $(this).attr("href");
|
||||
location.href = appendNodeId(href);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</html>
|
@ -128,14 +128,13 @@
|
||||
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
|
||||
}
|
||||
|
||||
var laytpl, upload;
|
||||
var laytpl;
|
||||
|
||||
function loadSuccess() {
|
||||
var uploadConfig, hashSelectConfig, updateFormData;
|
||||
layui.use(['laytpl', 'upload'], function () {
|
||||
layui.use(['laytpl'], function () {
|
||||
laytpl = layui.laytpl;
|
||||
upload = layui.upload;
|
||||
uploadConfig = upload.render({
|
||||
uploadRender({
|
||||
elem: '#selectZip',
|
||||
url: './saveCertificate',
|
||||
multiple: false,
|
||||
@ -169,6 +168,8 @@
|
||||
error: function () {
|
||||
layer.msg("上传失败");
|
||||
}
|
||||
}, function (data) {
|
||||
uploadConfig = data;
|
||||
});
|
||||
tableRender({
|
||||
id: 'tab_certificate',
|
||||
|
Loading…
Reference in New Issue
Block a user