refactor(项目管理): 菜单管理配置平台插件,插件key校验

This commit is contained in:
WangXu10 2023-10-07 14:16:14 +08:00 committed by 刘瑞斌
parent 91c6687b5d
commit e36278861f
6 changed files with 126 additions and 148 deletions

View File

@ -13,4 +13,10 @@ public interface Platform extends ExtensionPoint {
* 服务集成点击校验时调用
*/
void validateIntegrationConfig();
/**
* 校验项目配置
* 项目设置成点击校验项目 key 时调用
*/
void validateProjectConfig(String projectConfig);
}

View File

@ -1,6 +1,7 @@
package io.metersphere.project.controller;
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.dto.ModuleDTO;
import io.metersphere.project.request.ProjectApplicationRequest;
import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.project.service.ProjectService;
@ -8,7 +9,6 @@ import io.metersphere.sdk.constants.ModuleType;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.dto.OptionDTO;
import io.metersphere.sdk.dto.SessionUser;
import io.metersphere.system.domain.User;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
@ -25,7 +25,6 @@ import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@ -280,22 +279,17 @@ public class ProjectApplicationController {
}
/**
* ==========全部==========
*/
@GetMapping("/all/{projectId}")
@Operation(summary = "全部-获取配置")
public List<ProjectApplication> getAll(@PathVariable String projectId) {
SessionUser user = Objects.requireNonNull(SessionUtils.getUser());
return projectApplicationService.getAllConfigs(user, projectId);
}
@GetMapping("/module-setting/{projectId}")
@Operation(summary = "获取菜单列表")
public Map<String, Boolean> getModuleSetting(@PathVariable String projectId) {
public List<ModuleDTO> getModuleSetting(@PathVariable String projectId) {
return projectApplicationService.getModuleSetting(projectId);
}
@PostMapping("/validate/{pluginId}")
@Operation(summary = "插件key校验")
public void validateProjectConfig(@PathVariable("pluginId") String pluginId, @RequestBody Map configs) {
projectApplicationService.validateProjectConfig(pluginId, configs);
}
}

View File

@ -0,0 +1,23 @@
package io.metersphere.project.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Data
public class ModuleDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "模块", allowableValues = {"WORKSTATION", "TEST_PLAN", "UI", "PERFORMANCE_TEST", "API", "CASE", "ISSUE"})
private String module;
@Schema(description = "是否启用", allowableValues = {"true", "false"})
private Boolean moduleEnable;
public ModuleDTO(String module, Boolean moduleEnable) {
this.module = module;
this.moduleEnable = moduleEnable;
}
}

View File

@ -1,18 +1,22 @@
package io.metersphere.project.service;
import io.metersphere.plugin.platform.api.AbstractPlatformPlugin;
import io.metersphere.plugin.platform.api.Platform;
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.domain.ProjectApplicationExample;
import io.metersphere.project.dto.ModuleDTO;
import io.metersphere.project.job.CleanUpReportJob;
import io.metersphere.project.job.IssueSyncJob;
import io.metersphere.project.mapper.ExtProjectMapper;
import io.metersphere.project.mapper.ExtProjectUserRoleMapper;
import io.metersphere.project.mapper.ProjectApplicationMapper;
import io.metersphere.project.request.ProjectApplicationRequest;
import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.constants.OperationLogConstants;
import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.constants.ScheduleType;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.dto.OptionDTO;
import io.metersphere.sdk.dto.SessionUser;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.domain.*;
import io.metersphere.system.log.constants.OperationLogModule;
@ -21,6 +25,7 @@ import io.metersphere.system.mapper.ExtPluginMapper;
import io.metersphere.system.mapper.PluginMapper;
import io.metersphere.system.mapper.ServiceIntegrationMapper;
import io.metersphere.system.sechedule.ScheduleService;
import io.metersphere.system.service.PlatformPluginService;
import io.metersphere.system.service.PluginLoadService;
import io.metersphere.system.utils.ServiceUtils;
import io.metersphere.system.utils.SessionUtils;
@ -34,6 +39,8 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND;
@Service
@Transactional
public class ProjectApplicationService {
@ -60,6 +67,9 @@ public class ProjectApplicationService {
@Resource
private ExtProjectMapper extProjectMapper;
@Resource
private PlatformPluginService platformPluginService;
/**
* 更新配置信息
*
@ -194,73 +204,6 @@ public class ProjectApplicationService {
}
/**
* 获取所有配置信息
*
* @param user
* @return
*/
public List<ProjectApplication> getAllConfigs(SessionUser user, String projectId) {
List<ProjectApplication> list = new ArrayList<>();
Boolean flag = checkAdmin(user);
ProjectApplicationExample example = new ProjectApplicationExample();
ProjectApplicationExample.Criteria criteria = example.createCriteria();
criteria.andProjectIdEqualTo(projectId);
if (flag) {
list = projectApplicationMapper.selectByExample(example);
}
List<String> types = checkPermission(user);
if (CollectionUtils.isNotEmpty(types)) {
criteria.andTypeIn(types);
list = projectApplicationMapper.selectByExample(example);
}
return list;
}
private List<String> checkPermission(SessionUser user) {
List<UserRolePermission> permissions = new ArrayList<>();
user.getUserRolePermissions().forEach(g -> {
permissions.addAll(g.getUserRolePermissions());
});
List<String> permissionIds = permissions.stream().map(UserRolePermission::getPermissionId).collect(Collectors.toList());
List<String> types = new ArrayList<>();
permissionIds.forEach(permissionId -> {
switch (permissionId) {
case PermissionConstants.PROJECT_APPLICATION_WORKSTATION_READ ->
types.addAll(Arrays.asList(ProjectApplicationType.WORKSTATION.values()).stream().map(ProjectApplicationType.WORKSTATION::name).collect(Collectors.toList()));
case PermissionConstants.PROJECT_APPLICATION_TEST_PLAN_READ ->
types.addAll(Arrays.asList(ProjectApplicationType.TEST_PLAN.values()).stream().map(ProjectApplicationType.TEST_PLAN::name).collect(Collectors.toList()));
case PermissionConstants.PROJECT_APPLICATION_ISSUE_READ ->
types.addAll(Arrays.asList(ProjectApplicationType.ISSUE.values()).stream().map(ProjectApplicationType.ISSUE::name).collect(Collectors.toList()));
case PermissionConstants.PROJECT_APPLICATION_CASE_READ ->
types.addAll(Arrays.asList(ProjectApplicationType.CASE.values()).stream().map(ProjectApplicationType.CASE::name).collect(Collectors.toList()));
case PermissionConstants.PROJECT_APPLICATION_API_READ ->
types.addAll(Arrays.asList(ProjectApplicationType.API.values()).stream().map(ProjectApplicationType.API::name).collect(Collectors.toList()));
case PermissionConstants.PROJECT_APPLICATION_UI_READ ->
types.addAll(Arrays.asList(ProjectApplicationType.UI.values()).stream().map(ProjectApplicationType.UI::name).collect(Collectors.toList()));
case PermissionConstants.PROJECT_APPLICATION_PERFORMANCE_TEST_READ ->
types.addAll(Arrays.asList(ProjectApplicationType.PERFORMANCE_TEST.values()).stream().map(ProjectApplicationType.PERFORMANCE_TEST::name).collect(Collectors.toList()));
default -> {
}
}
});
return types;
}
private Boolean checkAdmin(SessionUser user) {
long count = user.getUserRoles()
.stream()
.filter(g -> StringUtils.equalsIgnoreCase(g.getId(), InternalUserRole.ADMIN.getValue()))
.count();
if (count > 0) {
return true;
}
return false;
}
/**
* 同步缺陷配置
*
@ -449,6 +392,7 @@ public class ProjectApplicationService {
/**
* 关联需求配置 日志
*
* @param projectId
* @param configs
* @return
@ -469,16 +413,16 @@ public class ProjectApplicationService {
}
/**
* 获取菜单列表
*
* @param projectId
* @return
*/
public Map<String, Boolean> getModuleSetting(String projectId) {
public List<ModuleDTO> getModuleSetting(String projectId) {
String moduleSetting = extProjectMapper.getModuleSetting(projectId);
Map<String, Boolean> moudleMap = new HashMap<>();
List<ModuleDTO> moduleDTOList = new ArrayList<>();
if (StringUtils.isNotEmpty(moduleSetting)) {
ProjectApplicationExample example = new ProjectApplicationExample();
JSON.parseArray(moduleSetting).forEach(module -> {
@ -491,8 +435,9 @@ public class ProjectApplicationService {
moudleMap.put(String.valueOf(module), Boolean.TRUE);
}
});
moduleDTOList = moudleMap.entrySet().stream().map(entry -> new ModuleDTO(entry.getKey(), entry.getValue())).collect(Collectors.toList());
}
return moudleMap;
return moduleDTOList;
}
@ -534,4 +479,27 @@ public class ProjectApplicationService {
}
return collect;
}
/**
* 校验插件key
*
* @param pluginId
* @param configs
*/
public void validateProjectConfig(String pluginId, Map configs) {
Platform platform = this.getPlatform(pluginId);
platform.validateProjectConfig(JSON.toJSONString(configs));
}
private Platform getPlatform(String pluginId) {
ServiceIntegrationExample example = new ServiceIntegrationExample();
example.createCriteria().andPluginIdEqualTo(pluginId);
List<ServiceIntegration> serviceIntegrations = serviceIntegrationMapper.selectByExampleWithBLOBs(example);
if (CollectionUtils.isEmpty(serviceIntegrations)) {
throw new MSException(NOT_FOUND);
}
return platformPluginService.getPlatform(pluginId, serviceIntegrations.get(0).getOrganizationId(), new String(serviceIntegrations.get(0).getConfiguration()));
}
}

View File

@ -1,28 +1,27 @@
package io.metersphere.project.controller;
import com.jayway.jsonpath.JsonPath;
import io.metersphere.project.controller.param.ProjectApplicationDefinition;
import io.metersphere.project.controller.param.ProjectApplicationRequestDefinition;
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.request.ProjectApplicationRequest;
import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.Plugin;
import io.metersphere.system.request.PluginUpdateRequest;
import io.metersphere.system.request.ServiceIntegrationUpdateRequest;
import io.metersphere.system.service.PluginService;
import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.Setter;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.io.File;
import java.io.FileInputStream;
@ -30,9 +29,7 @@ import java.nio.charset.StandardCharsets;
import java.util.*;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ -462,57 +459,6 @@ public class ProjectApplicationControllerTests extends BaseTest {
*/
/**
* 全部
*
* @return
* @throws Exception
*/
public static final String GET_ALL_URL = "/project/application/all";
@Test
@Order(33)
public void testGetAll() throws Exception {
this.loginTest();
this.requestGetTest();
this.requestGetWithOkAndReturn(GET_ALL_URL + "/" + PROJECT_ID);
this.adminlogin();
this.requestGetWithOkAndReturn(GET_ALL_URL + "/" + PROJECT_ID);
}
private void adminlogin() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/login")
.content("{\"username\":\"admin\",\"password\":\"metersphere\"}")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
sessionId = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.sessionId");
csrfToken = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.csrfToken");
}
private void requestGetTest() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get(GET_ALL_URL + "/" + PROJECT_ID)
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken))
.andExpect(status().isOk())
.andDo(print());
}
public void loginTest() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/login")
.content("{\"username\":\"wx-test\",\"password\":\"metersphere\"}")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
sessionId = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.sessionId");
csrfToken = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.csrfToken");
}
public Plugin addPlugin() throws Exception {
PluginUpdateRequest request = new PluginUpdateRequest();
File jarFile = new File(
@ -571,6 +517,9 @@ public class ProjectApplicationControllerTests extends BaseTest {
ResultHolder updateResultHolder = JSON.parseObject(updateData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(updateResultHolder);
congifs.remove("CRON_EXPRESSION");
this.requestPostWithOkAndReturn(UPDATE_ISSUE_CONFIG_URL + "/default-project-2", congifs);
}
private Map<String, String> mockTeseData() {
@ -602,6 +551,7 @@ public class ProjectApplicationControllerTests extends BaseTest {
@Test
@Order(36)
public void testGetModuleSetting() throws Exception {
this.requestGetWithOkAndReturn(GET_MODULE_SETTING_URL + "/100001100002");
MvcResult mvcResult = this.requestGetWithOkAndReturn(GET_MODULE_SETTING_URL + "/100001100001");
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
@ -622,8 +572,6 @@ public class ProjectApplicationControllerTests extends BaseTest {
}
public static final String UPDATE_CASE_RELATED_CONFIG_URL = "/project/application/update/case/related";
public static final String GET_CASE_RELATED_CONFIG_INFO_URL = "/project/application/case/related/info";
@ -669,4 +617,43 @@ public class ProjectApplicationControllerTests extends BaseTest {
// 返回请求正常
Assertions.assertNotNull(resultHolder);
}
public static final String CHECK_PROJECT_KEY_URL = "/project/application/validate";
@Test
@Order(39)
public void testCheckProjectKey() throws Exception {
Map<String, String> configs = new HashMap<>();
configs.put("jiraKey", "Test");
configs.put("jiraIssueTypeId", "10086");
configs.put("jiraStoryTypeId", "10010");
assertErrorCode(this.requestPost(CHECK_PROJECT_KEY_URL + "/" + plugin.getId(), configs), NOT_FOUND);
JiraIntegrationConfig integrationConfig = new JiraIntegrationConfig();
Map<String, Object> integrationConfigMap = JSON.parseMap(JSON.toJSONString(integrationConfig));
ServiceIntegrationUpdateRequest request = new ServiceIntegrationUpdateRequest();
request.setEnable(true);
request.setPluginId(plugin.getId());
request.setConfiguration(integrationConfigMap);
request.setOrganizationId("100001100001");
this.requestPostWithOkAndReturn("/service/integration/add", request);
MvcResult mvcResult = this.requestPostWithOkAndReturn(CHECK_PROJECT_KEY_URL + "/" + plugin.getId(), configs);
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
}
@Getter
@Setter
public class JiraIntegrationConfig {
private String account;
private String password;
private String token;
private String authType;
private String address;
private String version;
}
}