diff --git a/backend/src/main/java/io/metersphere/api/controller/APITestController.java b/backend/src/main/java/io/metersphere/api/controller/APITestController.java index 78bd6367af..e50b94d837 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APITestController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APITestController.java @@ -14,7 +14,6 @@ import io.metersphere.api.service.*; import io.metersphere.base.domain.ApiTest; import io.metersphere.base.domain.Schedule; import io.metersphere.commons.constants.RoleConstants; -import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.utils.CronUtils; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; @@ -59,7 +58,7 @@ public class APITestController { @Resource private ScheduleService scheduleService; @Resource - private APIReportService apiReportService; + private HistoricalDataUpgradeService historicalDataUpgradeService; @GetMapping("recent/{count}") public List recentTest(@PathVariable int count) { @@ -359,4 +358,8 @@ public class APITestController { schedule.setEnable(request.isEnable()); apiAutomationService.updateSchedule(schedule); } + @PostMapping(value = "/historicalDataUpgrade") + public String historicalDataUpgrade(@RequestBody SaveHistoricalDataUpgrade request) { + return historicalDataUpgradeService.upgrade(request); + } } diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java index 2f8fbdbc06..0fee8b53b1 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -121,5 +121,6 @@ public class ApiAutomationController { public void createSchedule(@RequestBody Schedule request) { apiAutomationService.createSchedule(request); } + } diff --git a/backend/src/main/java/io/metersphere/api/dto/SaveHistoricalDataUpgrade.java b/backend/src/main/java/io/metersphere/api/dto/SaveHistoricalDataUpgrade.java new file mode 100644 index 0000000000..61e084790b --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/SaveHistoricalDataUpgrade.java @@ -0,0 +1,18 @@ +package io.metersphere.api.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Setter +@Getter +public class SaveHistoricalDataUpgrade { + private List testIds; + + private String projectId; + + private String modulePath; + + private String moduleId; +} diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java index 6d97c94cc3..432d3e73e8 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsDubboSampler.java @@ -31,7 +31,7 @@ public class MsDubboSampler extends MsTestElement { private String type = "DubboSampler"; @JSONField(ordinal = 52) - private String protocol; + private String protocol = "DUBBO"; @JsonProperty(value = "interface") @JSONField(ordinal = 53, name = "interface") private String _interface; diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index 4770e79c04..dbfa8b8173 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -172,7 +172,7 @@ public class MsHTTPSamplerProxy extends MsTestElement { LogUtil.error(e); } // REST参数 - if (CollectionUtils.isNotEmpty(this.getArguments())) { + if (CollectionUtils.isNotEmpty(this.getRest())) { sampler.setArguments(httpArguments(this.getRest())); } // 请求参数 @@ -186,7 +186,9 @@ public class MsHTTPSamplerProxy extends MsTestElement { if (StringUtils.isNotEmpty(this.body.getType()) && this.body.getType().equals("Form Data")) { sampler.setDoMultipart(true); } - sampler.setArguments(httpArguments(bodyParams)); + if (CollectionUtils.isNotEmpty(bodyParams)) { + sampler.setArguments(httpArguments(bodyParams)); + } } } diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java index 4065544e7b..bfc0729c12 100644 --- a/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java @@ -42,7 +42,11 @@ public class Body { return true; } else return false; } - + public boolean isOldKV() { + if (StringUtils.equals(type, KV)) { + return true; + } else return false; + } public List getBodyParams(HTTPSamplerProxy sampler, String requestId) { List body = new ArrayList<>(); if (this.isKV() || this.isBinary()) { diff --git a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java index 0fde847e07..e5f05b7805 100644 --- a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java @@ -2,6 +2,7 @@ package io.metersphere.api.parse; import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.definition.ApiDefinitionResult; +import io.metersphere.api.dto.definition.ApiModuleDTO; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; @@ -11,6 +12,8 @@ import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.BeanUtils; +import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.SessionUtils; import org.apache.commons.collections.CollectionUtils; @@ -60,6 +63,32 @@ public abstract class ApiImportAbstractParser implements ApiImportParser { } } + protected ApiModule getSelectModule(String moduleId) { + apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); + if (StringUtils.isNotBlank(moduleId)) { + ApiModule module = new ApiModule(); + ApiModuleDTO moduleDTO = apiModuleService.getNode(moduleId); + BeanUtils.copyBean(module, moduleDTO); + return module; + } + return null; + } + + protected ApiModule buildModule(ApiModule parentModule, String name, boolean isSaved) { + apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); + ApiModule module; + if (parentModule != null) { + module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1); + module.setParentId(parentModule.getId()); + } else { + module = apiModuleService.getNewModule(name, this.projectId, 1); + } + if (isSaved) { + createModule(module); + } + return module; + } + protected void createModule(ApiModule module) { module.setProtocol(RequestType.HTTP); List apiModules = apiModuleService.selectSameModule(module); diff --git a/backend/src/main/java/io/metersphere/api/parse/MsParser.java b/backend/src/main/java/io/metersphere/api/parse/MsParser.java index 512965d760..0838445d12 100644 --- a/backend/src/main/java/io/metersphere/api/parse/MsParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/MsParser.java @@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; import io.metersphere.api.dto.ApiTestImportRequest; import io.metersphere.api.dto.definition.ApiDefinitionResult; +import io.metersphere.api.dto.definition.ApiModuleDTO; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.scenario.Body; @@ -31,7 +32,7 @@ public class MsParser extends ApiImportAbstractParser { if (testObject.get("projectName") != null) { return parseMsFormat(testStr, request); } else { - return parsePluginFormat(testObject, request.isSaved()); + return parsePluginFormat(testObject, request); } } @@ -44,7 +45,7 @@ public class MsParser extends ApiImportAbstractParser { if (StringUtils.isBlank(apiDefinition.getModulePath())) { apiDefinition.setModuleId(null); } - parseModule(apiDefinition, importRequest.isSaved()); + parseModule(apiDefinition, importRequest); apiDefinition.setId(id); apiDefinition.setProjectId(this.projectId); String request = apiDefinition.getRequest(); @@ -55,16 +56,16 @@ public class MsParser extends ApiImportAbstractParser { return apiDefinitionImport; } - private ApiDefinitionImport parsePluginFormat(JSONObject testObject, boolean isSaved) { + private ApiDefinitionImport parsePluginFormat(JSONObject testObject, ApiTestImportRequest importRequest) { List results = new ArrayList<>(); ApiDefinitionImport apiImport = new ApiDefinitionImport(); apiImport.setProtocol(RequestType.HTTP); apiImport.setData(results); testObject.keySet().forEach(tag -> { - ApiModule module = apiModuleService.getNewModule(tag, this.projectId, 1); - if (isSaved) { - createModule(module); - } + + ApiModule parentModule = getSelectModule(importRequest.getModuleId()); + ApiModule module = buildModule(parentModule, tag, importRequest.isSaved()); + JSONObject requests = testObject.getJSONObject(tag); requests.keySet().forEach(requestName -> { @@ -125,7 +126,7 @@ public class MsParser extends ApiImportAbstractParser { } - private void parseModule(ApiDefinitionResult apiDefinition, Boolean isSaved) { + private void parseModule(ApiDefinitionResult apiDefinition, ApiTestImportRequest importRequest) { String modulePath = apiDefinition.getModulePath(); if (StringUtils.isBlank(modulePath)) { return; @@ -137,29 +138,14 @@ public class MsParser extends ApiImportAbstractParser { modulePath = modulePath.substring(0, modulePath.length() - 1); } List modules = Arrays.asList(modulePath.split("/")); - ApiModule parent = null; + ApiModule parent = getSelectModule(importRequest.getModuleId()); Iterator iterator = modules.iterator(); while (iterator.hasNext()) { String item = iterator.next(); - parent = buildModule(item, parent, isSaved); + parent = buildModule(parent, item, importRequest.isSaved()); if (!iterator.hasNext()) { apiDefinition.setModuleId(parent.getId()); } } } - - private ApiModule buildModule(String name, ApiModule parentModule, boolean isSaved) { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module; - if (parentModule != null) { - module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1); - module.setParentId(parentModule.getId()); - } else { - module = apiModuleService.getNewModule(name, this.projectId, 1); - } - if (isSaved) { - createModule(module); - } - return module; - } } diff --git a/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java b/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java index 9809326b35..71d2379d3e 100644 --- a/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/PostmanParser.java @@ -9,11 +9,9 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; import io.metersphere.api.dto.parse.postman.*; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; -import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.constants.MsRequestBodyType; import io.metersphere.commons.constants.PostmanRequestBodyMode; -import io.metersphere.commons.utils.CommonBeanFactory; import org.apache.commons.lang3.StringUtils; import java.io.InputStream; @@ -30,7 +28,7 @@ public class PostmanParser extends ApiImportAbstractParser { List variables = postmanCollection.getVariable(); ApiDefinitionImport apiImport = new ApiDefinitionImport(); List results = new ArrayList<>(); - parseItem(postmanCollection.getItem(), variables, results, buildModule(postmanCollection.getInfo().getName(), null, request.isSaved()), request.isSaved()); + parseItem(postmanCollection.getItem(), variables, results, buildModule(getSelectModule(request.getModuleId()), postmanCollection.getInfo().getName(), request.isSaved()), request.isSaved()); apiImport.setData(results); return apiImport; } @@ -39,7 +37,7 @@ public class PostmanParser extends ApiImportAbstractParser { for (PostmanItem item : items) { List childItems = item.getItem(); if (childItems != null) { - ApiModule module = buildModule(item.getName(), parentModule, isSaved); + ApiModule module = buildModule(parentModule, item.getName() , isSaved); parseItem(childItems, variables, results, module, isSaved); } else { ApiDefinitionResult request = parsePostman(item); @@ -53,21 +51,6 @@ public class PostmanParser extends ApiImportAbstractParser { } } - private ApiModule buildModule(String name, ApiModule parentModule, boolean isSaved) { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module; - if (parentModule != null) { - module = apiModuleService.getNewModule(name, this.projectId, parentModule.getLevel() + 1); - module.setParentId(parentModule.getId()); - } else { - module = apiModuleService.getNewModule(name, this.projectId, 1); - } - if (isSaved) { - createModule(module); - } - return module; - } - private ApiDefinitionResult parsePostman(PostmanItem requestItem) { PostmanRequest requestDesc = requestItem.getRequest(); if (requestDesc == null) { diff --git a/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java b/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java index d61d9af101..b080aa2e23 100644 --- a/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java +++ b/backend/src/main/java/io/metersphere/api/parse/Swagger2Parser.java @@ -11,10 +11,8 @@ import io.metersphere.api.dto.definition.response.HttpResponse; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.request.RequestType; -import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.constants.SwaggerParameterType; -import io.metersphere.commons.utils.CommonBeanFactory; import io.swagger.models.*; import io.swagger.models.parameters.*; import io.swagger.models.properties.*; @@ -25,7 +23,7 @@ import org.apache.commons.lang3.StringUtils; import java.io.InputStream; import java.util.*; -public class Swagger2Parser extends ApiImportAbstractParser { +public class Swagger2Parser extends SwaggerAbstractParser { private Map definitions = null; @@ -47,11 +45,11 @@ public class Swagger2Parser extends ApiImportAbstractParser { ApiDefinitionImport definitionImport = new ApiDefinitionImport(); this.projectId = request.getProjectId(); - definitionImport.setData(parseRequests(swagger, request.isSaved())); + definitionImport.setData(parseRequests(swagger, request)); return definitionImport; } - private List parseRequests(Swagger swagger, boolean isSaved) { + private List parseRequests(Swagger swagger, ApiTestImportRequest importRequest) { Map paths = swagger.getPaths(); Set pathNames = paths.keySet(); @@ -59,6 +57,8 @@ public class Swagger2Parser extends ApiImportAbstractParser { List results = new ArrayList<>(); + ApiModule parentNode = getSelectModule(importRequest.getModuleId()); + for (String pathName : pathNames) { Path path = paths.get(pathName); Map operationMap = path.getOperationMap(); @@ -70,7 +70,7 @@ public class Swagger2Parser extends ApiImportAbstractParser { parseParameters(operation, request); apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses()))); - buildModule(apiDefinition, operation, isSaved); + buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved()); results.add(apiDefinition); } } @@ -79,20 +79,6 @@ public class Swagger2Parser extends ApiImportAbstractParser { return results; } - private void buildModule(ApiDefinitionResult apiDefinition, Operation operation, boolean isSaved) { - List tags = operation.getTags(); - if (tags != null) { - tags.forEach(tag -> { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module = apiModuleService.getNewModule(tag, this.projectId, 1); - if (isSaved) { - createModule(module); - } - apiDefinition.setModuleId(module.getId()); - }); - } - } - private ApiDefinitionResult buildApiDefinition(String id, Operation operation, String path, String method) { String name = ""; if (StringUtils.isNotBlank(operation.getSummary())) { diff --git a/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java b/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java index 92edcfddf1..ac6ae883fa 100644 --- a/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java +++ b/backend/src/main/java/io/metersphere/api/parse/Swagger3Parser.java @@ -11,10 +11,8 @@ import io.metersphere.api.dto.definition.response.HttpResponse; import io.metersphere.api.dto.scenario.Body; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.request.RequestType; -import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.exception.MSException; -import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.XMLUtils; import io.swagger.parser.OpenAPIParser; @@ -34,7 +32,7 @@ import java.io.InputStream; import java.util.*; -public class Swagger3Parser extends ApiImportAbstractParser { +public class Swagger3Parser extends SwaggerAbstractParser { private Components components; @@ -67,11 +65,11 @@ public class Swagger3Parser extends ApiImportAbstractParser { ApiDefinitionImport definitionImport = new ApiDefinitionImport(); this.projectId = request.getProjectId(); - definitionImport.setData(parseRequests(openAPI, request.isSaved())); + definitionImport.setData(parseRequests(openAPI, request)); return definitionImport; } - private List parseRequests(OpenAPI openAPI, boolean isSaved) { + private List parseRequests(OpenAPI openAPI, ApiTestImportRequest importRequest) { Paths paths = openAPI.getPaths(); Set pathNames = paths.keySet(); @@ -80,6 +78,8 @@ public class Swagger3Parser extends ApiImportAbstractParser { List results = new ArrayList<>(); + ApiModule parentNode = getSelectModule(importRequest.getModuleId()); + for (String pathName : pathNames) { PathItem pathItem = paths.get(pathName); @@ -102,7 +102,7 @@ public class Swagger3Parser extends ApiImportAbstractParser { parseRequestBody(operation.getRequestBody(), request.getBody()); apiDefinition.setRequest(JSON.toJSONString(request)); apiDefinition.setResponse(JSON.toJSONString(parseResponse(operation.getResponses()))); - buildModule(apiDefinition, operation, isSaved); + buildModule(parentNode, apiDefinition, operation.getTags(), importRequest.isSaved()); results.add(apiDefinition); } } @@ -111,20 +111,6 @@ public class Swagger3Parser extends ApiImportAbstractParser { return results; } - private void buildModule(ApiDefinitionResult apiDefinition, Operation operation, boolean isSaved) { - List tags = operation.getTags(); - if (tags != null) { - tags.forEach(tag -> { - apiModuleService = CommonBeanFactory.getBean(ApiModuleService.class); - ApiModule module = apiModuleService.getNewModule(tag, this.projectId, 1); - if (isSaved) { - createModule(module); - } - apiDefinition.setModuleId(module.getId()); - }); - } - } - private ApiDefinitionResult buildApiDefinition(String id, Operation operation, String path, String method) { String name = ""; if (StringUtils.isNotBlank(operation.getSummary())) { diff --git a/backend/src/main/java/io/metersphere/api/parse/SwaggerAbstractParser.java b/backend/src/main/java/io/metersphere/api/parse/SwaggerAbstractParser.java new file mode 100644 index 0000000000..1973109c54 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/parse/SwaggerAbstractParser.java @@ -0,0 +1,19 @@ +package io.metersphere.api.parse; + +import io.metersphere.api.dto.definition.ApiDefinitionResult; +import io.metersphere.base.domain.ApiModule; + +import java.util.List; + +public abstract class SwaggerAbstractParser extends ApiImportAbstractParser { + + protected void buildModule(ApiModule parentModule, ApiDefinitionResult apiDefinition, List tags, boolean isSaved) { + if (tags != null) { + tags.forEach(tag -> { + ApiModule module = buildModule(parentModule, tag, isSaved); + apiDefinition.setModuleId(module.getId()); + }); + } + } + +} diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index 944b908847..bdbc29b31c 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.ApiTestImportRequest; -import io.metersphere.api.dto.automation.ApiScenarioDTO; import io.metersphere.api.dto.automation.ApiScenarioRequest; import io.metersphere.api.dto.automation.ReferenceDTO; import io.metersphere.api.dto.datacount.ApiDataCountResult; @@ -18,6 +17,7 @@ import io.metersphere.api.parse.ApiImportParserFactory; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.ApiDefinitionMapper; import io.metersphere.base.mapper.ApiTestFileMapper; +import io.metersphere.base.mapper.ProjectMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionMapper; import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; @@ -71,6 +71,8 @@ public class ApiDefinitionService { private ExtApiScenarioMapper extApiScenarioMapper; @Resource private ExtTestPlanMapper extTestPlanMapper; + @Resource + private ProjectMapper projectMapper; private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24); @@ -178,7 +180,8 @@ public class ApiDefinitionService { example.createCriteria().andMethodEqualTo(request.getMethod()).andStatusNotEqualTo("Trash") .andProtocolEqualTo(request.getProtocol()).andPathEqualTo(request.getPath()) .andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId()); - if (apiDefinitionMapper.countByExample(example) > 0) { + Project project = projectMapper.selectByPrimaryKey(request.getProjectId()); + if (apiDefinitionMapper.countByExample(example) > 0 && !project.getRepeatable()) { MSException.throwException(Translator.get("api_definition_url_not_repeating")); } } else { @@ -439,8 +442,8 @@ public class ApiDefinitionService { public void editApiByParam(ApiBatchRequest request) { List ids = request.getIds(); - if(request.isSelectAllDate()){ - ids = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds()); + if (request.isSelectAllDate()) { + ids = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds()); } //name在这里只是查询参数 request.setName(null); @@ -503,15 +506,15 @@ public class ApiDefinitionService { public void deleteByParams(ApiDefinitionBatchProcessingRequest request) { List apiIds = request.getDataIds(); - if(request.isSelectAllDate()){ - apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds()); + if (request.isSelectAllDate()) { + apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds()); } ApiDefinitionExample example = new ApiDefinitionExample(); example.createCriteria().andIdIn(apiIds); apiDefinitionMapper.deleteByExample(example); } - private List getAllApiIdsByFontedSelect(List filter,String name,List moduleIds,String projectId,ListunSelectIds) { + private List getAllApiIdsByFontedSelect(List filter, String name, List moduleIds, String projectId, List unSelectIds) { ApiDefinitionRequest request = new ApiDefinitionRequest(); request.setFilters(filter); request.setName(name); @@ -529,8 +532,8 @@ public class ApiDefinitionService { public void removeToGcByParams(ApiDefinitionBatchProcessingRequest request) { List apiIds = request.getDataIds(); - if(request.isSelectAllDate()){ - apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(),request.getName(),request.getModuleIds(),request.getProjectId(),request.getUnSelectIds()); + if (request.isSelectAllDate()) { + apiIds = this.getAllApiIdsByFontedSelect(request.getFilters(), request.getName(), request.getModuleIds(), request.getProjectId(), request.getUnSelectIds()); } extApiDefinitionMapper.removeToGc(apiIds); } diff --git a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java new file mode 100644 index 0000000000..4e9358e6c2 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java @@ -0,0 +1,335 @@ +package io.metersphere.api.service; + +import com.alibaba.fastjson.JSON; +import io.metersphere.api.dto.SaveHistoricalDataUpgrade; +import io.metersphere.api.dto.automation.ScenarioStatus; +import io.metersphere.api.dto.definition.request.MsScenario; +import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.api.dto.definition.request.assertions.MsAssertions; +import io.metersphere.api.dto.definition.request.controller.MsIfController; +import io.metersphere.api.dto.definition.request.extract.MsExtract; +import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor; +import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; +import io.metersphere.api.dto.definition.request.sampler.MsDubboSampler; +import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy; +import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler; +import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler; +import io.metersphere.api.dto.definition.request.timer.MsConstantTimer; +import io.metersphere.api.dto.scenario.Body; +import io.metersphere.api.dto.scenario.Scenario; +import io.metersphere.api.dto.scenario.request.*; +import io.metersphere.base.domain.*; +import io.metersphere.base.mapper.ApiScenarioMapper; +import io.metersphere.base.mapper.ApiTestMapper; +import io.metersphere.base.mapper.ext.ExtApiScenarioMapper; +import io.metersphere.commons.utils.BeanUtils; +import io.metersphere.commons.utils.DateUtils; +import io.metersphere.commons.utils.LogUtil; +import io.metersphere.commons.utils.SessionUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.io.*; +import java.net.URL; +import java.util.*; + +@Service +@Transactional(rollbackFor = Exception.class) +public class HistoricalDataUpgradeService { + @Resource + private ApiTestMapper apiTestMapper; + @Resource + private ExtApiScenarioMapper extApiScenarioMapper; + @Resource + SqlSessionFactory sqlSessionFactory; + + private int getNextNum(String projectId) { + ApiScenario apiScenario = extApiScenarioMapper.getNextNum(projectId); + if (apiScenario == null) { + return 100001; + } else { + return Optional.of(apiScenario.getNum() + 1).orElse(100001); + } + } + + private MsScenario createScenario(Scenario oldScenario) { + MsScenario scenario = new MsScenario(); + scenario.setVariables(oldScenario.getVariables()); + scenario.setName(oldScenario.getName()); + scenario.setEnableCookieShare(oldScenario.isEnableCookieShare()); + scenario.setEnvironmentId(oldScenario.getEnvironmentId()); + scenario.setReferenced("Upgrade"); + scenario.setId(oldScenario.getId()); + scenario.setResourceId(UUID.randomUUID().toString()); + LinkedList testElements = new LinkedList<>(); + int index = 1; + for (Request request : oldScenario.getRequests()) { + // 条件控制器 + MsIfController ifController = null; + if (request.getController() != null && StringUtils.isNotEmpty(request.getController().getValue()) + && StringUtils.isNotEmpty(request.getController().getVariable())) { + ifController = new MsIfController(); + BeanUtils.copyBean(ifController, request.getController()); + ifController.setType("IfController"); + ifController.setName("IfController"); + ifController.setIndex(index + ""); + ifController.setResourceId(UUID.randomUUID().toString()); + } + // 等待控制器 + if (request.getTimer() != null && StringUtils.isNotEmpty(request.getTimer().getDelay())) { + MsConstantTimer constantTimer = new MsConstantTimer(); + BeanUtils.copyBean(constantTimer, request.getTimer()); + constantTimer.setType("ConstantTimer"); + constantTimer.setIndex(index + ""); + constantTimer.setResourceId(UUID.randomUUID().toString()); + testElements.add(constantTimer); + } + + MsTestElement element = null; + if (request instanceof HttpRequest) { + element = new MsHTTPSamplerProxy(); + HttpRequest request1 = (HttpRequest) request; + if (StringUtils.isEmpty(request1.getPath()) && StringUtils.isNotEmpty(request1.getUrl())) { + try { + URL urlObject = new URL(request1.getUrl()); + String envPath = StringUtils.equals(urlObject.getPath(), "/") ? "" : urlObject.getPath(); + request1.setPath(envPath); + } catch (Exception ex) { + LogUtil.error(ex.getMessage()); + } + } + if (request1.getBody() != null && request1.getBody().isOldKV()) { + request1.getBody().setType(Body.FORM_DATA); + } + BeanUtils.copyBean(element, request1); + ((MsHTTPSamplerProxy) element).setProtocol(RequestType.HTTP); + ((MsHTTPSamplerProxy) element).setArguments(request1.getParameters()); + element.setType("HTTPSamplerProxy"); + } + if (request instanceof DubboRequest) { + String requestJson = JSON.toJSONString(request); + element = JSON.parseObject(requestJson, MsDubboSampler.class); + element.setType("DubboSampler"); + } + if (request instanceof SqlRequest) { + element = new MsJDBCSampler(); + SqlRequest request1 = (SqlRequest) request; + BeanUtils.copyBean(element, request1); + element.setType("JDBCSampler"); + } + if (request instanceof TCPRequest) { + element = new MsTCPSampler(); + TCPRequest request1 = (TCPRequest) request; + BeanUtils.copyBean(element, request1); + element.setType("TCPSampler"); + } + element.setIndex(index + ""); + element.setResourceId(UUID.randomUUID().toString()); + LinkedList msTestElements = new LinkedList<>(); + // 断言规则 + if (request.getAssertions() != null && ((request.getAssertions().getDuration() != null && request.getAssertions().getDuration().getValue() > 0) || + CollectionUtils.isNotEmpty(request.getAssertions().getJsonPath()) || CollectionUtils.isNotEmpty(request.getAssertions().getJsr223()) || + CollectionUtils.isNotEmpty(request.getAssertions().getRegex()) || CollectionUtils.isNotEmpty(request.getAssertions().getXpath2()))) { + String assertions = JSON.toJSONString(request.getAssertions()); + MsAssertions msAssertions = JSON.parseObject(assertions, MsAssertions.class); + msAssertions.setType("Assertions"); + msAssertions.setIndex(index + ""); + msAssertions.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(msAssertions); + } + // 提取规则 + if (request.getExtract() != null && (CollectionUtils.isNotEmpty(request.getExtract().getJson()) || + CollectionUtils.isNotEmpty(request.getExtract().getRegex()) || CollectionUtils.isNotEmpty(request.getExtract().getXpath()))) { + String extractJson = JSON.toJSONString(request.getExtract()); + MsExtract extract = JSON.parseObject(extractJson, MsExtract.class); + extract.setType("Extract"); + extract.setIndex(index + ""); + extract.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(extract); + } + // 前置脚本 + if (request.getJsr223PreProcessor() != null && StringUtils.isNotEmpty(request.getJsr223PreProcessor().getScript())) { + String preJson = JSON.toJSONString(request.getJsr223PreProcessor()); + MsJSR223PreProcessor preProcessor = JSON.parseObject(preJson, MsJSR223PreProcessor.class); + preProcessor.setType("JSR223PreProcessor"); + preProcessor.setIndex(index + ""); + preProcessor.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(preProcessor); + } + // 后置脚本 + if (request.getJsr223PostProcessor() != null && StringUtils.isNotEmpty(request.getJsr223PostProcessor().getScript())) { + String preJson = JSON.toJSONString(request.getJsr223PostProcessor()); + MsJSR223PostProcessor preProcessor = JSON.parseObject(preJson, MsJSR223PostProcessor.class); + preProcessor.setType("JSR223PostProcessor"); + preProcessor.setIndex(index + ""); + preProcessor.setResourceId(UUID.randomUUID().toString()); + msTestElements.add(preProcessor); + } + if (CollectionUtils.isNotEmpty(msTestElements)) { + element.setHashTree(msTestElements); + } + if (ifController != null) { + LinkedList elements = new LinkedList<>(); + elements.add(element); + ifController.setHashTree(elements); + testElements.add(ifController); + } else { + testElements.add(element); + } + index++; + } + scenario.setHashTree(testElements); + return scenario; + } + + private ApiScenarioWithBLOBs checkNameExist(Scenario oldScenario, String projectId, ApiScenarioMapper mapper) { + ApiScenarioExample example = new ApiScenarioExample(); + example.createCriteria().andIdEqualTo(oldScenario.getId()); + List list = mapper.selectByExampleWithBLOBs(example); + if (list.size() > 0) { + return list.get(0); + } + return null; + } + + private static final String BODY_FILE_DIR = "/opt/metersphere/data/body"; + + //文件的拷贝 + private static void copyFile(String sourcePath, String newPath) { + File readfile = new File(sourcePath); + File newFile = new File(newPath); + BufferedWriter bufferedWriter = null; + Writer writer = null; + FileOutputStream fileOutputStream = null; + BufferedReader bufferedReader = null; + try { + fileOutputStream = new FileOutputStream(newFile, true); + writer = new OutputStreamWriter(fileOutputStream, "UTF-8"); + bufferedWriter = new BufferedWriter(writer); + + bufferedReader = new BufferedReader(new FileReader(readfile)); + + String line = null; + while ((line = bufferedReader.readLine()) != null) { + bufferedWriter.write(line); + bufferedWriter.newLine(); + bufferedWriter.flush(); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bufferedWriter != null) { + bufferedWriter.close(); + } + if (bufferedReader != null) { + bufferedReader.close(); + } + if (writer != null) { + writer.close(); + } + if (fileOutputStream != null) { + fileOutputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static void copyDir(String sourcePathDir, String newPathDir) { + File start = new File(sourcePathDir); + File end = new File(newPathDir); + String[] filePath = start.list(); + if (!end.exists()) { + end.mkdir(); + } + for (String temp : filePath) { + //添加满足情况的条件 + if (new File(sourcePathDir + File.separator + temp).isFile()) { + //为文件则进行拷贝 + copyFile(sourcePathDir + File.separator + temp, newPathDir + File.separator + temp); + } + } + } + + private void createBodyFiles(String testId) { + String dir = BODY_FILE_DIR + "/" + testId; + File testDir = new File(dir); + if (testDir.exists()) { + testDir.mkdirs(); + } + copyDir(dir, BODY_FILE_DIR); + } + + private void createApiScenarioWithBLOBs(SaveHistoricalDataUpgrade saveHistoricalDataUpgrade, Scenario oldScenario, String scenarioDefinition, ApiScenarioMapper mapper) { + if (StringUtils.isEmpty(oldScenario.getName())) { + oldScenario.setName("默认名称-" + DateUtils.getTimeStr(System.currentTimeMillis())); + } + ApiScenarioWithBLOBs scenario = checkNameExist(oldScenario, saveHistoricalDataUpgrade.getProjectId(), mapper); + if (scenario != null) { + scenario.setName(oldScenario.getName()); + scenario.setProjectId(saveHistoricalDataUpgrade.getProjectId()); + scenario.setTags(scenario.getTags()); + scenario.setLevel("P0"); + scenario.setModulePath(saveHistoricalDataUpgrade.getModulePath()); + scenario.setApiScenarioModuleId(saveHistoricalDataUpgrade.getModuleId()); + scenario.setPrincipal(Objects.requireNonNull(SessionUtils.getUser()).getId()); + scenario.setStepTotal(oldScenario.getRequests().size()); + scenario.setScenarioDefinition(scenarioDefinition); + scenario.setUpdateTime(System.currentTimeMillis()); + scenario.setStatus(ScenarioStatus.Underway.name()); + scenario.setUserId(SessionUtils.getUserId()); + scenario.setNum(getNextNum(saveHistoricalDataUpgrade.getProjectId())); + mapper.updateByPrimaryKeySelective(scenario); + } else { + scenario = new ApiScenarioWithBLOBs(); + scenario.setId(oldScenario.getId()); + scenario.setName(oldScenario.getName()); + scenario.setProjectId(saveHistoricalDataUpgrade.getProjectId()); + scenario.setTags(scenario.getTags()); + scenario.setLevel("P0"); + scenario.setModulePath(saveHistoricalDataUpgrade.getModulePath()); + scenario.setApiScenarioModuleId(saveHistoricalDataUpgrade.getModuleId()); + scenario.setPrincipal(Objects.requireNonNull(SessionUtils.getUser()).getId()); + scenario.setStepTotal(oldScenario.getRequests().size()); + scenario.setScenarioDefinition(scenarioDefinition); + scenario.setCreateTime(System.currentTimeMillis()); + scenario.setUpdateTime(System.currentTimeMillis()); + scenario.setStatus(ScenarioStatus.Underway.name()); + scenario.setUserId(SessionUtils.getUserId()); + scenario.setNum(getNextNum(saveHistoricalDataUpgrade.getProjectId())); + mapper.insert(scenario); + } + } + + public String upgrade(SaveHistoricalDataUpgrade saveHistoricalDataUpgrade) { + ApiTestExample example = new ApiTestExample(); + example.createCriteria().andIdIn(saveHistoricalDataUpgrade.getTestIds()); + List blobs = apiTestMapper.selectByExampleWithBLOBs(example); + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + ApiScenarioMapper mapper = sqlSession.getMapper(ApiScenarioMapper.class); + for (ApiTest test : blobs) { + // 附件迁移 + createBodyFiles(test.getId()); + + List scenarios = JSON.parseArray(test.getScenarioDefinition(), Scenario.class); + if (CollectionUtils.isNotEmpty(scenarios)) { + // 批量处理 + for (Scenario scenario : scenarios) { + MsScenario scenario1 = createScenario(scenario); + String scenarioDefinition = JSON.toJSONString(scenario1); + createApiScenarioWithBLOBs(saveHistoricalDataUpgrade, scenario, scenarioDefinition, mapper); + } + } + } + sqlSession.flushStatements(); + return null; + } +} diff --git a/backend/src/main/java/io/metersphere/base/domain/Project.java b/backend/src/main/java/io/metersphere/base/domain/Project.java index 25403e763e..a1ca062eee 100644 --- a/backend/src/main/java/io/metersphere/base/domain/Project.java +++ b/backend/src/main/java/io/metersphere/base/domain/Project.java @@ -1,8 +1,9 @@ package io.metersphere.base.domain; -import java.io.Serializable; import lombok.Data; +import java.io.Serializable; + @Data public class Project implements Serializable { private String id; @@ -23,5 +24,7 @@ public class Project implements Serializable { private String zentaoId; + private Boolean repeatable; + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java b/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java index 8f83d6ad88..dd20602779 100644 --- a/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/ProjectExample.java @@ -713,6 +713,66 @@ public class ProjectExample { addCriterion("zentao_id not between", value1, value2, "zentaoId"); return (Criteria) this; } + + public Criteria andRepeatableIsNull() { + addCriterion("`repeatable` is null"); + return (Criteria) this; + } + + public Criteria andRepeatableIsNotNull() { + addCriterion("`repeatable` is not null"); + return (Criteria) this; + } + + public Criteria andRepeatableEqualTo(Boolean value) { + addCriterion("`repeatable` =", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableNotEqualTo(Boolean value) { + addCriterion("`repeatable` <>", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableGreaterThan(Boolean value) { + addCriterion("`repeatable` >", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableGreaterThanOrEqualTo(Boolean value) { + addCriterion("`repeatable` >=", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableLessThan(Boolean value) { + addCriterion("`repeatable` <", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableLessThanOrEqualTo(Boolean value) { + addCriterion("`repeatable` <=", value, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableIn(List values) { + addCriterion("`repeatable` in", values, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableNotIn(List values) { + addCriterion("`repeatable` not in", values, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableBetween(Boolean value1, Boolean value2) { + addCriterion("`repeatable` between", value1, value2, "repeatable"); + return (Criteria) this; + } + + public Criteria andRepeatableNotBetween(Boolean value1, Boolean value2) { + addCriterion("`repeatable` not between", value1, value2, "repeatable"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml index 4ed30cebfe..7765a51e20 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ProjectMapper.xml @@ -11,6 +11,7 @@ + @@ -72,7 +73,7 @@ id, workspace_id, `name`, description, create_time, update_time, tapd_id, jira_key, - zentao_id + zentao_id, `repeatable` @@ -211,6 +218,9 @@ zentao_id = #{record.zentaoId,jdbcType=VARCHAR}, + + `repeatable` = #{record.repeatable,jdbcType=BIT}, + @@ -226,7 +236,8 @@ update_time = #{record.updateTime,jdbcType=BIGINT}, tapd_id = #{record.tapdId,jdbcType=VARCHAR}, jira_key = #{record.jiraKey,jdbcType=VARCHAR}, - zentao_id = #{record.zentaoId,jdbcType=VARCHAR} + zentao_id = #{record.zentaoId,jdbcType=VARCHAR}, + `repeatable` = #{record.repeatable,jdbcType=BIT} @@ -258,6 +269,9 @@ zentao_id = #{zentaoId,jdbcType=VARCHAR}, + + `repeatable` = #{repeatable,jdbcType=BIT}, + where id = #{id,jdbcType=VARCHAR} @@ -270,7 +284,8 @@ update_time = #{updateTime,jdbcType=BIGINT}, tapd_id = #{tapdId,jdbcType=VARCHAR}, jira_key = #{jiraKey,jdbcType=VARCHAR}, - zentao_id = #{zentaoId,jdbcType=VARCHAR} + zentao_id = #{zentaoId,jdbcType=VARCHAR}, + `repeatable` = #{repeatable,jdbcType=BIT} where id = #{id,jdbcType=VARCHAR} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml index 66bb7c3588..af9787bece 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtProjectMapper.xml @@ -4,7 +4,7 @@