refactor(项目管理): 将xpack的部分功能移到开源版本

This commit is contained in:
guoyuqi 2024-02-02 17:46:28 +08:00 committed by 刘瑞斌
parent 2a9b9d3e59
commit 3aa5e50732
24 changed files with 899 additions and 91 deletions

View File

@ -923,11 +923,7 @@ public class ApiDefinitionService {
}
public List<OperationHistoryDTO> list(OperationHistoryRequest request) {
XpackApiDefinitionService xpackApiDefinitionService = CommonBeanFactory.getBean(XpackApiDefinitionService.class);
if (xpackApiDefinitionService != null) {
return xpackApiDefinitionService.listHis(request, API_TABLE);
}
return new ArrayList<>();
return operationHistoryService.listWidthTable(request, API_TABLE);
}
/**

View File

@ -568,13 +568,8 @@ public class ApiTestCaseService {
return executeList;
}
public List<OperationHistoryDTO> operationHistoryList(OperationHistoryRequest request) {
XpackApiDefinitionService xpackApiDefinitionService = CommonBeanFactory.getBean(XpackApiDefinitionService.class);
if (xpackApiDefinitionService != null) {
return xpackApiDefinitionService.listHis(request, CASE_TABLE);
}
return new ArrayList<>();
return operationHistoryService.listWidthTable(request, CASE_TABLE);
}
public void updatePriority(String id, String priority, String userId) {

View File

@ -1,20 +0,0 @@
package io.metersphere.api.service.definition;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import java.util.List;
/**
* 接口管理Xpack功能接口
*/
public interface XpackApiDefinitionService {
/**
* 功能用例变更历史分页列表
*
* @param request 请求参数
* @return 变更历史集合
*/
List<OperationHistoryDTO> listHis(OperationHistoryRequest request, String table);
}

View File

@ -841,8 +841,8 @@ public class ApiTestCaseControllerTests extends BaseTest {
List<OperationHistoryDTO> reportDTOS = JSON.parseArray(JSON.toJSONString(returnPager.getList()), OperationHistoryDTO.class);
reportDTOS.forEach(reportDTO -> Assertions.assertEquals(reportDTO.getSourceId(), first.getId()));
List<OperationHistoryDTO> operationHistoryDTOS = operationHistoryService.listWidthLimit(request, "api_test_case");
Assertions.assertTrue(org.apache.commons.collections4.CollectionUtils.isNotEmpty(operationHistoryDTOS));
List<OperationHistoryDTO> operationHistoryDTOS = operationHistoryService.listWidthTable(request, "api_test_case");
Assertions.assertTrue(CollectionUtils.isNotEmpty(operationHistoryDTOS));
request = new OperationHistoryRequest();
request.setProjectId(DEFAULT_PROJECT_ID);

View File

@ -1,22 +1,57 @@
package io.metersphere.bug.service;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.domain.OperationHistory;
import io.metersphere.system.domain.OperationHistoryExample;
import io.metersphere.system.domain.User;
import io.metersphere.system.domain.UserExample;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.mapper.OperationHistoryMapper;
import io.metersphere.system.mapper.UserMapper;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class BugHistoryService {
@Resource
private UserMapper userMapper;
@Resource
private OperationHistoryMapper operationHistoryMapper;
/**
* 缺陷变更历史分页列表
* @param request 请求参数
* @return 变更历史集合
*/
public List<OperationHistoryDTO> list(OperationHistoryRequest request) {
XpackBugService bugService = CommonBeanFactory.getBean(XpackBugService.class);
if (bugService != null) {
return bugService.listHis(request);
OperationHistoryExample example = new OperationHistoryExample();
example.createCriteria().andProjectIdEqualTo(request.getProjectId()).andModuleEqualTo(OperationLogModule.BUG_MANAGEMENT)
.andSourceIdEqualTo(request.getSourceId());
List<OperationHistory> history = operationHistoryMapper.selectByExample(example);
if (CollectionUtils.isEmpty(history)) {
return List.of();
}
return List.of();
List<String> userIds = history.stream().map(OperationHistory::getCreateUser).toList();
UserExample userExample = new UserExample();
userExample.createCriteria().andIdIn(userIds);
List<User> users = userMapper.selectByExample(userExample);
Map<String, String> userMap = users.stream().collect(Collectors.toMap(User::getId, User::getName));
return history.stream().map(h -> {
OperationHistoryDTO dto = new OperationHistoryDTO();
BeanUtils.copyBean(dto, h);
dto.setCreateUserName(userMap.get(h.getCreateUser()) == null ? h.getCreateUser() : userMap.get(h.getCreateUser()));
return dto;
}).toList();
}
}

View File

@ -2,10 +2,6 @@ package io.metersphere.bug.service;
import io.metersphere.bug.dto.request.BugSyncRequest;
import io.metersphere.project.domain.Project;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import java.util.List;
/**
* 缺陷相关xpack功能接口
@ -27,10 +23,4 @@ public interface XpackBugService {
*/
void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser);
/**
* 缺陷变更历史分页列表
* @param request 请求参数
* @return 变更历史集合
*/
List<OperationHistoryDTO> listHis(OperationHistoryRequest request);
}

View File

@ -3,12 +3,8 @@ package io.metersphere.bug.mock;
import io.metersphere.bug.dto.request.BugSyncRequest;
import io.metersphere.bug.service.XpackBugService;
import io.metersphere.project.domain.Project;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class XpackBugMockServiceImpl implements XpackBugService {
@ -21,9 +17,4 @@ public class XpackBugMockServiceImpl implements XpackBugService {
public void syncPlatformBugs(Project project, BugSyncRequest request, String currentUser) {
}
@Override
public List<OperationHistoryDTO> listHis(OperationHistoryRequest request) {
return List.of();
}
}

View File

@ -28,7 +28,6 @@ import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.CustomFieldOption;
@ -44,6 +43,7 @@ import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.notice.sender.AfterReturningNoticeSendService;
import io.metersphere.system.service.BaseCustomFieldOptionService;
import io.metersphere.system.service.BaseCustomFieldService;
import io.metersphere.system.service.OperationHistoryService;
import io.metersphere.system.service.UserLoginService;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
@ -151,6 +151,8 @@ public class FunctionalCaseService {
private FileAssociationMapper fileAssociationMapper;
@Resource
private AfterReturningNoticeSendService afterReturningNoticeSendService;
@Resource
private OperationHistoryService operationHistoryService;
public FunctionalCase addFunctionalCase(FunctionalCaseAddRequest request, List<MultipartFile> files, String userId, String organizationId) {
@ -1110,10 +1112,6 @@ public class FunctionalCaseService {
}
public List<OperationHistoryDTO> operationHistoryList(OperationHistoryRequest request) {
XpackFunctionalCaseService functionalCaseService = CommonBeanFactory.getBean(XpackFunctionalCaseService.class);
if (functionalCaseService != null) {
return functionalCaseService.listHis(request, CASE_TABLE);
}
return List.of();
return operationHistoryService.listWidthTable(request, CASE_TABLE);
}
}

View File

@ -1,19 +0,0 @@
package io.metersphere.functional.service;
import io.metersphere.system.dto.OperationHistoryDTO;
import io.metersphere.system.dto.request.OperationHistoryRequest;
import java.util.List;
/**
* 用例管理Xpack功能接口
*/
public interface XpackFunctionalCaseService {
/**
* 功能用例变更历史分页列表
* @param request 请求参数
* @return 变更历史集合
*/
List<OperationHistoryDTO> listHis(OperationHistoryRequest request,String table);
}

View File

@ -1,6 +1,5 @@
package io.metersphere.functional.config;
import io.metersphere.functional.service.XpackFunctionalCaseService;
import io.metersphere.provider.BaseAssociateApiProvider;
import io.metersphere.provider.BaseAssociateBugProvider;
import io.metersphere.provider.BaseAssociateScenarioProvider;
@ -19,7 +18,4 @@ public class CaseTestConfiguration {
@MockBean
BaseAssociateBugProvider baseAssociateBugProvider;
@MockBean
XpackFunctionalCaseService xpackFunctionalCaseService;
}

View File

@ -667,7 +667,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
request.setSort(Map.of());
this.requestPost(OPERATION_HISTORY_URL, request);
List<OperationHistoryDTO> operationHistoryDTOS = operationHistoryService.listWidthLimit(request, "functional_case");
List<OperationHistoryDTO> operationHistoryDTOS = operationHistoryService.listWidthTable(request, "functional_case");
Assertions.assertTrue(CollectionUtils.isNotEmpty(operationHistoryDTOS));
}

View File

@ -0,0 +1,88 @@
package io.metersphere.project.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.project.domain.FakeError;
import io.metersphere.project.dto.FakeErrorDTO;
import io.metersphere.project.dto.filemanagement.request.FakeErrorDelRequest;
import io.metersphere.project.dto.filemanagement.request.FakeErrorRequest;
import io.metersphere.project.dto.filemanagement.request.FakeErrorStatusRequest;
import io.metersphere.project.service.FakeErrorService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.SessionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "项目管理-项目与权限-接口测试-误报规则配置")
@RestController
@RequestMapping(value = "/fake/error")
public class FakeErrorController {
@Resource
private FakeErrorService fakeErrorService;
@PostMapping("/add")
@Operation(summary = "项目与权限-接口测试-新增误报规则")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_UPDATE)
public ResultHolder add(@Validated @RequestBody List<FakeErrorDTO> dto) {
String userId = SessionUtils.getUserId();
return fakeErrorService.save(dto, userId);
}
@PostMapping("/list")
@Operation(summary = "项目与权限-接口测试-获取误报规则列表")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_READ)
public Pager<List<FakeError>> list(@Validated @RequestBody FakeErrorRequest request) {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
return PageUtils.setPageInfo(page, fakeErrorService.list(request));
}
@PostMapping("/update")
@Operation(summary = "项目与权限-接口测试-编辑误报规则")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_UPDATE)
public ResultHolder update(@Validated @RequestBody List<FakeErrorDTO> requests) {
String userId = SessionUtils.getUserId();
return fakeErrorService.update(requests, userId);
}
@PostMapping("/delete")
@Operation(summary = "应用设置-接口测试-删除误报规则")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.deleteLog(#request)", msClass = FakeErrorService.class)
public void delete(@Validated @RequestBody FakeErrorDelRequest request) {
fakeErrorService.delete(request);
}
@PostMapping("/update/enable")
@Operation(summary = "项目与权限-接口测试-启用/禁用误报规则")
@RequiresPermissions(PermissionConstants.PROJECT_APPLICATION_API_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchUpdateEnableLog(#request)", msClass = FakeErrorService.class)
public void updateEnable(@Validated @RequestBody FakeErrorStatusRequest request) {
String userId = SessionUtils.getUserId();
fakeErrorService.updateEnable(request, userId);
}
}

View File

@ -0,0 +1,48 @@
package io.metersphere.project.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serializable;
/**
* @author wx
*/
@Data
public class FakeErrorDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "ID")
private String id;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.project_id.not_blank}")
private String projectId;
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.name.not_blank}")
private String name;
@Schema(description = "标签", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.type.not_blank}")
private String type;
@Schema(description = "匹配规则-内容类型/header/data/body", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.resp_type.not_blank}")
private String respType;
@Schema(description = "匹配规则-操作类型", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.relation.not_blank}")
private String relation;
@Schema(description = "匹配规则-表达式", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.expression.not_blank}")
private String expression;
@Schema(description = "状态")
private Boolean enable;
}

View File

@ -0,0 +1,22 @@
package io.metersphere.project.dto.filemanagement.request;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serializable;
/**
* @author wx
*/
@Data
public class FakeErrorDelRequest extends TableBatchProcessDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.project_id.not_blank}")
private String projectId;
}

View File

@ -0,0 +1,21 @@
package io.metersphere.project.dto.filemanagement.request;
import io.metersphere.system.dto.sdk.BasePageRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
/**
* @author wx
*/
@Getter
@Setter
public class FakeErrorRequest extends BasePageRequest {
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.project_id.not_blank}")
private String projectId;
}

View File

@ -0,0 +1,24 @@
package io.metersphere.project.dto.filemanagement.request;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serializable;
/**
* @author wx
*/
@Data
public class FakeErrorStatusRequest extends TableBatchProcessDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "是否禁用")
private Boolean enable;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{fake_error.project_id.not_blank}")
private String projectId;
}

View File

@ -0,0 +1,34 @@
package io.metersphere.project.dto.filemanagement.response;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Data
public class FakeErrorResponse implements Serializable {
@Schema(description = "ID")
private String id;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
private String projectId;
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String name;
@Schema(description = "标签", requiredMode = Schema.RequiredMode.REQUIRED)
private String type;
@Schema(description = "匹配规则-内容类型/header/data/body", requiredMode = Schema.RequiredMode.REQUIRED)
private String respType;
@Schema(description = "匹配规则-操作类型", requiredMode = Schema.RequiredMode.REQUIRED)
private String relation;
@Schema(description = "匹配规则-表达式", requiredMode = Schema.RequiredMode.REQUIRED)
private String expression;
@Schema(description = "状态")
private Boolean enable;
}

View File

@ -0,0 +1,13 @@
package io.metersphere.project.mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author wx
*/
public interface ExtFakeErrorMapper {
List<String> selectByKeyword(@Param("keyword") String keyword);
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.metersphere.project.mapper.ExtFakeErrorMapper">
<select id="selectByKeyword" resultType="java.lang.String">
select id from fake_error
<where>
<if test="keyword != null and keyword != ''">
and name like concat('%', #{keyword}, '%')
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,315 @@
package io.metersphere.project.service;
import io.metersphere.project.domain.FakeError;
import io.metersphere.project.domain.FakeErrorExample;
import io.metersphere.project.domain.Project;
import io.metersphere.project.dto.FakeErrorDTO;
import io.metersphere.project.dto.filemanagement.request.FakeErrorDelRequest;
import io.metersphere.project.dto.filemanagement.request.FakeErrorRequest;
import io.metersphere.project.dto.filemanagement.request.FakeErrorStatusRequest;
import io.metersphere.project.dto.filemanagement.response.FakeErrorResponse;
import io.metersphere.project.mapper.ExtFakeErrorMapper;
import io.metersphere.project.mapper.FakeErrorMapper;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.table.TableBatchProcessDTO;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.log.service.OperationLogService;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Transactional(rollbackFor = Exception.class)
public class FakeErrorService {
@Resource
private FakeErrorMapper fakeErrorMapper;
@Resource
private ProjectMapper projectMapper;
@Resource
private OperationLogService operationLogService;
@Resource
private ExtFakeErrorMapper extFakeErrorMapper;
private static final String ADD_TYPE = "ADD";
private static final String UPDATE_TYPE = "UPDATE";
/**
* 保存误报规则
*
* @param dto
* @return
*/
public ResultHolder save(List<FakeErrorDTO> dto, String userId) {
List<FakeErrorResponse> responseList = checkNameRepeat(dto, ADD_TYPE);
if (CollectionUtils.isNotEmpty(responseList)) {
return ResultHolder.success(responseList);
}
doSave(dto, userId);
return ResultHolder.success(responseList);
}
private void doSave(List<FakeErrorDTO> dto, String userId) {
dto.forEach(item -> {
FakeError fakeError = new FakeError();
BeanUtils.copyBean(fakeError, item);
fakeError.setId(IDGenerator.nextStr());
fakeError.setCreateTime(System.currentTimeMillis());
fakeError.setUpdateTime(System.currentTimeMillis());
fakeError.setCreateUser(userId);
fakeError.setUpdateUser(userId);
fakeErrorMapper.insertSelective(fakeError);
doSaveLog(fakeError, userId);
});
}
private List<FakeErrorResponse> checkNameRepeat(List<FakeErrorDTO> dto, String type) {
List<FakeErrorResponse> responseList = new ArrayList<>();
Map<String, FakeErrorDTO> nameMap = new HashMap<>();
dto.forEach(item -> {
if (nameMap.containsKey(item.getName())) {
addRepeatResponse(responseList, item);
return;
}
nameMap.put(item.getName(), item);
FakeErrorExample example = new FakeErrorExample();
FakeErrorExample.Criteria criteria = example.createCriteria();
criteria.andProjectIdEqualTo(item.getProjectId()).andNameEqualTo(item.getName());
if (StringUtils.isNotBlank(item.getId()) && StringUtils.equalsIgnoreCase(type,UPDATE_TYPE)) {
criteria.andIdNotEqualTo(item.getId());
}
if (fakeErrorMapper.countByExample(example) > 0) {
addRepeatResponse(responseList, item);
}
});
return responseList;
}
private void addRepeatResponse(List<FakeErrorResponse> responseList, FakeErrorDTO item) {
FakeErrorResponse fakeErrorResponse = BeanUtils.copyBean(new FakeErrorResponse(), item);
responseList.add(fakeErrorResponse);
}
/**
* 获取误报列表
*
* @param request
* @return
*/
public List<FakeError> list(FakeErrorRequest request) {
FakeErrorExample example = new FakeErrorExample();
FakeErrorExample.Criteria criteria = example.createCriteria();
criteria.andProjectIdEqualTo(request.getProjectId());
if (StringUtils.isNotBlank(request.getKeyword())) {
criteria.andNameLike("%" + request.getKeyword() + "%");
}
return fakeErrorMapper.selectByExample(example);
}
/**
* 更新误报规则
*
* @param dto
* @param userId
* @return
*/
public ResultHolder update(List<FakeErrorDTO> dto, String userId) {
List<FakeErrorResponse> responseList = checkNameRepeat(dto, UPDATE_TYPE);
if (CollectionUtils.isNotEmpty(responseList)) {
return ResultHolder.success(responseList);
}
doUpdate(dto, userId);
return ResultHolder.success(responseList);
}
private void doUpdate(List<FakeErrorDTO> dto, String userId) {
dto.forEach(item -> {
FakeError fakeError = new FakeError();
BeanUtils.copyBean(fakeError, item);
fakeError.setUpdateUser(userId);
fakeError.setUpdateTime(System.currentTimeMillis());
fakeErrorMapper.updateByPrimaryKeySelective(fakeError);
updateLog(fakeError, userId);
});
}
/**
* 删除误报规则
*
* @param request
* @return
*/
public void delete(FakeErrorDelRequest request) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isEmpty(ids)) {
return;
}
FakeErrorExample example = new FakeErrorExample();
example.createCriteria().andIdIn(ids);
fakeErrorMapper.deleteByExample(example);
}
/**
* 保存日志
*
* @param fakeError
* @return
*/
private void doSaveLog(FakeError fakeError, String userId) {
Project project = projectMapper.selectByPrimaryKey(fakeError.getProjectId());
LogDTO dto = new LogDTO(
fakeError.getProjectId(),
project.getOrganizationId(),
fakeError.getId(),
userId,
OperationLogType.ADD.name(),
OperationLogModule.PROJECT_PROJECT_MANAGER,
fakeError.getName());
dto.setMethod(HttpMethodConstants.POST.name());
dto.setPath("/fake/error/add");
dto.setModifiedValue(JSON.toJSONBytes(fakeError));
operationLogService.add(dto);
}
/**
* 更新日志
*
* @param fakeError
* @return
*/
public void updateLog(FakeError fakeError, String userId) {
Project project = projectMapper.selectByPrimaryKey(fakeError.getProjectId());
FakeError originalValue = fakeErrorMapper.selectByPrimaryKey(fakeError.getId());
LogDTO dto = new LogDTO(
fakeError.getProjectId(),
project.getOrganizationId(),
fakeError.getId(),
userId,
OperationLogType.UPDATE.name(),
OperationLogModule.PROJECT_PROJECT_MANAGER,
fakeError.getName());
dto.setMethod(HttpMethodConstants.POST.name());
dto.setPath("/fake/error/update");
dto.setOriginalValue(JSON.toJSONBytes(fakeError));
dto.setOriginalValue(JSON.toJSONBytes(originalValue));
operationLogService.add(dto);
}
/**
* 删除日志
*
* @param request
* @return
*/
public List<LogDTO> deleteLog(FakeErrorDelRequest request) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isEmpty(ids)) {
return new ArrayList<>();
}
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
FakeErrorExample example = new FakeErrorExample();
example.createCriteria().andIdIn(ids).andProjectIdEqualTo(request.getProjectId());
List<FakeError> fakeErrors = fakeErrorMapper.selectByExample(example);
List<LogDTO> logs = new ArrayList<>();
fakeErrors.forEach(fakeError -> {
LogDTO dto = new LogDTO(
fakeError.getProjectId(),
project.getOrganizationId(),
fakeError.getId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.PROJECT_PROJECT_MANAGER,
fakeError.getName());
dto.setOriginalValue(JSON.toJSONBytes(fakeError));
logs.add(dto);
});
return logs;
}
/**
* 更新状态
*
* @param request
* @param userId
* @return
*/
public void updateEnable(FakeErrorStatusRequest request, String userId) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isEmpty(ids)) {
return;
}
FakeErrorExample example = new FakeErrorExample();
example.createCriteria().andIdIn(ids).andProjectIdEqualTo(request.getProjectId());
FakeError fakeError = new FakeError();
fakeError.setEnable(request.getEnable());
fakeError.setUpdateUser(userId);
fakeError.setUpdateTime(System.currentTimeMillis());
fakeErrorMapper.updateByExampleSelective(fakeError, example);
}
private <T> List<String> doSelectIds(T dto) {
TableBatchProcessDTO request = (TableBatchProcessDTO) dto;
if (request.isSelectAll()) {
List<String> ids = extFakeErrorMapper.selectByKeyword(request.getCondition().getKeyword());
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
ids.removeAll(request.getExcludeIds());
}
return ids;
} else {
return request.getSelectIds();
}
}
public List<LogDTO> batchUpdateEnableLog(FakeErrorStatusRequest request) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isEmpty(ids)) {
return new ArrayList<>();
}
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
FakeErrorExample example = new FakeErrorExample();
example.createCriteria().andIdIn(ids).andProjectIdEqualTo(request.getProjectId());
List<FakeError> fakeErrors = fakeErrorMapper.selectByExample(example);
List<LogDTO> logs = new ArrayList<>();
fakeErrors.forEach(fakeError -> {
LogDTO dto = new LogDTO(
fakeError.getProjectId(),
project.getOrganizationId(),
fakeError.getId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.PROJECT_PROJECT_MANAGER,
fakeError.getName());
dto.setOriginalValue(JSON.toJSONBytes(fakeError));
logs.add(dto);
});
return logs;
}
}

View File

@ -0,0 +1,267 @@
package io.metersphere.project.controller;
import io.metersphere.project.domain.FakeError;
import io.metersphere.project.domain.FakeErrorExample;
import io.metersphere.project.dto.FakeErrorDTO;
import io.metersphere.project.dto.filemanagement.request.FakeErrorDelRequest;
import io.metersphere.project.dto.filemanagement.request.FakeErrorRequest;
import io.metersphere.project.dto.filemanagement.request.FakeErrorStatusRequest;
import io.metersphere.project.mapper.FakeErrorMapper;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MvcResult;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
public class FakeErrorControllerTests extends BaseTest {
@Resource
private FakeErrorMapper fakeErrorMapper;
private static final String prefix = "/fake/error";
private static final String ADD = prefix + "/add";
private static final String UPDATE = prefix + "/update";
private static final String UPDATE_ENABLE = UPDATE + "/enable";
private static final String DELETE = prefix + "/delete";
private static final String LIST = prefix + "/list";
@Test
@Order(1)
public void addFakeErrorRuleSuccess() throws Exception {
List<FakeErrorDTO> dtoList = new ArrayList<>();
FakeErrorDTO dto = new FakeErrorDTO();
dto.setName("测试新增误报规则");
dto.setExpression("ok");
dto.setProjectId(DEFAULT_PROJECT_ID);
dto.setRelation("equal");
dto.setType("dd");
dto.setRespType("data");
dtoList.add(dto);
MvcResult mvcResult = this.requestPostWithOkAndReturn(ADD, dtoList);
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
List<FakeError> fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
Assertions.assertEquals(1,fakeErrors.size());
FakeErrorDTO dto1 = new FakeErrorDTO();
dto1.setName("测试新增误报规则");
dto1.setExpression("ok");
dto1.setProjectId(DEFAULT_PROJECT_ID);
dto1.setRelation("equal");
dto1.setType("dd");
dto1.setRespType("headers");
dtoList.add(dto1);
mvcResult = this.requestPostWithOkAndReturn(ADD, dtoList);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
//名字重复不添加
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
Assertions.assertEquals(1,fakeErrors.size());
}
@Test
@Order(2)
public void getListFakeErrorRuleSuccess() throws Exception {
FakeErrorRequest request = new FakeErrorRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setCurrent(1);
request.setPageSize(10);
MvcResult mvcResult = this.requestPostWithOkAndReturn(LIST, request);
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
// 返回值不为空
Assertions.assertNotNull(pageData);
// 返回值的页码和当前页码相同
Assertions.assertEquals(pageData.getCurrent(), request.getCurrent());
// 返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
request.setKeyword("测试");
mvcResult = this.requestPostWithOkAndReturn(LIST, request);
// 获取返回值
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
}
@Test
@Order(3)
public void updateFakeErrorRuleSuccess() throws Exception {
List<FakeError> fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
List<FakeErrorDTO> dtoList = new ArrayList<>();
FakeErrorDTO dto = new FakeErrorDTO();
dto.setId(fakeErrors.get(0).getId());
dto.setName("测试新增误报规则更新");
dto.setExpression("ok");
dto.setProjectId(DEFAULT_PROJECT_ID);
dto.setRelation("equal");
dto.setType("dd");
dto.setRespType("data");
dto.setEnable(true);
dtoList.add(dto);
MvcResult mvcResult = this.requestPostWithOkAndReturn(UPDATE, dtoList);
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
Assertions.assertTrue(fakeErrors.get(0).getEnable());
mvcResult = this.requestPostWithOkAndReturn(ADD, dtoList);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
Assertions.assertEquals(1, fakeErrors.size());
FakeErrorDTO dtoTwo = new FakeErrorDTO();
dtoTwo.setName("测试新增误报规则更新2");
dtoTwo.setExpression("ok");
dtoTwo.setProjectId(DEFAULT_PROJECT_ID);
dtoTwo.setRelation("equal");
dtoTwo.setType("dd");
dtoTwo.setRespType("data");
dtoTwo.setEnable(true);
List<FakeErrorDTO> dtoListTwo = new ArrayList<>();
dtoListTwo.add(dtoTwo);
mvcResult = this.requestPostWithOkAndReturn(ADD, dtoListTwo);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
Assertions.assertEquals(2, fakeErrors.size());
List<FakeErrorDTO> updateList = new ArrayList<>();
for (FakeError fakeError : fakeErrors) {
FakeErrorDTO fakeErrorDTO = new FakeErrorDTO();
BeanUtils.copyBean(fakeErrorDTO,fakeError);
fakeErrorDTO.setName("更新同名");
updateList.add(fakeErrorDTO);
}
mvcResult = this.requestPostWithOkAndReturn(UPDATE, updateList);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
//名字重复不更新
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
Assertions.assertFalse(StringUtils.equalsIgnoreCase(fakeErrors.get(0).getName(),fakeErrors.get(1).getName()));
}
@Test
@Order(4)
public void updateEnableFakeErrorRuleSuccess() throws Exception {
List<FakeError> fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
List<String> ids = fakeErrors.stream().map(FakeError::getId).toList();
FakeErrorStatusRequest fakeErrorStatusRequest = new FakeErrorStatusRequest();
fakeErrorStatusRequest.setProjectId(DEFAULT_PROJECT_ID);
fakeErrorStatusRequest.setEnable(false);
fakeErrorStatusRequest.setSelectAll(true);
MvcResult mvcResult = this.requestPostWithOkAndReturn(UPDATE_ENABLE, fakeErrorStatusRequest);
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
//名字重复不更新
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
List<FakeError> list = fakeErrors.stream().filter(FakeError::getEnable).toList();
Assertions.assertEquals(0,list.size());
fakeErrorStatusRequest = new FakeErrorStatusRequest();
fakeErrorStatusRequest.setProjectId(DEFAULT_PROJECT_ID);
fakeErrorStatusRequest.setEnable(true);
fakeErrorStatusRequest.setSelectAll(false);
mvcResult = this.requestPostWithOkAndReturn(UPDATE_ENABLE, fakeErrorStatusRequest);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
list = fakeErrors.stream().filter(FakeError::getEnable).toList();
Assertions.assertEquals(0,list.size());
String oneId = ids.get(0);
fakeErrorStatusRequest = new FakeErrorStatusRequest();
fakeErrorStatusRequest.setProjectId(DEFAULT_PROJECT_ID);
fakeErrorStatusRequest.setEnable(true);
fakeErrorStatusRequest.setSelectAll(false);
fakeErrorStatusRequest.setSelectIds(List.of(oneId));
mvcResult = this.requestPostWithOkAndReturn(UPDATE_ENABLE, fakeErrorStatusRequest);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
fakeErrors = fakeErrorMapper.selectByExample(new FakeErrorExample());
list = fakeErrors.stream().filter(FakeError::getEnable).toList();
Assertions.assertEquals(1,list.size());
}
@Test
@Order(5)
public void deleteFakeErrorRuleSuccess() throws Exception {
List<FakeErrorDTO> dtoList = new ArrayList<>();
FakeErrorDTO dto = new FakeErrorDTO();
dto.setName("用来删除");
dto.setExpression("ok");
dto.setProjectId(DEFAULT_PROJECT_ID);
dto.setRelation("equal");
dto.setType("dd");
dto.setRespType("data");
dtoList.add(dto);
MvcResult mvcResult = this.requestPostWithOkAndReturn(ADD, dtoList);
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
FakeErrorExample fakeErrorExample = new FakeErrorExample();
fakeErrorExample.createCriteria().andNameLike("用来删除");
List<FakeError> fakeErrors = fakeErrorMapper.selectByExample(fakeErrorExample);
String deleteId = fakeErrors.get(0).getId();
Assertions.assertEquals(1,fakeErrors.size());
FakeErrorDelRequest request = new FakeErrorDelRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setSelectAll(false);
mvcResult = this.requestPostWithOkAndReturn(DELETE, request);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
request.setSelectAll(true);
fakeErrorExample = new FakeErrorExample();
fakeErrorExample.createCriteria().andNameLike("测试");
fakeErrors = fakeErrorMapper.selectByExample(fakeErrorExample);
List<String> ids = fakeErrors.stream().map(FakeError::getId).toList();
request.setExcludeIds(ids);
mvcResult = this.requestPostWithOkAndReturn(DELETE, request);
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
resultHolder = JSON.parseObject(returnData, ResultHolder.class);
Assertions.assertNotNull(resultHolder);
FakeError fakeError = fakeErrorMapper.selectByPrimaryKey(deleteId);
Assertions.assertNull(fakeError);
}
}

View File

@ -17,5 +17,5 @@ public interface BaseOperationHistoryMapper {
List<OperationHistoryDTO> list(@Param("request") OperationHistoryRequest request);
List<OperationHistoryDTO> listWidthLimit(@Param("request") OperationHistoryRequest request, @Param("table") String table);
List<OperationHistoryDTO> listWidthTable(@Param("request") OperationHistoryRequest request, @Param("table") String table);
}

View File

@ -41,7 +41,7 @@
</where>
</select>
<select id="listWidthLimit" resultType="io.metersphere.system.dto.OperationHistoryDTO">
<select id="listWidthTable" resultType="io.metersphere.system.dto.OperationHistoryDTO">
SELECT operation_history.id, operation_history.project_id, operation_history.create_time, operation_history.create_user, operation_history.source_id, operation_history.`type`, operation_history.`module`, operation_history.ref_id, project_version.name as versionName
FROM operation_history
LEFT JOIN ${table} sourceTable ON sourceTable.id = operation_history.source_id

View File

@ -47,8 +47,8 @@ public class OperationHistoryService {
}
public List<OperationHistoryDTO> listWidthLimit(OperationHistoryRequest request, String table) {
List<OperationHistoryDTO> list = baseOperationHistoryMapper.listWidthLimit(request, table);
public List<OperationHistoryDTO> listWidthTable(OperationHistoryRequest request, String table) {
List<OperationHistoryDTO> list = baseOperationHistoryMapper.listWidthTable(request, table);
if (CollectionUtils.isNotEmpty(list)) {
List<String> userIds = list.stream().distinct()
.map(OperationHistoryDTO::getCreateUser).toList();