diff --git a/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/dto/PluginOptionsRequest.java b/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/dto/PluginOptionsRequest.java new file mode 100644 index 0000000000..81c8180906 --- /dev/null +++ b/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/dto/PluginOptionsRequest.java @@ -0,0 +1,20 @@ +package io.metersphere.plugin.platform.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * @author wx + */ +@Setter +@Getter +public class PluginOptionsRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private String projectConfig; + private String optionMethod; + +} diff --git a/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/AbstractPlatform.java b/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/AbstractPlatform.java index 57d5733c7d..5fd82e8cd6 100644 --- a/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/AbstractPlatform.java +++ b/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/AbstractPlatform.java @@ -1,10 +1,15 @@ package io.metersphere.plugin.platform.spi; import io.metersphere.plugin.platform.dto.PlatformRequest; +import io.metersphere.plugin.platform.dto.PluginOptionsRequest; +import io.metersphere.plugin.platform.dto.SelectOption; import io.metersphere.plugin.sdk.util.PluginUtils; import io.metersphere.plugin.sdk.util.MSPluginException; import org.apache.commons.lang3.StringUtils; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + public abstract class AbstractPlatform implements Platform { protected PlatformRequest request; @@ -22,4 +27,18 @@ public abstract class AbstractPlatform implements Platform { public String getPluginId() { return request.getPluginId(); } + + + @Override + public List getPluginOptions(PluginOptionsRequest request) { + String method = request.getOptionMethod(); + try { + // 这里反射调用 getIssueTypes 等方法,获取下拉框选项 + return (List) this.getClass().getMethod(method, request.getClass()).invoke(this, request); + } catch (InvocationTargetException e) { + throw new MSPluginException(e.getTargetException()); + } catch (Exception e) { + throw new MSPluginException(e); + } + } } diff --git a/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/Platform.java b/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/Platform.java index 865af9048b..199973f935 100644 --- a/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/Platform.java +++ b/backend/framework/plugin/plugin-platform-sdk/src/main/java/io/metersphere/plugin/platform/spi/Platform.java @@ -1,6 +1,8 @@ package io.metersphere.plugin.platform.spi; import io.metersphere.plugin.platform.dto.PlatformCustomFieldItemDTO; +import io.metersphere.plugin.platform.dto.PluginOptionsRequest; +import io.metersphere.plugin.platform.dto.SelectOption; import org.pf4j.ExtensionPoint; import java.util.List; @@ -35,4 +37,11 @@ public interface Platform extends ExtensionPoint { * @return */ List getThirdPartCustomField(String projectConfig); + + /** + * 获取第三方联级下拉options + * @param optionsRequest + * @return + */ + List getPluginOptions(PluginOptionsRequest optionsRequest); } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PluginController.java b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PluginController.java index a2fefbc0c1..ccbcba78ca 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PluginController.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PluginController.java @@ -1,9 +1,11 @@ package io.metersphere.system.controller; +import io.metersphere.plugin.platform.dto.SelectOption; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.sdk.util.BeanUtils; +import io.metersphere.system.request.PlatformOptionRequest; import io.metersphere.system.utils.SessionUtils; import io.metersphere.system.domain.Plugin; import io.metersphere.system.dto.PluginDTO; @@ -91,4 +93,12 @@ public class PluginController { HttpServletResponse response) throws IOException { pluginService.getPluginImg(pluginId, imagePath, response); } + + @PostMapping("/options") + @Operation(summary = "获取插件下拉选项") + public List getPluginOptions(@RequestBody PlatformOptionRequest request) { + return pluginService.getPluginOptions(request); + } + + } \ No newline at end of file diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/request/PlatformOptionRequest.java b/backend/services/system-setting/src/main/java/io/metersphere/system/request/PlatformOptionRequest.java new file mode 100644 index 0000000000..8787a10f1d --- /dev/null +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/request/PlatformOptionRequest.java @@ -0,0 +1,28 @@ +package io.metersphere.system.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * @author wx + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class PlatformOptionRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "插件id") + private String pluginId; + @Schema(description = "组织id") + private String organizationId; + + @Schema(description = "方法") + private String optionMethod; + @Schema(description = "输入参数") + private String projectConfig; + +} 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 2ab9789dcc..fd421badea 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 @@ -2,7 +2,10 @@ package io.metersphere.system.service; import io.metersphere.plugin.api.spi.AbstractApiPlugin; +import io.metersphere.plugin.platform.dto.PluginOptionsRequest; +import io.metersphere.plugin.platform.dto.SelectOption; import io.metersphere.plugin.platform.spi.AbstractPlatformPlugin; +import io.metersphere.plugin.platform.spi.Platform; import io.metersphere.plugin.sdk.spi.MsPlugin; import io.metersphere.sdk.constants.KafkaTopicConstants; import io.metersphere.sdk.constants.PluginScenarioType; @@ -17,6 +20,7 @@ import io.metersphere.system.dto.PluginDTO; import io.metersphere.system.dto.PluginNotifiedDTO; import io.metersphere.system.mapper.ExtPluginMapper; import io.metersphere.system.mapper.PluginMapper; +import io.metersphere.system.request.PlatformOptionRequest; import io.metersphere.system.request.PluginUpdateRequest; import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; @@ -64,6 +68,8 @@ public class PluginService { private KafkaTemplate kafkaTemplate; @Resource private UserLoginService userLoginService; + @Resource + private PlatformPluginService platformPluginService; public List list() { List plugins = extPluginMapper.getPlugins(); @@ -287,4 +293,16 @@ public class PluginService { out.flush(); } } + + public List getPluginOptions(PlatformOptionRequest request) { + try { + Platform platform = platformPluginService.getPlatform(request.getPluginId(), request.getOrganizationId()); + PluginOptionsRequest optionsRequest = new PluginOptionsRequest(); + optionsRequest.setOptionMethod(request.getOptionMethod()); + optionsRequest.setProjectConfig(request.getProjectConfig()); + return platform.getPluginOptions(optionsRequest); + }catch (Exception e){ + return new ArrayList<>(); + } + } } \ No newline at end of file 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 fcf33aa299..11288f5edd 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 @@ -1,28 +1,37 @@ package io.metersphere.system.controller; -import io.metersphere.system.base.BaseTest; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PluginScenarioType; -import io.metersphere.system.dto.sdk.OptionDTO; -import io.metersphere.system.log.constants.OperationLogType; -import io.metersphere.system.service.UserLoginService; -import io.metersphere.system.service.JdbcDriverPluginService; +import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.util.JSON; +import io.metersphere.system.base.BasePluginTestService; +import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.param.PluginUpdateRequestDefinition; import io.metersphere.system.domain.*; import io.metersphere.system.dto.OrganizationDTO; import io.metersphere.system.dto.PluginDTO; +import io.metersphere.system.dto.sdk.OptionDTO; +import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.mapper.PluginMapper; import io.metersphere.system.mapper.PluginOrganizationMapper; import io.metersphere.system.mapper.PluginScriptMapper; +import io.metersphere.system.request.PlatformOptionRequest; import io.metersphere.system.request.PluginUpdateRequest; +import io.metersphere.system.service.JdbcDriverPluginService; import io.metersphere.system.service.OrganizationService; +import io.metersphere.system.service.PluginService; +import io.metersphere.system.service.UserLoginService; import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.*; +import org.mockserver.client.MockServerClient; +import org.mockserver.model.Header; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.util.MultiValueMap; import java.io.File; @@ -32,6 +41,8 @@ import java.util.stream.Collectors; import static io.metersphere.system.controller.handler.result.CommonResultCode.FILE_NAME_ILLEGAL; import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND; import static io.metersphere.system.controller.result.SystemResultCode.*; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** @@ -60,6 +71,19 @@ public class PluginControllerTests extends BaseTest { private static Plugin addPlugin; private static Plugin anotherAddPlugin; + @Resource + private PluginService pluginService; + public static final String PLUGIN_OPTIONS_URL = "/plugin/options"; + @Resource + private MockServerClient mockServerClient; + @Value("${embedded.mockserver.host}") + private String mockServerHost; + @Value("${embedded.mockserver.port}") + private int mockServerHostPort; + + @Resource + private BasePluginTestService basePluginTestService; + @Override protected String getBasePath() { return BASE_PATH; @@ -325,4 +349,41 @@ public class PluginControllerTests extends BaseTest { .map(PluginScript::getScriptId) .toList(); } + + + @Test + @Order(7) + public void getPluginOptions() throws Exception { + Plugin plugin = basePluginTestService.addJiraPlugin(); + PlatformOptionRequest optionsRequest = new PlatformOptionRequest(); + optionsRequest.setPluginId(plugin.getId()); + optionsRequest.setOrganizationId(DEFAULT_ORGANIZATION_ID); + optionsRequest.setOptionMethod("getBugTypeId"); + optionsRequest.setProjectConfig("{\"jiraKey\":\"TES2\"}"); + this.requestPostTest(PLUGIN_OPTIONS_URL, optionsRequest); + basePluginTestService.addServiceIntegration("100001100001"); + mockServerClient + .when( + request() + .withMethod("GET") + .withPath("/issuetype/project?projectId=TES2")) + .respond( + response() + .withStatusCode(200) + .withHeaders( + new Header("Content-Type", "application/json; charset=utf-8"), + new Header("Cache-Control", "public, max-age=86400")) + .withBody("{\"id\":\"123456\",\"name\":\"test\"}") + ); + this.requestPostTest(PLUGIN_OPTIONS_URL, optionsRequest); + // 获取返回值 + } + + private void requestPostTest(String url, Object param) throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post(url) + .header(SessionConstants.HEADER_TOKEN, sessionId) + .header(SessionConstants.CSRF_TOKEN, csrfToken) + .content(JSON.toJSONString(param)) + .contentType(MediaType.APPLICATION_JSON)); + } } \ No newline at end of file