操作日志简单筛选

This commit is contained in:
jiangzeyin 2019-04-23 12:05:12 +08:00
parent d777095597
commit bee68c5d83
8 changed files with 129 additions and 26 deletions

View File

@ -8,7 +8,7 @@
2. 多节点统一管理(插件模式) 2. 多节点统一管理(插件模式)
3. 证书解析支持cer 证书(感谢@JAVA jesion) 3. 证书解析支持cer 证书(感谢@JAVA jesion)
4. 新增记录用户操作日志[采用H2数据库](感谢@〓下页) 4. 新增记录用户操作日志[采用H2数据库](感谢@〓下页)
5. 节点分发功能 5. 节点分发功能、合并管理项目
### 解决BUG、优化功能 ### 解决BUG、优化功能
@ -16,6 +16,7 @@
2. 进程id解析端口、解析项目名称带缓存 2. 进程id解析端口、解析项目名称带缓存
3. 项目分组变更,项目列表及时刷新(感谢@〓下页) 3. 项目分组变更,项目列表及时刷新(感谢@〓下页)
4. 批量上传文件数量进度显示(感谢@群友) 4. 批量上传文件数量进度显示(感谢@群友)
5. linux udp端口信息解析失败(感谢@Ruby)
----------------------------------------------------------- -----------------------------------------------------------

View File

@ -2,9 +2,9 @@
1. 程序宕机处理 1. 程序宕机处理
2. 主要管理页面兼容移动端 2. 主要管理页面兼容移动端
3. 项目监控完善 3. ssl 到期提醒、快捷续签
4. ssl 到期提醒、快捷续签
### 待优化解决 ### 待优化解决
1. 支持更多压缩包 1. 支持更多压缩包
2. 项目监控完善

View File

@ -190,21 +190,35 @@ public class NodeForward {
} }
private static void addUser(HttpRequest httpRequest, NodeModel nodeModel) { private static void addUser(HttpRequest httpRequest, NodeModel nodeModel) {
// 判断开启状态
if (!nodeModel.isOpenStatus()) {
throw new JpomRuntimeException(nodeModel.getName() + "节点未启用");
}
UserModel userModel = BaseServerController.getUserModel(); UserModel userModel = BaseServerController.getUserModel();
addUser(httpRequest, nodeModel, userModel); addUser(httpRequest, nodeModel, userModel);
} }
/**
* 添加agent 授权信息header
*
* @param httpRequest request
* @param nodeModel 节点
* @param userModel 用户
*/
public static void addUser(HttpRequest httpRequest, NodeModel nodeModel, UserModel userModel) { public static void addUser(HttpRequest httpRequest, NodeModel nodeModel, UserModel userModel) {
Objects.requireNonNull(userModel); Objects.requireNonNull(userModel);
// 判断开启状态
if (!nodeModel.isOpenStatus()) {
throw new JpomRuntimeException(nodeModel.getName() + "节点未启用");
}
httpRequest.header(ConfigBean.JPOM_SERVER_USER_NAME, UserModel.getOptUserName(userModel)); httpRequest.header(ConfigBean.JPOM_SERVER_USER_NAME, UserModel.getOptUserName(userModel));
httpRequest.header(ConfigBean.JPOM_SERVER_SYSTEM_USER_ROLE, userModel.getUserRole(nodeModel).name()); httpRequest.header(ConfigBean.JPOM_SERVER_SYSTEM_USER_ROLE, userModel.getUserRole(nodeModel).name());
httpRequest.header(ConfigBean.JPOM_AGENT_AUTHORIZE, nodeModel.getAuthorize(true)); httpRequest.header(ConfigBean.JPOM_AGENT_AUTHORIZE, nodeModel.getAuthorize(true));
} }
/**
* 获取节点socket 信息
*
* @param nodeModel 节点信息
* @param nodeUrl url
* @return url
*/
public static String getSocketUrl(NodeModel nodeModel, NodeUrl nodeUrl) { public static String getSocketUrl(NodeModel nodeModel, NodeUrl nodeUrl) {
String ws; String ws;
if ("https".equalsIgnoreCase(nodeModel.getProtocol())) { if ("https".equalsIgnoreCase(nodeModel.getProtocol())) {

View File

@ -12,7 +12,7 @@ import cn.keepbx.jpom.model.data.NodeModel;
import cn.keepbx.jpom.model.data.UserModel; import cn.keepbx.jpom.model.data.UserModel;
import cn.keepbx.jpom.service.manage.ProjectInfoService; import cn.keepbx.jpom.service.manage.ProjectInfoService;
import cn.keepbx.jpom.service.node.NodeService; import cn.keepbx.jpom.service.node.NodeService;
import cn.keepbx.jpom.system.JpomRuntimeException; import cn.keepbx.jpom.system.AgentException;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
@ -48,7 +48,7 @@ public class PermissionInterceptor extends BaseInterceptor {
// 节点信息 // 节点信息
NodeModel nodeModel = nodeService.getItem(nodeId); NodeModel nodeModel = nodeService.getItem(nodeId);
if (nodeModel != null && !nodeModel.isOpenStatus()) { if (nodeModel != null && !nodeModel.isOpenStatus()) {
throw new JpomRuntimeException(nodeModel.getName() + "节点未启用"); throw new AgentException(nodeModel.getName() + "节点未启用");
} }
request.setAttribute("node", nodeModel); request.setAttribute("node", nodeModel);
} }
@ -61,12 +61,6 @@ public class PermissionInterceptor extends BaseInterceptor {
return false; return false;
} }
// ProjectInfoModel projectInfoModel = projectInfoService.getItem(val);
// if (projectInfoModel == null) {
// JsonMessage jsonMessage = new JsonMessage(300, "没有找到对应项目");
// ServletUtil.write(response, jsonMessage.toString(), MediaType.APPLICATION_JSON_UTF8_VALUE);
// return false;
// }
if (!userModel.isProject(nodeId, val)) { if (!userModel.isProject(nodeId, val)) {
JsonMessage jsonMessage = new JsonMessage(300, "你没有改项目的权限"); JsonMessage jsonMessage = new JsonMessage(300, "你没有改项目的权限");
ServletUtil.write(response, jsonMessage.toString(), MediaType.APPLICATION_JSON_UTF8_VALUE); ServletUtil.write(response, jsonMessage.toString(), MediaType.APPLICATION_JSON_UTF8_VALUE);

View File

@ -2,6 +2,10 @@ package cn.keepbx.jpom.controller.user.log;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db; import cn.hutool.db.Db;
import cn.hutool.db.Entity; import cn.hutool.db.Entity;
import cn.hutool.db.Page; import cn.hutool.db.Page;
@ -10,7 +14,9 @@ import cn.hutool.db.sql.Direction;
import cn.hutool.db.sql.Order; import cn.hutool.db.sql.Order;
import cn.jiangzeyin.common.JsonMessage; import cn.jiangzeyin.common.JsonMessage;
import cn.keepbx.jpom.common.BaseServerController; import cn.keepbx.jpom.common.BaseServerController;
import cn.keepbx.jpom.model.data.NodeModel;
import cn.keepbx.jpom.model.data.UserOperateLogV1; import cn.keepbx.jpom.model.data.UserOperateLogV1;
import cn.keepbx.jpom.service.node.NodeService;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -19,7 +25,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
/** /**
* 用户操作日志 * 用户操作日志
@ -30,12 +38,17 @@ import java.sql.SQLException;
@Controller @Controller
@RequestMapping(value = "/user/log") @RequestMapping(value = "/user/log")
public class UserOptLogController extends BaseServerController { public class UserOptLogController extends BaseServerController {
@Resource
private NodeService nodeService;
/** /**
* 展示用户列表 * 展示用户列表
*/ */
@RequestMapping(value = "list.html", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE) @RequestMapping(value = "list.html", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
public String projectInfo() { public String projectInfo() {
// 所有节点
List<NodeModel> nodeModels = nodeService.list();
setAttribute("nodeArray", nodeModels);
return "user/log/list"; return "user/log/list";
} }
@ -45,12 +58,31 @@ public class UserOptLogController extends BaseServerController {
*/ */
@RequestMapping(value = "list_data.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @RequestMapping(value = "list_data.json", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody @ResponseBody
public String listData() throws SQLException { public String listData(String time) throws SQLException {
int limit = getParameterInt("limit", 10); int limit = getParameterInt("limit", 10);
int page1 = getParameterInt("page", 1); int page1 = getParameterInt("page", 1);
Page page = new Page(page1, limit); Page page = new Page(page1, limit);
Entity entity = Entity.create(UserOperateLogV1.TABLE_NAME); Entity entity = Entity.create(UserOperateLogV1.TABLE_NAME);
page.addOrder(new Order("optTime", Direction.DESC)); page.addOrder(new Order("optTime", Direction.DESC));
// 时间
if (StrUtil.isNotEmpty(time)) {
String[] val = StrUtil.split(time, "~");
if (val.length == 2) {
DateTime startDateTime = DateUtil.parse(val[0], DatePattern.NORM_DATETIME_FORMAT);
entity.set("optTime", ">= " + startDateTime.getTime());
DateTime endDateTime = DateUtil.parse(val[1], DatePattern.NORM_DATETIME_FORMAT);
if (startDateTime.equals(endDateTime)) {
endDateTime = DateUtil.endOfDay(endDateTime);
}
entity.set("optTime ", "<= " + endDateTime.getTime());
}
}
String selectNode = getParameter("selectNode");
if (StrUtil.isNotEmpty(selectNode)) {
entity.set("nodeId ", selectNode);
}
PageResult<Entity> pageResult = Db.use().page(entity, page); PageResult<Entity> pageResult = Db.use().page(entity, page);
CopyOptions copyOptions = new CopyOptions(); CopyOptions copyOptions = new CopyOptions();
copyOptions.setIgnoreError(true); copyOptions.setIgnoreError(true);

View File

@ -31,9 +31,9 @@ public class InitDb {
// //
if (JpomManifest.getInstance().isDebug()) { if (JpomManifest.getInstance().isDebug()) {
setting.set("showSql", "true"); setting.set("showSql", "true");
setting.set("sqlLevel", "INFO");
setting.set("showParams", "true"); setting.set("showParams", "true");
} }
try { try {
DSFactory dsFactory = DSFactory.create(setting); DSFactory dsFactory = DSFactory.create(setting);
DSFactory.setCurrentDSFactory(dsFactory); DSFactory.setCurrentDSFactory(dsFactory);

View File

@ -23,7 +23,7 @@
#if(!$item) #if(!$item)
<div class="layui-form-item"> <div class="layui-form-item">
<blockquote class="layui-elem-quote layui-quote-nm"> <blockquote class="layui-elem-quote layui-quote-nm">
创建分发项目是在不同的节点新创建对应项目(项目路径为节点白名单中的值,然后所有节点都将自动配置对应的白名单) 创建分发项目是在不同的节点新创建对应项目(项目路径为节点白名单中的值,然后所有节点都将自动配置对应的白名单),项目id、项目名称和分发id、分发名称同步
</blockquote> </blockquote>
</div> </div>
#end #end

View File

@ -13,7 +13,7 @@
<body> <body>
<div class="layui-row"> <div class="layui-row">
<button id="refresh" class="layui-btn layui-btn-sm">刷新表格</button> <button onclick="reloadTable();" class="layui-btn layui-btn-sm">刷新表格</button>
</div> </div>
<table class="layui-table" id="tab_user" lay-filter="tab_user" style="margin: 0;"></table> <table class="layui-table" id="tab_user" lay-filter="tab_user" style="margin: 0;"></table>
<script type="text/html" id="bar_projects"> <script type="text/html" id="bar_projects">
@ -42,13 +42,44 @@
</div> </div>
</script> </script>
</body> </body>
<script type="text/html" id="toolbarDemo">
<form class="layui-form" action="">
<div class="layui-form-item" style="margin-bottom: 0;">
<div class="layui-inline">
<label class="layui-form-label" style="width: auto !important;">时间</label>
<div class="layui-input-inline" style="width: 300px;">
<input type="text" class="layui-input" id="time" placeholder="请选择时间范围">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label" style="width: auto !important;">节点</label>
<div class="layui-input-inline">
<select name="selectNode" id="selectNode" lay-verify="required" lay-filter="selectNode"
lay-search="">
<option value="">请选择</option>
<option value="-">无节点操作</option>
#foreach($item in $nodeArray)
<option value="$item.id">$item.name</option>
#end
</select>
</div>
</div>
</div>
</form>
</script>
<script type="text/javascript"> <script type="text/javascript">
const apiWhere = {};
var laydate;
function loadSuccess() { function loadSuccess() {
tableRender({ tableRender({
id: 'tab_user', id: 'tab_user',
elem: '#tab_user', elem: '#tab_user',
url: './list_data.json', url: './list_data.json',
toolbar: '#toolbarDemo',
page: true, page: true,
where: apiWhere,
cols: [[ cols: [[
{field: 'userId', title: '操作者'}, {field: 'userId', title: '操作者'},
{field: 'ip', title: '操作ip'}, {field: 'ip', title: '操作ip'},
@ -70,15 +101,16 @@
"count": data.total, "count": data.total,
"data": data.data "data": data.data
}; };
},
done: function () {
$("#time").val(apiWhere.time);
renderDate();
// 选中
$("#selectNode option[value='" + apiWhere.selectNode + "']").attr("selected", "selected");
form.render();
} }
}); });
// '刷新表格'点击事件
$('#refresh').on('click', function () {
table.reload('tab_user', {});
});
layui.use(['laytpl'], function () { layui.use(['laytpl'], function () {
var laytpl = layui.laytpl; var laytpl = layui.laytpl;
var showBox = document.getElementById('showBox').innerHTML; var showBox = document.getElementById('showBox').innerHTML;
@ -98,7 +130,37 @@
} }
}); });
}); });
layui.use('laydate', function () {
laydate = layui.laydate;
renderDate();
});
form.on('select(selectNode)', function (data) {
apiWhere.selectNode = data.value;
reloadTable();
return true;
});
}
function renderDate() {
var now = new Date().getTime();
laydate.render({
elem: '#time',
type: 'datetime',
range: "~",
max: now,
done: function (value, date, endDate) {
apiWhere.time = value;
reloadTable();
}
});
}
function reloadTable() {
table.reload('tab_user', {
where: apiWhere
});
} }
</script> </script>
</html> </html>