diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java index ab28bfb079..667662ccb5 100644 --- a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractMsTestElement.java @@ -7,9 +7,14 @@ import lombok.Data; import java.util.LinkedList; /** -*@Author: jianxing -*@CreateTime: 2023-10-30 15:08 -*/ + * + *
+ * 该对象传参时,需要传入 polymorphicName 字段,用于区分是哪个协议的组件 + * 对应协议的组件 polymorphicName 字段,调用 /api/test/protocol/{organizationId} 接口获取 + *+ * @Author: jianxing + * @CreateTime: 2023-10-30 15:08 + */ @Data @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "polymorphicName") @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java index 2614596d53..97d7e096a0 100644 --- a/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java +++ b/backend/framework/plugin/plugin-api-sdk/src/main/java/io/metersphere/plugin/api/spi/AbstractProtocolPlugin.java @@ -7,9 +7,30 @@ package io.metersphere.plugin.api.spi; */ public abstract class AbstractProtocolPlugin extends AbstractApiPlugin { + private static final String DEFAULT_API_PROTOCOL_SCRIPT_ID = "api"; + private static final String DEFAULT_ENVIRONMENT_PROTOCOL_SCRIPT_ID = "environment"; + /** * 返回协议名 * @return */ abstract public String getProtocol(); + + /** + * 返回接口协议主页面的脚本的ID,默认为 api + * 可以重写此方法,返回自定义的脚本ID + * @return + */ + public String getApiProtocolScriptId() { + return DEFAULT_API_PROTOCOL_SCRIPT_ID; + } + + /** + * 返回协议环境配置页面的脚本的ID,默认为 environment + * 可以重写此方法,返回自定义的脚本ID + * @return + */ + public String getEnvProtocolScriptId() { + return DEFAULT_ENVIRONMENT_PROTOCOL_SCRIPT_ID; + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java index feef5c6b87..2adf17048a 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/ApiTestController.java @@ -38,7 +38,6 @@ public class ApiTestController { return apiTestService.getProtocols(organizationId); } - @GetMapping("/mock/{key}") @Operation(summary = "获取mock数据") public String mock(@PathVariable String key) { @@ -52,6 +51,18 @@ public class ApiTestController { return apiExecuteService.runScript(runRequest); } + @GetMapping("/plugin/script/{pluginId}") + @Operation(summary = "获取协议插件的的协议列表") + @RequiresPermissions(value = { + PermissionConstants.PROJECT_API_DEFINITION_READ, + PermissionConstants.PROJECT_API_DEFINITION_CASE_READ, + PermissionConstants.PROJECT_API_DEBUG_READ, + PermissionConstants.PROJECT_API_SCENARIO_READ + }, logical = Logical.OR) + public Object getApiProtocolScript(@PathVariable String pluginId) { + return apiTestService.getApiProtocolScript(pluginId); + } + @PostMapping("/plugin/form/option") @Operation(summary = "接口测试-获取插件表单选项") @RequiresPermissions(value = { diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/BinaryBody.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/BinaryBody.java index 6558b883a2..8487d99d52 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/BinaryBody.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/http/body/BinaryBody.java @@ -9,7 +9,7 @@ import lombok.Data; * @CreateTime: 2023-11-06 18:25 */ @Data -public class BinaryBody extends ApiFile{ +public class BinaryBody extends ApiFile { /** * 描述 */ diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java index 7f1f135624..6cfac1e22d 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiTestService.java @@ -6,9 +6,11 @@ import io.metersphere.api.dto.request.http.MsHTTPElement; import io.metersphere.plugin.api.dto.ApiPluginOptionsRequest; import io.metersphere.plugin.api.dto.ApiPluginSelectOption; import io.metersphere.plugin.api.spi.AbstractApiPlugin; +import io.metersphere.plugin.api.spi.AbstractProtocolPlugin; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.system.dto.ProtocolDTO; import io.metersphere.system.service.ApiPluginService; +import io.metersphere.system.service.PluginLoadService; import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; @@ -28,6 +30,8 @@ public class ApiTestService { @Resource private ApiPluginService apiPluginService; + @Resource + private PluginLoadService pluginLoadService; public ListgetProtocols(String orgId) { List protocols = apiPluginService.getProtocols(orgId); @@ -48,10 +52,25 @@ public class ApiTestService { .orElse(null); if (pluginWrapper == null || !(pluginWrapper.getPlugin() instanceof AbstractApiPlugin)) { // 插件不存在或者非接口插件,抛出异常 - ServiceUtils.checkResourceExist(null, "permission.api_plugin.name"); + checkResourceExist(null); } ApiPluginOptionsRequest optionsRequest = BeanUtils.copyBean(new ApiPluginOptionsRequest(), request); assert pluginWrapper != null; return ((AbstractApiPlugin) pluginWrapper.getPlugin()).getPluginOptions(optionsRequest); } + + public Object getApiProtocolScript(String pluginId) { + PluginWrapper pluginWrapper = pluginLoadService.getPluginWrapper(pluginId); + checkResourceExist(pluginWrapper); + if (pluginWrapper.getPlugin() instanceof AbstractProtocolPlugin protocolPlugin) { + return pluginLoadService.getPluginScriptContent(pluginId, protocolPlugin.getApiProtocolScriptId()); + } else { + // 插件不存在或者非接口插件,抛出异常 + return checkResourceExist(null); + } + } + + public Object checkResourceExist(PluginWrapper pluginWrapper) { + return ServiceUtils.checkResourceExist(pluginWrapper, "permission.system_plugin.name"); + } } \ No newline at end of file diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java index 5e583efa68..81462f82b8 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestControllerTests.java @@ -14,10 +14,7 @@ import io.metersphere.system.dto.request.PluginUpdateRequest; import io.metersphere.system.service.PluginService; import io.metersphere.system.uid.IDGenerator; import jakarta.annotation.Resource; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.*; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.mock.web.MockMultipartFile; @@ -28,6 +25,7 @@ import java.io.FileInputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import static io.metersphere.sdk.constants.InternalUserRole.ADMIN; import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND; @@ -46,6 +44,7 @@ public class ApiTestControllerTests extends BaseTest { protected static final String MOCK = "mock/{0}"; protected static final String CUSTOM_FUNC_RUN = "custom/func/run"; protected static final String PLUGIN_FORM_OPTION = "plugin/form/option"; + protected static final String PLUGIN_SCRIPT = "plugin/script/{0}"; @Resource private BaseResourcePoolTestService baseResourcePoolTestService; @@ -98,6 +97,7 @@ public class ApiTestControllerTests extends BaseTest { } @Test + @Order(10) public void getFormOptions() throws Exception { ApiTestPluginOptionRequest request = new ApiTestPluginOptionRequest(); request.setOrgId(DEFAULT_ORGANIZATION_ID); @@ -127,6 +127,30 @@ public class ApiTestControllerTests extends BaseTest { }}, PLUGIN_FORM_OPTION, request); } + @Test + @Order(11) + public void getApiProtocolScript() throws Exception { + assertErrorCode(this.requestGet(PLUGIN_SCRIPT, "aa"), NOT_FOUND); + Plugin jiraPlugin = basePluginTestService.addJiraPlugin(); + assertErrorCode(this.requestGet(PLUGIN_SCRIPT, jiraPlugin.getId()), NOT_FOUND); + // @@请求成功 + Plugin plugin = addTcpTestPlugin(); + MvcResult mvcResult = this.requestGetWithOkAndReturn(PLUGIN_SCRIPT, plugin.getId()); + Object resultData = getResultData(mvcResult, Object.class); + Assertions.assertNotNull(resultData); + + basePluginTestService.deleteJiraPlugin(); + pluginService.delete(plugin.getId()); + + // @@校验权限 + requestGetPermissionsTest(new ArrayList<>() {{ + add(PermissionConstants.PROJECT_API_DEFINITION_READ); + add(PermissionConstants.PROJECT_API_DEFINITION_CASE_READ); + add(PermissionConstants.PROJECT_API_DEBUG_READ); + add(PermissionConstants.PROJECT_API_SCENARIO_READ); + }}, PLUGIN_SCRIPT, "11"); + } + public Plugin addOptionTestPlugin() throws Exception { PluginUpdateRequest request = new PluginUpdateRequest(); File jarFile = new File( @@ -142,4 +166,19 @@ public class ApiTestControllerTests extends BaseTest { return pluginService.add(request, mockMultipartFile); } + public Plugin addTcpTestPlugin() throws Exception { + PluginUpdateRequest request = new PluginUpdateRequest(); + File jarFile = new File( + this.getClass().getClassLoader().getResource("file/tcp-sampler-v3.x.jar") + .getPath() + ); + FileInputStream inputStream = new FileInputStream(jarFile); + MockMultipartFile mockMultipartFile = new MockMultipartFile(jarFile.getName(), jarFile.getName(), "jar", inputStream); + request.setName("测试TCP插件"); + request.setGlobal(true); + request.setEnable(true); + request.setCreateUser(ADMIN.name()); + return pluginService.add(request, mockMultipartFile); + } + } diff --git a/backend/services/api-test/src/test/resources/file/tcp-sampler-v3.x.jar b/backend/services/api-test/src/test/resources/file/tcp-sampler-v3.x.jar new file mode 100644 index 0000000000..c15a551671 Binary files /dev/null and b/backend/services/api-test/src/test/resources/file/tcp-sampler-v3.x.jar differ diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/EnvironmentService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/EnvironmentService.java index c76b767893..ba252852fd 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/EnvironmentService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/EnvironmentService.java @@ -1,6 +1,7 @@ package io.metersphere.project.service; +import io.metersphere.plugin.api.spi.AbstractProtocolPlugin; import io.metersphere.project.domain.Project; import io.metersphere.project.domain.ProjectExample; import io.metersphere.project.dto.environment.*; @@ -39,6 +40,7 @@ import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.pf4j.Plugin; import org.pf4j.PluginWrapper; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -388,13 +390,17 @@ public class EnvironmentService { public List getPluginScripts(String projectId) { Project project = projectService.checkProjectNotExist(projectId); - // 查询组织下有权限的接口插件ID - List orgApiPluginIds = apiPluginService.getOrgApiPluginWrappers(project.getOrganizationId()) - .stream() - .map(PluginWrapper::getPluginId) - .collect(Collectors.toList()); - // 查询环境页面脚本 - List pluginScripts = pluginScriptService.getByPluginIdsAndScriptId(orgApiPluginIds, "environment"); + // 查询组织下有权限的接口插件 + List orgApiPluginWrappers = apiPluginService.getOrgApiPluginWrappers(project.getOrganizationId()); + + // 接口协议环境脚本 + List pluginScripts = new ArrayList<>(orgApiPluginWrappers.size()); + orgApiPluginWrappers.stream().forEach(wrapper -> { + Plugin plugin = wrapper.getPlugin(); + if (plugin instanceof AbstractProtocolPlugin protocolPlugin) { + pluginScripts.add(pluginScriptService.get(wrapper.getPluginId(), protocolPlugin.getEnvProtocolScriptId())); + } + }); // 返回环境脚本列表 return pluginScripts.stream().map(pluginScript -> { diff --git a/backend/services/project-management/src/test/resources/file/tcp-sampler-v3.x-jar-with-dependencies.jar b/backend/services/project-management/src/test/resources/file/tcp-sampler-v3.x-jar-with-dependencies.jar index 3c0fe0ccbe..ed67930359 100644 Binary files a/backend/services/project-management/src/test/resources/file/tcp-sampler-v3.x-jar-with-dependencies.jar and b/backend/services/project-management/src/test/resources/file/tcp-sampler-v3.x-jar-with-dependencies.jar differ diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginScriptService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginScriptService.java index bc1efce051..29dc48adb9 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginScriptService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginScriptService.java @@ -64,11 +64,15 @@ public class PluginScriptService { pluginScriptMapper.deleteByExample(example); } - public String get(String pluginId, String scriptId) { - PluginScript frontScript = pluginScriptMapper.selectByPrimaryKey(pluginId, scriptId); + public String getScriptContent(String pluginId, String scriptId) { + PluginScript frontScript = get(pluginId, scriptId); return frontScript == null ? null : new String(frontScript.getScript()); } + public PluginScript get(String pluginId, String scriptId) { + return pluginScriptMapper.selectByPrimaryKey(pluginId, scriptId); + } + public Map > getScripteMap(List pluginIds) { if (CollectionUtils.isEmpty(pluginIds)) { return Collections.emptyMap(); @@ -83,15 +87,5 @@ public class PluginScriptService { scriptList.add(optionDTO); } return scriptMap; - - } - - public List getByPluginIdsAndScriptId(List pluginIds, String scriptId) { - if (CollectionUtils.isEmpty(pluginIds)) { - return Collections.emptyList(); - } - PluginScriptExample example = new PluginScriptExample(); - example.createCriteria().andScriptIdEqualTo(scriptId); - return pluginScriptMapper.selectByExampleWithBLOBs(example); } } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginService.java index b66b87b7a9..ae19ab3b83 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/service/PluginService.java @@ -264,7 +264,7 @@ public class PluginService { } public String getScript(String pluginId, String scriptId) { - return pluginScriptService.get(pluginId, scriptId); + return pluginScriptService.getScriptContent(pluginId, scriptId); } public void getPluginImg(String pluginId, String filePath, HttpServletResponse response) throws IOException { diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/PluginControllerTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/PluginControllerTests.java index 96d44abcc9..ca46753578 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/PluginControllerTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/PluginControllerTests.java @@ -317,10 +317,6 @@ public class PluginControllerTests extends BaseTest { // @@请求成功 MvcResult mvcResult = this.requestGetWithOk(SCRIPT_GET, this.addPlugin.getId(), "connect").andReturn(); - // 增加覆盖率 - pluginScriptService.getByPluginIdsAndScriptId(List.of(), "connect"); - pluginScriptService.getByPluginIdsAndScriptId(List.of(addPlugin.getId()), "connect"); - // 校验数据是否正确 Assertions.assertTrue(StringUtils.isNotBlank(getResultData(mvcResult, String.class))); // @@校验权限