refactor(项目管理): 导出环境增加全选功能

This commit is contained in:
wxg0103 2023-09-25 17:09:08 +08:00 committed by wxg0103
parent 7c25a87ef8
commit eb3e76b45e
7 changed files with 176 additions and 69 deletions

View File

@ -1,5 +1,7 @@
package io.metersphere.project.controller; package io.metersphere.project.controller;
import io.metersphere.project.dto.environment.EnvironmentDTO;
import io.metersphere.project.dto.environment.EnvironmentExportDTO;
import io.metersphere.project.dto.environment.EnvironmentRequest; import io.metersphere.project.dto.environment.EnvironmentRequest;
import io.metersphere.project.dto.environment.datasource.DataSource; import io.metersphere.project.dto.environment.datasource.DataSource;
import io.metersphere.project.dto.environment.ssl.KeyStoreEntry; import io.metersphere.project.dto.environment.ssl.KeyStoreEntry;
@ -36,11 +38,11 @@ public class EnvironmentController {
@Resource @Resource
private CommandService commandService; private CommandService commandService;
@GetMapping("/list/{projectId}") @PostMapping("/list")
@Operation(summary = "项目管理-环境-环境目录-列表") @Operation(summary = "项目管理-环境-环境目录-列表")
@RequiresPermissions(PermissionConstants.PROJECT_ENVIRONMENT_READ) @RequiresPermissions(PermissionConstants.PROJECT_ENVIRONMENT_READ)
public List<Environment> list(@PathVariable String projectId) { public List<Environment> list(@Validated @RequestBody EnvironmentDTO request) {
return environmentService.list(projectId); return environmentService.list(request);
} }
@GetMapping("/get/{environmentId}") @GetMapping("/get/{environmentId}")
@ -101,8 +103,8 @@ public class EnvironmentController {
@PostMapping("/export") @PostMapping("/export")
@RequiresPermissions(PermissionConstants.PROJECT_ENVIRONMENT_READ_EXPORT) @RequiresPermissions(PermissionConstants.PROJECT_ENVIRONMENT_READ_EXPORT)
@Operation(summary = "项目管理-环境-环境目录-导出") @Operation(summary = "项目管理-环境-环境目录-导出")
public String export(@RequestBody List<String> environmentIds) { public String export(@Validated @RequestBody EnvironmentExportDTO request) {
return environmentService.export(environmentIds); return environmentService.export(request);
} }
@PostMapping(value = "/get/entry") @PostMapping(value = "/get/entry")

View File

@ -0,0 +1,20 @@
package io.metersphere.project.dto.environment;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class EnvironmentDTO {
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{project_application.project_id.not_blank}")
@Size(min = 1, max = 50, message = "{project_parameters.project_id.length_range}")
private String projectId;
@Schema(description = "关键字")
private String keyword;
}

View File

@ -0,0 +1,19 @@
package io.metersphere.project.dto.environment;
import io.metersphere.sdk.dto.TableBatchProcessDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class EnvironmentExportDTO extends TableBatchProcessDTO {
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{project_application.project_id.not_blank}")
@Size(min = 1, max = 50, message = "{project_parameters.project_id.length_range}")
private String projectId;
}

View File

@ -0,0 +1,11 @@
package io.metersphere.project.mapper;
import io.metersphere.sdk.domain.Environment;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtEnvironmentMapper {
List<Environment> selectByKeyword(@Param("keyword") String keyword, @Param("selectId") boolean selectId , @Param("projectId") String projectId);
}

View File

@ -0,0 +1,24 @@
<?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.ExtEnvironmentMapper">
<select id="selectByKeyword" resultType="io.metersphere.sdk.domain.Environment">
SELECT
<if test="selectId">
id
</if>
<if test="!selectId">
*
</if>
FROM environment
WHERE environment.project_id = #{projectId}
<if test="keyword != null and keyword != ''">
AND (
id = #{keyword} OR
(name LIKE CONCAT('%', #{keyword}, '%'))
)
</if>
ORDER BY update_time DESC
</select>
</mapper>

View File

@ -3,8 +3,11 @@ package io.metersphere.project.service;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.dto.environment.EnvironmentConfig; import io.metersphere.project.dto.environment.EnvironmentConfig;
import io.metersphere.project.dto.environment.EnvironmentDTO;
import io.metersphere.project.dto.environment.EnvironmentExportDTO;
import io.metersphere.project.dto.environment.EnvironmentRequest; import io.metersphere.project.dto.environment.EnvironmentRequest;
import io.metersphere.project.dto.environment.datasource.DataSource; import io.metersphere.project.dto.environment.datasource.DataSource;
import io.metersphere.project.mapper.ExtEnvironmentMapper;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.domain.Environment; import io.metersphere.sdk.domain.Environment;
@ -18,14 +21,14 @@ import io.metersphere.sdk.file.FileRequest;
import io.metersphere.sdk.file.MinioRepository; import io.metersphere.sdk.file.MinioRepository;
import io.metersphere.sdk.mapper.EnvironmentBlobMapper; import io.metersphere.sdk.mapper.EnvironmentBlobMapper;
import io.metersphere.sdk.mapper.EnvironmentMapper; import io.metersphere.sdk.mapper.EnvironmentMapper;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.service.OperationLogService;
import io.metersphere.system.uid.UUID;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.service.OperationLogService;
import io.metersphere.system.service.JdbcDriverPluginService; import io.metersphere.system.service.JdbcDriverPluginService;
import io.metersphere.system.uid.UUID;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -36,6 +39,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream; import java.io.InputStream;
import java.sql.Driver; import java.sql.Driver;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
@Service @Service
@Transactional @Transactional
@ -52,10 +56,13 @@ public class EnvironmentService {
private ProjectMapper projectMapper; private ProjectMapper projectMapper;
@Resource @Resource
private OperationLogService operationLogService; private OperationLogService operationLogService;
@Resource
private ExtEnvironmentMapper extEnvironmentMapper;
private static final String DIR_PATH = "/project-management/environment/"; private static final String DIR_PATH = "/project-management/environment/";
private static final String USERNAME = "user"; private static final String USERNAME = "user";
private static final String PASSWORD = "password"; private static final String PASSWORD = "password";
private static final String PATH = "/project/environment/import";
public List<OptionDTO> getDriverOptions(String organizationId) { public List<OptionDTO> getDriverOptions(String organizationId) {
return jdbcDriverPluginService.getJdbcDriverOption(organizationId); return jdbcDriverPluginService.getJdbcDriverOption(organizationId);
@ -125,11 +132,8 @@ public class EnvironmentService {
return request; return request;
} }
public List<Environment> list(String projectId) { public List<Environment> list(EnvironmentDTO request) {
EnvironmentExample example = new EnvironmentExample(); return extEnvironmentMapper.selectByKeyword(request.getKeyword(), false, request.getProjectId());
example.createCriteria().andProjectIdEqualTo(projectId);
example.setOrderByClause("update_time desc");
return environmentMapper.selectByExample(example);
} }
public EnvironmentRequest get(String environmentId) { public EnvironmentRequest get(String environmentId) {
@ -146,37 +150,47 @@ public class EnvironmentService {
return environmentRequest; return environmentRequest;
} }
public String export(List<String> environmentIds) { public String export(EnvironmentExportDTO environmentExportDTO) {
if (CollectionUtils.isNotEmpty(environmentIds)) { List<String> environmentIds = this.getEnvironmentIds(environmentExportDTO);
// 查询环境 // 查询环境
EnvironmentExample environmentExample = new EnvironmentExample(); EnvironmentExample environmentExample = new EnvironmentExample();
environmentExample.createCriteria().andIdIn(environmentIds); environmentExample.createCriteria().andIdIn(environmentIds);
List<Environment> environments = environmentMapper.selectByExample(environmentExample); List<Environment> environments = environmentMapper.selectByExample(environmentExample);
Map<String, Environment> environmentMap = new HashMap<>(); Map<String, Environment> environmentMap = new HashMap<>();
environments.forEach(environment -> environmentMap.put(environment.getId(), environment)); environments.forEach(environment -> environmentMap.put(environment.getId(), environment));
// 查询环境配置 // 查询环境配置
EnvironmentBlobExample environmentBlobExample = new EnvironmentBlobExample(); EnvironmentBlobExample environmentBlobExample = new EnvironmentBlobExample();
environmentBlobExample.createCriteria().andIdIn(environmentIds); environmentBlobExample.createCriteria().andIdIn(environmentIds);
List<EnvironmentBlob> environmentBlobs = environmentBlobMapper.selectByExampleWithBLOBs(environmentBlobExample); List<EnvironmentBlob> environmentBlobs = environmentBlobMapper.selectByExampleWithBLOBs(environmentBlobExample);
Map<String, EnvironmentBlob> environmentBlobMap = new HashMap<>(); Map<String, EnvironmentBlob> environmentBlobMap = new HashMap<>();
environmentBlobs.forEach(environmentBlob -> environmentBlobMap.put(environmentBlob.getId(), environmentBlob)); environmentBlobs.forEach(environmentBlob -> environmentBlobMap.put(environmentBlob.getId(), environmentBlob));
List<EnvironmentRequest> environmentRequests = new ArrayList<>(); List<EnvironmentRequest> environmentRequests = new ArrayList<>();
environmentIds.forEach(environmentId -> { environmentIds.forEach(environmentId -> {
EnvironmentRequest environmentRequest = new EnvironmentRequest(); EnvironmentRequest environmentRequest = new EnvironmentRequest();
Environment environment = environmentMap.get(environmentId); Environment environment = environmentMap.get(environmentId);
EnvironmentBlob environmentBlob = environmentBlobMap.get(environmentId); EnvironmentBlob environmentBlob = environmentBlobMap.get(environmentId);
environmentRequest.setProjectId(environment.getProjectId()); environmentRequest.setProjectId(environment.getProjectId());
environmentRequest.setName(environment.getName()); environmentRequest.setName(environment.getName());
environmentRequest.setId(environment.getId()); environmentRequest.setId(environment.getId());
if (environmentBlob != null) { if (environmentBlob != null) {
environmentRequest.setConfig(JSON.parseObject(new String(environmentBlob.getConfig()), EnvironmentConfig.class)); environmentRequest.setConfig(JSON.parseObject(new String(environmentBlob.getConfig()), EnvironmentConfig.class));
} }
environmentRequests.add(environmentRequest); environmentRequests.add(environmentRequest);
}); });
return JSON.toJSONString(environmentRequests); return JSON.toJSONString(environmentRequests);
}
private List<String> getEnvironmentIds(EnvironmentExportDTO request) {
if (request.isSelectAll()) {
List<Environment> environments = extEnvironmentMapper.selectByKeyword(request.getCondition().getKeyword(), true, request.getProjectId());
List<String> environmentIds = environments.stream().map(Environment::getId).collect(Collectors.toList());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(request.getExcludeIds())) {
environmentIds.removeAll(request.getExcludeIds());
}
return environmentIds;
} else { } else {
return null; return request.getSelectIds();
} }
} }
@ -230,7 +244,7 @@ public class EnvironmentService {
environment.getName()); environment.getName());
logDTO.setMethod(HttpMethodConstants.POST.name()); logDTO.setMethod(HttpMethodConstants.POST.name());
logDTO.setOriginalValue(JSON.toJSONBytes(environmentRequest.getConfig())); logDTO.setOriginalValue(JSON.toJSONBytes(environmentRequest.getConfig()));
logDTO.setPath("/project/environment/import"); logDTO.setPath(PATH);
logDTOS.add(logDTO); logDTOS.add(logDTO);
}); });
environmentMapper.batchInsert(environments); environmentMapper.batchInsert(environments);

View File

@ -1,9 +1,7 @@
package io.metersphere.project.controller; package io.metersphere.project.controller;
import io.metersphere.project.dto.environment.EnvironmentConfig; import io.metersphere.project.dto.environment.*;
import io.metersphere.project.dto.environment.EnvironmentRequest;
import io.metersphere.project.dto.environment.KeyValue;
import io.metersphere.project.dto.environment.assertions.*; import io.metersphere.project.dto.environment.assertions.*;
import io.metersphere.project.dto.environment.auth.AuthConfig; import io.metersphere.project.dto.environment.auth.AuthConfig;
import io.metersphere.project.dto.environment.common.CommonParams; import io.metersphere.project.dto.environment.common.CommonParams;
@ -79,7 +77,7 @@ public class EnvironmentControllerTests extends BaseTest {
private static final String get = prefix + "/get/"; private static final String get = prefix + "/get/";
private static final String update = prefix + "/update"; private static final String update = prefix + "/update";
private static final String delete = prefix + "/delete/"; private static final String delete = prefix + "/delete/";
private static final String list = prefix + "/list/"; private static final String list = prefix + "/list";
private static final String getEnTry = prefix + "/get/entry"; private static final String getEnTry = prefix + "/get/entry";
private static final String importEnv = prefix + "/import"; private static final String importEnv = prefix + "/import";
private static final String exportEnv = prefix + "/export"; private static final String exportEnv = prefix + "/export";
@ -144,13 +142,13 @@ public class EnvironmentControllerTests extends BaseTest {
.andExpect(content().contentType(MediaType.APPLICATION_JSON)); .andExpect(content().contentType(MediaType.APPLICATION_JSON));
} }
protected MvcResult requestMultipartWithOk(String url, MultiValueMap<String, Object> paramMap) throws Exception { protected MvcResult requestMultipartWithOk(String url, MultiValueMap<String, Object> paramMap, String projectId) throws Exception {
MockMultipartHttpServletRequestBuilder requestBuilder = getMultipartRequestBuilderWithParam(url, paramMap); MockMultipartHttpServletRequestBuilder requestBuilder = getMultipartRequestBuilderWithParam(url, paramMap);
MockHttpServletRequestBuilder header = requestBuilder MockHttpServletRequestBuilder header = requestBuilder
.header(SessionConstants.HEADER_TOKEN, sessionId) .header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken) .header(SessionConstants.CSRF_TOKEN, csrfToken)
.header(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN") .header(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN")
.header("PROJECT", "projectId"); .header("PROJECT", projectId);
return mockMvc.perform(header) return mockMvc.perform(header)
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andReturn(); .andExpect(status().isOk()).andReturn();
@ -694,7 +692,7 @@ public class EnvironmentControllerTests extends BaseTest {
MockMultipartFile file11 = new MockMultipartFile("file", "测试一下a", MediaType.APPLICATION_OCTET_STREAM_VALUE, "Test content".getBytes()); MockMultipartFile file11 = new MockMultipartFile("file", "测试一下a", MediaType.APPLICATION_OCTET_STREAM_VALUE, "Test content".getBytes());
paramMap.add("file", List.of(file, file11)); paramMap.add("file", List.of(file, file11));
paramMap.set("request", JSON.toJSONString(request)); paramMap.set("request", JSON.toJSONString(request));
mvcResult = requestMultipartWithOk(add, paramMap); mvcResult = requestMultipartWithOk(add, paramMap, "projectId");
response = parseObjectFromMvcResult(mvcResult, EnvironmentRequest.class); response = parseObjectFromMvcResult(mvcResult, EnvironmentRequest.class);
Assertions.assertNotNull(response); Assertions.assertNotNull(response);
environment = environmentMapper.selectByPrimaryKey(response.getId()); environment = environmentMapper.selectByPrimaryKey(response.getId());
@ -882,7 +880,7 @@ public class EnvironmentControllerTests extends BaseTest {
MockMultipartFile file11 = new MockMultipartFile("file", "测试一下a", MediaType.APPLICATION_OCTET_STREAM_VALUE, "Test content".getBytes()); MockMultipartFile file11 = new MockMultipartFile("file", "测试一下a", MediaType.APPLICATION_OCTET_STREAM_VALUE, "Test content".getBytes());
paramMap.add("file", List.of(file, file11)); paramMap.add("file", List.of(file, file11));
paramMap.set("request", JSON.toJSONString(request)); paramMap.set("request", JSON.toJSONString(request));
mvcResult = requestMultipartWithOk(update, paramMap); mvcResult = requestMultipartWithOk(update, paramMap, "projectId");
response = parseObjectFromMvcResult(mvcResult, EnvironmentRequest.class); response = parseObjectFromMvcResult(mvcResult, EnvironmentRequest.class);
Assertions.assertNotNull(response); Assertions.assertNotNull(response);
environment = environmentMapper.selectByPrimaryKey(response.getId()); environment = environmentMapper.selectByPrimaryKey(response.getId());
@ -984,15 +982,25 @@ public class EnvironmentControllerTests extends BaseTest {
@Test @Test
@Order(11) @Order(11)
public void testList() throws Exception { public void testList() throws Exception {
MvcResult mvcResult = this.responseGet(list + "projectId"); EnvironmentDTO environmentDTO = new EnvironmentDTO();
environmentDTO.setProjectId("projectId");
MvcResult mvcResult = this.responsePost(list, environmentDTO);
List<Environment> response = parseObjectFromMvcResult(mvcResult, List.class); List<Environment> response = parseObjectFromMvcResult(mvcResult, List.class);
Assertions.assertNotNull(response); Assertions.assertNotNull(response);
//输入搜索值
environmentDTO.setKeyword("commonParams");
mvcResult = this.responsePost(list, environmentDTO);
response = parseObjectFromMvcResult(mvcResult, List.class);
Assertions.assertNotNull(response);
//校验拿到的数据包含搜索值
Assertions.assertEquals(1, response.size());
environmentDTO.setProjectId(DEFAULT_PROJECT_ID);
//校验权限 //校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_ENVIRONMENT_READ, list + DEFAULT_PROJECT_ID); requestPostPermissionTest(PermissionConstants.PROJECT_ENVIRONMENT_READ, list , environmentDTO);
//项目不存在 返回内容为[] //项目不存在 返回内容为[]
mvcResult = this.responseGet(list + "ceshi"); environmentDTO.setProjectId("ceshi");
mvcResult = this.responsePost(list ,environmentDTO);
response = parseObjectFromMvcResult(mvcResult, List.class); response = parseObjectFromMvcResult(mvcResult, List.class);
Assertions.assertEquals(0, response.size()); Assertions.assertEquals(0, response.size());
} }
@ -1009,7 +1017,7 @@ public class EnvironmentControllerTests extends BaseTest {
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>(); MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("file", List.of(file)); paramMap.add("file", List.of(file));
paramMap.set("request", password); paramMap.set("request", password);
MvcResult mvcResult = requestMultipartWithOk(getEnTry, paramMap); MvcResult mvcResult = requestMultipartWithOk(getEnTry, paramMap, "projectId");
List<KeyStoreEntry> response = parseObjectFromMvcResult(mvcResult, List.class); List<KeyStoreEntry> response = parseObjectFromMvcResult(mvcResult, List.class);
Assertions.assertNotNull(response); Assertions.assertNotNull(response);
@ -1039,21 +1047,28 @@ public class EnvironmentControllerTests extends BaseTest {
@Test @Test
@Order(13) @Order(13)
public void testExport() throws Exception { public void testExport() throws Exception {
//校验参数 //指定id
EnvironmentExample example = new EnvironmentExample(); EnvironmentExportDTO environmentExportDTO = new EnvironmentExportDTO();
example.createCriteria().andProjectIdEqualTo("projectId"); environmentExportDTO.setProjectId("projectId");
List<Environment> environments = environmentMapper.selectByExample(example); environmentExportDTO.setSelectIds(List.of("environmentId1"));
//把环境的id整理为一个集合
List<String> ids = environments.stream().map(Environment::getId).toList();
MvcResult mvcResult = this.responsePost(exportEnv, ids); MvcResult mvcResult = this.responsePost(exportEnv, environmentExportDTO);
String response = parseObjectFromMvcResult(mvcResult, String.class); String response = parseObjectFromMvcResult(mvcResult, String.class);
//判断response只有一条数据
Assertions.assertNotNull(response);
List<EnvironmentRequest> environments = JSON.parseArray(response, EnvironmentRequest.class);
Assertions.assertEquals(1, environments.size());
//全选
environmentExportDTO.setSelectIds(List.of("environmentId1"));
environmentExportDTO.setSelectAll(true);
environmentExportDTO.setExcludeIds(List.of("environmentId1"));
mvcResult = this.responsePost(exportEnv, environmentExportDTO);
response = parseObjectFromMvcResult(mvcResult, String.class);
Assertions.assertNotNull(response); Assertions.assertNotNull(response);
//传id为空 environmentExportDTO.setProjectId(DEFAULT_PROJECT_ID);
mvcResult = this.responsePost(exportEnv, new ArrayList<>()); //校验权限
response = parseObjectFromMvcResult(mvcResult, String.class); requestPostPermissionTest(PermissionConstants.PROJECT_ENVIRONMENT_READ_EXPORT, exportEnv, environmentExportDTO);
Assertions.assertNull(response);
} }
@Test @Test
@ -1066,7 +1081,9 @@ public class EnvironmentControllerTests extends BaseTest {
MockMultipartFile file = new MockMultipartFile("file", "huanj.json", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream); MockMultipartFile file = new MockMultipartFile("file", "huanj.json", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>(); MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("file", List.of(file)); paramMap.add("file", List.of(file));
requestMultipartWithOk(importEnv, paramMap); requestMultipartWithOk(importEnv, paramMap, DEFAULT_PROJECT_ID);
//校验权限
requestMultipartPermissionTest(PermissionConstants.PROJECT_ENVIRONMENT_READ_IMPORT, importEnv, paramMap);
} }
} }