fix(系统设置): 插件管理操作添加日志

--bug=1019390 --user=李玉号 【系统设置】操作日志对象功能类型不全,缺少用户组和权限/插件管理/配额管理/项目管理
https://www.tapd.cn/55049933/s/1307148
This commit is contained in:
shiziyuan9527 2022-11-28 17:23:20 +08:00 committed by CaptainB
parent 2b3660d7b7
commit dfc96c3deb
14 changed files with 110 additions and 1 deletions

View File

@ -41,6 +41,12 @@
#{item} #{item}
</foreach> </foreach>
</if> </if>
<if test="request.levelModules != null and request.levelModules != ''">
AND t.oper_module IN
<foreach collection="request.levelModules" index="index" open="(" close=")" separator="," item="item">
#{item}
</foreach>
</if>
<if test="request.startTime != null and request.endTime != null"> <if test="request.startTime != null and request.endTime != null">
AND t.oper_time BETWEEN #{request.startTime} AND #{request.endTime} AND t.oper_time BETWEEN #{request.startTime} AND #{request.endTime}
</if> </if>

View File

@ -1,5 +1,7 @@
package io.metersphere.commons.constants; package io.metersphere.commons.constants;
import java.util.List;
public class OperLogModule { public class OperLogModule {
public static final String SYSTEM_PARAMETER_SETTING = "SYSTEM_PARAMETER_SETTING"; public static final String SYSTEM_PARAMETER_SETTING = "SYSTEM_PARAMETER_SETTING";
public static final String SYSTEM_TEST_RESOURCE = "SYSTEM_TEST_RESOURCE"; public static final String SYSTEM_TEST_RESOURCE = "SYSTEM_TEST_RESOURCE";
@ -44,6 +46,35 @@ public class OperLogModule {
public static final String UI_AUTOMATION = "UI_AUTOMATION"; public static final String UI_AUTOMATION = "UI_AUTOMATION";
public static final String UI_AUTOMATION_REPORT = "UI_AUTOMATION_REPORT"; public static final String UI_AUTOMATION_REPORT = "UI_AUTOMATION_REPORT";
public static final String UI_AUTOMATION_SCHEDULE = "UI_AUTOMATION_SCHEDULE"; public static final String UI_AUTOMATION_SCHEDULE = "UI_AUTOMATION_SCHEDULE";
public static final String PLUGIN_MANAGE = "PLUGIN_MANAGE";
public static final List<String> SYSTEM_MODULES = List.of(
SYSTEM_PARAMETER_SETTING, SYSTEM_TEST_RESOURCE, SYSTEM_QUOTA_MANAGEMENT,
SYSTEM_USER, SYSTEM_WORKSPACE, PLUGIN_MANAGE,
SYSTEM_AUTHORIZATION_MANAGEMENT, AUTH_TITLE,
PERSONAL_INFORMATION_APIKEYS, SYSTEM_AUTHORIZATION_MANAGEMENT
);
public static final List<String> WORKSPACE_MODULES = List.of(
WORKSPACE_SERVICE_INTEGRATION, WORKSPACE_MEMBER, PROJECT_PROJECT_MANAGER
);
public static final List<String> PROJECT_MODULES = List.of(
WORKSPACE_TEMPLATE_SETTINGS, WORKSPACE_MESSAGE_SETTINGS,
WORKSPACE_TEMPLATE_SETTINGS_FIELD, WORKSPACE_TEMPLATE_SETTINGS_ISSUE,
WORKSPACE_TEMPLATE_SETTINGS_CASE, WORKSPACE_TEMPLATE_SETTINGS_API,
API_AUTOMATION, API_AUTOMATION_SCHEDULE,
API_AUTOMATION_REPORT, API_DEFINITION, API_DEFINITION_CASE,
TRACK_TEST_PLAN, TRACK_TEST_PLAN_SCHEDULE, TRACK_BUG,
TRACK_TEST_CASE_REVIEW, TRACK_TEST_CASE,
TRACK_REPORT, GROUP_PERMISSION,
PROJECT_PROJECT_JAR, PROJECT_ENVIRONMENT_SETTING,
PROJECT_FILE_MANAGEMENT, PROJECT_TEMPLATE_MANAGEMENT,
PROJECT_PROJECT_MEMBER, PERSONAL_INFORMATION_PERSONAL_SETTINGS,
PERFORMANCE_TEST_REPORT, PERFORMANCE_TEST,
ERROR_REPORT_LIBRARY, ENTERPRISE_TEST_REPORT,
UI_AUTOMATION_REPORT, UI_AUTOMATION_SCHEDULE,
UI_ELEMENT, UI_AUTOMATION
);
} }

View File

@ -0,0 +1,7 @@
package io.metersphere.log.constants;
public class OperatorLevel {
public static final String SYSTEM = "system";
public static final String WORKSPACE = "workspace";
public static final String PROJECT = "project";
}

View File

@ -5,9 +5,11 @@ import io.metersphere.base.domain.OperatingLogWithBLOBs;
import io.metersphere.base.mapper.OperatingLogMapper; import io.metersphere.base.mapper.OperatingLogMapper;
import io.metersphere.base.mapper.OperatingLogResourceMapper; import io.metersphere.base.mapper.OperatingLogResourceMapper;
import io.metersphere.base.mapper.ext.BaseOperatingLogMapper; import io.metersphere.base.mapper.ext.BaseOperatingLogMapper;
import io.metersphere.commons.constants.OperLogModule;
import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.JSON; import io.metersphere.commons.utils.JSON;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import io.metersphere.log.constants.OperatorLevel;
import io.metersphere.log.vo.OperatingLogDTO; import io.metersphere.log.vo.OperatingLogDTO;
import io.metersphere.log.vo.OperatingLogDetails; import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.OperatingLogRequest; import io.metersphere.log.vo.OperatingLogRequest;
@ -68,6 +70,16 @@ public class OperatingLogService {
request.setStartTime(request.getTimes().get(0)); request.setStartTime(request.getTimes().get(0));
request.setEndTime(request.getTimes().get(1)); request.setEndTime(request.getTimes().get(1));
} }
String level = request.getLevel();
List<String> modules = new ArrayList<>(OperLogModule.PROJECT_MODULES);
if (StringUtils.equals(level, OperatorLevel.WORKSPACE)) {
modules.addAll(OperLogModule.WORKSPACE_MODULES);
} else if (StringUtils.equals(level, OperatorLevel.SYSTEM)) {
modules.addAll(OperLogModule.SYSTEM_MODULES);
modules.addAll(OperLogModule.WORKSPACE_MODULES);
}
request.setLevelModules(modules);
List<OperatingLogDTO> list = baseOperatingLogMapper.list(request); List<OperatingLogDTO> list = baseOperatingLogMapper.list(request);
if (CollectionUtils.isNotEmpty(list)) { if (CollectionUtils.isNotEmpty(list)) {
List<String> userIds = list.stream().map(OperatingLogDTO::getOperUser).collect(Collectors.toList()); List<String> userIds = list.stream().map(OperatingLogDTO::getOperUser).collect(Collectors.toList());

View File

@ -1,5 +1,6 @@
package io.metersphere.log.vo; package io.metersphere.log.vo;
import io.metersphere.log.constants.OperatorLevel;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
@ -37,4 +38,7 @@ public class OperatingLogRequest implements Serializable {
//要查找的日志类型 //要查找的日志类型
private String logType; private String logType;
private String level = OperatorLevel.PROJECT;
private List<String> levelModules;
} }

View File

@ -23,6 +23,7 @@ public class SystemReference {
public static Map<String, String> baseColumns = new LinkedHashMap<>(); public static Map<String, String> baseColumns = new LinkedHashMap<>();
public static Map<String, String> groupColumns = new LinkedHashMap<>(); public static Map<String, String> groupColumns = new LinkedHashMap<>();
public static Map<String, String> projectApplicationColumns = new LinkedHashMap<>(); public static Map<String, String> projectApplicationColumns = new LinkedHashMap<>();
public static Map<String, String> pluginColumns = new LinkedHashMap<>();
static { static {
@ -44,6 +45,7 @@ public class SystemReference {
mailColumns.clear(); mailColumns.clear();
groupColumns.clear(); groupColumns.clear();
projectApplicationColumns.clear(); projectApplicationColumns.clear();
pluginColumns.clear();
userColumns.put("name", "用户名称"); userColumns.put("name", "用户名称");
userColumns.put("createUser", "创建人"); userColumns.put("createUser", "创建人");
@ -158,5 +160,7 @@ public class SystemReference {
groupColumns.put("description", "描述"); groupColumns.put("description", "描述");
groupColumns.put("type", "所属类型"); groupColumns.put("type", "所属类型");
groupColumns.put("scopeId", "全局用户组"); groupColumns.put("scopeId", "全局用户组");
pluginColumns.put("name", "名称");
} }
} }

View File

@ -1,7 +1,10 @@
package io.metersphere.controller; package io.metersphere.controller;
import io.metersphere.base.domain.Plugin; import io.metersphere.base.domain.Plugin;
import io.metersphere.commons.constants.OperLogConstants;
import io.metersphere.commons.constants.OperLogModule;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.request.PluginDTO; import io.metersphere.request.PluginDTO;
import io.metersphere.request.PluginRequest; import io.metersphere.request.PluginRequest;
import io.metersphere.service.PluginService; import io.metersphere.service.PluginService;
@ -20,6 +23,7 @@ public class PluginController {
private PluginService pluginService; private PluginService pluginService;
@PostMapping("/add/{scenario}") @PostMapping("/add/{scenario}")
@MsAuditLog(module = OperLogModule.PLUGIN_MANAGE, type = OperLogConstants.CREATE, title = "#file.getOriginalFilename()", msClass = PluginService.class)
public void create(@RequestPart(value = "file", required = false) MultipartFile file, @PathVariable String scenario) { public void create(@RequestPart(value = "file", required = false) MultipartFile file, @PathVariable String scenario) {
if (file == null) { if (file == null) {
MSException.throwException("上传文件/执行入口为空"); MSException.throwException("上传文件/执行入口为空");
@ -38,6 +42,7 @@ public class PluginController {
} }
@GetMapping("/delete/{scenario}/{id}") @GetMapping("/delete/{scenario}/{id}")
@MsAuditLog(module = OperLogModule.PLUGIN_MANAGE, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = PluginService.class)
public void delete(@PathVariable String scenario, @PathVariable String id) { public void delete(@PathVariable String scenario, @PathVariable String id) {
pluginService.delete(scenario, id); pluginService.delete(scenario, id);
} }

View File

@ -7,7 +7,12 @@ import io.metersphere.base.mapper.PluginMapper;
import io.metersphere.commons.constants.PluginScenario; import io.metersphere.commons.constants.PluginScenario;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.log.utils.ReflexObjectUtil;
import io.metersphere.log.vo.DetailColumn;
import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.system.SystemReference;
import io.metersphere.request.PluginDTO; import io.metersphere.request.PluginDTO;
import io.metersphere.request.PluginRequest; import io.metersphere.request.PluginRequest;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@ -126,4 +131,17 @@ public class PluginService {
MSException.throwException("Plugin exist!"); MSException.throwException("Plugin exist!");
} }
} }
public String getLogDetails(String id) {
PluginExample example = new PluginExample();
example.createCriteria().andPluginIdEqualTo(id);
List<PluginWithBLOBs> plugins = pluginMapper.selectByExampleWithBLOBs(example);
if (CollectionUtils.isNotEmpty(plugins)) {
Plugin plugin = plugins.get(0);
List<DetailColumn> columns = ReflexObjectUtil.getColumns(plugin, SystemReference.pluginColumns);
OperatingLogDetails details = new OperatingLogDetails(JSON.toJSONString(plugin.getId()), null, plugin.getSourceName(), plugin.getCreateUserId(), columns);
return JSON.toJSONString(details);
}
return null;
}
} }

View File

@ -100,6 +100,7 @@ export function LOG_MODULE_MAP(_this) {
['UI_AUTOMATION', _this.$t('operating_log.ui_automation')], ['UI_AUTOMATION', _this.$t('operating_log.ui_automation')],
['UI_AUTOMATION_SCHEDULE', _this.$t('operating_log.ui_automation_schedule')], ['UI_AUTOMATION_SCHEDULE', _this.$t('operating_log.ui_automation_schedule')],
['UI_AUTOMATION_REPORT', _this.$t('operating_log.ui_automation_report')], ['UI_AUTOMATION_REPORT', _this.$t('operating_log.ui_automation_report')],
['PLUGIN_MANAGE', _this.$t('system.operating_log.plugin_manage')],
]); ]);
return LOG_MODULE_MAP; return LOG_MODULE_MAP;
} }
@ -237,6 +238,11 @@ export function SYSLIST() {
value: [i18n.t('commons.system') + "-" + i18n.t('operating_log.group_permission'), 'GROUP_PERMISSION'], value: [i18n.t('commons.system') + "-" + i18n.t('operating_log.group_permission'), 'GROUP_PERMISSION'],
leaf: true leaf: true
}, },
{
label: i18n.t('commons.system') + "-" + i18n.t('system.operating_log.plugin_manage'),
value: [i18n.t('commons.system') + "-" + i18n.t('system.operating_log.plugin_manage'), 'PLUGIN_MANAGE'],
leaf: true
},
{ {
label: i18n.t('commons.workspace'), label: i18n.t('commons.workspace'),
value: [i18n.t('commons.workspace'), 'SYSTEM_WORKSPACE'], value: [i18n.t('commons.workspace'), 'SYSTEM_WORKSPACE'],
@ -256,7 +262,12 @@ export function SYSLIST() {
label: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_project_environment.name'), label: i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_project_environment.name'),
value: [i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_project_environment.name'), 'PROJECT_ENVIRONMENT_SETTING'], value: [i18n.t('commons.workspace') + "-" + i18n.t('permission.workspace_project_environment.name'), 'PROJECT_ENVIRONMENT_SETTING'],
leaf: true leaf: true
} },
{
label: i18n.t('commons.workspace') + "-" + i18n.t('project.manager'),
value: [i18n.t('commons.workspace') + "-" + i18n.t('project.manager'), 'PROJECT_PROJECT_MANAGER'],
leaf: true
},
] ]
}, },
{ {

View File

@ -322,6 +322,7 @@ export default {
} else { } else {
this.condition.workspaceIds = []; this.condition.workspaceIds = [];
} }
this.condition.level = 'system';
this.loading = getOperatingLogPages(this.currentPage, this.pageSize, this.condition).then(res => { this.loading = getOperatingLogPages(this.currentPage, this.pageSize, this.condition).then(res => {
let {listObject, itemCount} = res.data; let {listObject, itemCount} = res.data;
this.tableData = listObject; this.tableData = listObject;

View File

@ -321,6 +321,7 @@ export default {
} else { } else {
this.condition.workspaceIds = []; this.condition.workspaceIds = [];
} }
this.condition.level = 'workspace';
this.loading = getOperatingLogPages(this.currentPage, this.pageSize, this.condition).then(res => { this.loading = getOperatingLogPages(this.currentPage, this.pageSize, this.condition).then(res => {
let {listObject, itemCount} = res.data; let {listObject, itemCount} = res.data;
this.tableData = listObject; this.tableData = listObject;

View File

@ -15,6 +15,9 @@ const message = {
test_resource_pool: { test_resource_pool: {
edit_job_template: "Edit Job Template", edit_job_template: "Edit Job Template",
edit_job_template_tip: "The Kubernetes Job template is a text in YAML format that defines the running parameters of the Job. You can edit the Job template here.", edit_job_template_tip: "The Kubernetes Job template is a text in YAML format that defines the running parameters of the Job. You can edit the Job template here.",
},
operating_log: {
plugin_manage: "Plugin Manage",
} }
}, },
display: { display: {

View File

@ -15,6 +15,9 @@ const message = {
test_resource_pool: { test_resource_pool: {
edit_job_template: "编辑Job模版", edit_job_template: "编辑Job模版",
edit_job_template_tip: "Kubernetes Job模版是一个YAML格式的文本用于定义Job的运行参数您可以在此处编辑Job模版。", edit_job_template_tip: "Kubernetes Job模版是一个YAML格式的文本用于定义Job的运行参数您可以在此处编辑Job模版。",
},
operating_log: {
plugin_manage: "插件管理",
} }
}, },
display: { display: {

View File

@ -15,6 +15,9 @@ const message = {
test_resource_pool: { test_resource_pool: {
edit_job_template: "編輯Job模版", edit_job_template: "編輯Job模版",
edit_job_template_tip: "Kubernetes Job模版是一個YAML格式的文本用於定義Job的運行參數您可以在此處編輯Job模版。", edit_job_template_tip: "Kubernetes Job模版是一個YAML格式的文本用於定義Job的運行參數您可以在此處編輯Job模版。",
},
operating_log: {
plugin_manage: "插件管理",
} }
}, },
display: { display: {