feat(接口测试): 增加导入功能
This commit is contained in:
parent
bf68a4e688
commit
3f6ba6680c
|
@ -206,7 +206,6 @@ public class PermissionConstants {
|
|||
/*------ end: PROJECT_TEMPLATE ------*/
|
||||
|
||||
|
||||
|
||||
/*------ start: FUNCTIONAL_CASE ------*/
|
||||
public static final String FUNCTIONAL_CASE_READ = "FUNCTIONAL_CASE:READ";
|
||||
public static final String FUNCTIONAL_CASE_READ_ADD = "FUNCTIONAL_CASE:READ+ADD";
|
||||
|
@ -278,12 +277,10 @@ public class PermissionConstants {
|
|||
public static final String PROJECT_API_SCENARIO_DEBUG = "PROJECT_API_SCENARIO:READ+DEBUG";
|
||||
|
||||
|
||||
|
||||
|
||||
/*------ end: API_MANAGEMENT ------*/
|
||||
//个人中心
|
||||
/*------ start: PERSONAL_CENTER ------*/
|
||||
public static final String SYSTEM_PERSONAL_API_KEY_ADD = "SYSTEM_PERSONAL_API_KEYD:READ+ADD";
|
||||
public static final String SYSTEM_PERSONAL_API_KEY_ADD = "SYSTEM_PERSONAL_API_KEY:READ+ADD";
|
||||
public static final String SYSTEM_PERSONAL_API_KEY_DELETE = "SYSTEM_PERSONAL_API_KEY:READ+DELETE";
|
||||
public static final String SYSTEM_PERSONAL_API_KEY_READ = "SYSTEM_PERSONAL_API_KEY:READ";
|
||||
public static final String SYSTEM_PERSONAL_API_KEY_UPDATE = "SYSTEM_PERSONAL_API_KEY:READ+UPDATE";
|
||||
|
|
|
@ -304,3 +304,4 @@ api_definition_exist=接口已存在
|
|||
api_definition_mock_exist=接口 MOCK 已存在
|
||||
execute_resource_pool_not_config_error=请在【项目管理-应用管理-接口测试】中选择资源池
|
||||
resource_pool_execute_error=资源池调用失败
|
||||
api_swagger_url_error=Swagger url无法连通
|
||||
|
|
|
@ -308,3 +308,4 @@ api_definition_exist=The API already exists
|
|||
api_definition_mock_exist=The API MOCK already exists
|
||||
execute_resource_pool_not_config_error=Select a resource pool in 【Project Management - Application Management - Interface Testing】
|
||||
resource_pool_execute_error=The resource pool call failed
|
||||
api_swagger_url_error=Swagger url unable to connect
|
|
@ -308,3 +308,4 @@ api_definition_exist=接口已存在
|
|||
api_definition_mock_exist=接口 MOCK 已存在
|
||||
execute_resource_pool_not_config_error=请在【项目管理-应用管理-接口测试】中选择资源池
|
||||
resource_pool_execute_error=资源池调用失败
|
||||
api_swagger_url_error=Swagger url无法连通
|
||||
|
|
|
@ -308,3 +308,4 @@ api_definition_exist=接口已存在
|
|||
api_definition_mock_exist=接口 MOCK 已存在
|
||||
execute_resource_pool_not_config_error=請在【項目管理-應用管理-接口測試】中選擇資源池
|
||||
resource_pool_execute_error=資源池調用失敗
|
||||
api_swagger_url_error=Swagger url無法調解
|
||||
|
|
|
@ -492,3 +492,5 @@ apikey_has_expired=ApiKey 已过期
|
|||
user_key.id.not_blank=ApiKey ID不能为空
|
||||
expire_time_not_null=过期时间不能为空
|
||||
permission.organization.name=组织
|
||||
swagger_parse_error_with_auth=Swagger 解析失败,请确认认证信息是否正确或文件格式是否正确!
|
||||
swagger_parse_error=Swagger 解析失败,请确认文件格式是否正确!
|
|
@ -502,3 +502,5 @@ apikey_has_expired=ApiKey has expired
|
|||
user_key.id.not_blank=User key id can not blank
|
||||
expire_time_not_null=Expire time can not null
|
||||
permission.organization.name=Organization
|
||||
swagger_parse_error_with_auth=Swagger parsing failed, please confirm whether the verification information is correct or the file format is correct!
|
||||
swagger_parse_error=Swagger parsing failed or file format is incorrect!
|
|
@ -498,3 +498,5 @@ apikey_has_expired=ApiKey 已过期
|
|||
user_key.id.not_blank=ApiKey ID不能为空
|
||||
expire_time_not_null=过期时间不能为空
|
||||
permission.organization.name=组织
|
||||
swagger_parse_error_with_auth=Swagger 解析失败,请确认认证信息是否正确或文件格式是否正确!
|
||||
swagger_parse_error=Swagger 解析失败,请确认文件格式是否正确!
|
|
@ -498,3 +498,5 @@ apikey_has_expired=ApiKey 已過期
|
|||
user_key.id.not_blank=ApiKey ID不能为空
|
||||
expire_time_not_null=過期時間不能為空
|
||||
permission.organization.name=組織
|
||||
swagger_parse_error_with_auth=Swagger 解析失敗,請檢查 Swagger 接口是否需要認證
|
||||
swagger_parse_error=Swagger 解析失敗
|
|
@ -4,6 +4,8 @@ import com.github.pagehelper.Page;
|
|||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.request.ImportRequest;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionLogService;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
|
@ -73,6 +75,7 @@ public class ApiDefinitionController {
|
|||
public void delete(@Validated @RequestBody ApiDefinitionDeleteRequest request) {
|
||||
apiDefinitionService.delete(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/batch-del")
|
||||
@Operation(summary = "接口测试-接口管理-批量删除接口定义到回收站")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
|
||||
|
@ -141,6 +144,7 @@ public class ApiDefinitionController {
|
|||
public void recover(@Validated @RequestBody ApiDefinitionDeleteRequest request) {
|
||||
apiDefinitionService.recover(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/trash-del")
|
||||
@Operation(summary = "接口测试-接口管理-删除回收站接口定义")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
|
||||
|
@ -149,6 +153,7 @@ public class ApiDefinitionController {
|
|||
public void trashDel(@Validated @RequestBody ApiDefinitionDeleteRequest request) {
|
||||
apiDefinitionService.trashDel(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/batch-recover")
|
||||
@Operation(summary = "接口测试-接口管理-批量从回收站恢复接口定义")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_RECOVER)
|
||||
|
@ -190,4 +195,11 @@ public class ApiDefinitionController {
|
|||
return apiDefinitionService.getDocInfo(request);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/import", consumes = {"multipart/form-data"})
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT)
|
||||
@Operation(summary = "接口测试-接口管理-导入接口定义")
|
||||
public ApiDefinitionImport testCaseImport(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart("request") ImportRequest request) {
|
||||
return apiDefinitionService.apiTestImport(file, request);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package io.metersphere.api.dto.definition.importdto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ApiDeatlWithData {
|
||||
@Schema(description = "相同的数据的key")
|
||||
List<String> sameList = new ArrayList<>();
|
||||
@Schema(description = "不同的数据的key")
|
||||
List<String> differenceList = new ArrayList<>();
|
||||
@Schema(description = "数据库中存在的数据")
|
||||
Map<String, ApiDefinitionImportDTO> apiDateMap = new HashMap<>();
|
||||
@Schema(description = "导入的数据")
|
||||
Map<String, ApiDefinitionImportDTO> importDataMap = new HashMap<>();
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package io.metersphere.api.dto.definition.importdto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ApiDeatlWithDataUpdate {
|
||||
@Schema(description = "需要更新模块的数据")
|
||||
List<ApiDefinitionImportDTO> updateModuleData = new ArrayList<>();
|
||||
@Schema(description = "需要更新接口的数据")
|
||||
List<ApiDefinitionImportDTO> updateRequestData = new ArrayList<>();
|
||||
@Schema(description = "需要新增的接口数据")
|
||||
List<ApiDefinitionImportDTO> addModuleData = new ArrayList<>();
|
||||
@Schema(description = "需要新增的日志数据")
|
||||
Map<String, ApiDefinitionImportDTO> logData;
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.api.dto.definition.importdto;
|
||||
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ApiDefinitionImport {
|
||||
private String projectName;
|
||||
private String protocol;
|
||||
private List<ApiDefinitionImportDTO> data;
|
||||
|
||||
// 新版本带用例导出
|
||||
private List<ApiTestCaseDTO> cases = new ArrayList<>();
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.api.dto.importdto;
|
||||
package io.metersphere.api.dto.definition.importdto;
|
||||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.dto.definition.HttpResponse;
|
|
@ -1,31 +1,45 @@
|
|||
package io.metersphere.api.dto.request;
|
||||
|
||||
import io.metersphere.api.dto.request.http.Header;
|
||||
import io.metersphere.api.dto.request.http.QueryParam;
|
||||
import io.metersphere.api.dto.request.http.auth.HTTPAuth;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ImportRequest {
|
||||
private String id;
|
||||
private String name;
|
||||
private String moduleId;
|
||||
private String environmentId;
|
||||
private String projectId;
|
||||
private String platform;
|
||||
@Schema(description = "导入的swagger地址")
|
||||
private String swaggerUrl;
|
||||
|
||||
//导入策略
|
||||
private String modeId;
|
||||
@Schema(description = "如果是定时任务的时候 需要传入创建人id")
|
||||
private String userId;
|
||||
private String versionId; // 新导入选择的版本
|
||||
private String updateVersionId; // 覆盖导入已存在的接口选择的版本
|
||||
private String defaultVersion;
|
||||
private String platform;
|
||||
//调用类型
|
||||
private String type;
|
||||
// 是否开启自定义ID
|
||||
private Boolean openCustomNum = false;
|
||||
// 是否覆盖模块
|
||||
@Schema(description = "是否覆盖模块")
|
||||
private Boolean coverModule;
|
||||
@Schema(description = "是否同步导入用例")
|
||||
private Boolean syncCase;
|
||||
@Schema(description = "是否覆盖数据")
|
||||
private Boolean coverData;
|
||||
// 当前协议
|
||||
private String protocol;
|
||||
//上传文件来源,目前用于辨别是否是idea插件
|
||||
private String origin;
|
||||
@Schema(description = "swagger的请求头参数")
|
||||
private List<Header> headers;
|
||||
@Schema(description = "swagger的请求参数")
|
||||
private List<QueryParam> arguments;
|
||||
@Schema(description = "swagger的认证参数")
|
||||
private HTTPAuth authManager;
|
||||
@Schema(description = "唯一标识 默认是Method & Path 后续估计会补充")
|
||||
private String uniquelyIdentifies = "Method & Path";
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.api.dto.request.http.body;
|
||||
|
||||
import io.metersphere.api.dto.schema.JsonSchemaItem;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
|
@ -20,5 +21,9 @@ public class JsonBody {
|
|||
* 启用 json-schema 时的参数对象
|
||||
* todo json-schema 编辑器待调研,暂时使用 Object 类型
|
||||
*/
|
||||
private Object jsonSchema;
|
||||
private JsonSchemaItem jsonSchema;
|
||||
/**
|
||||
* 是否开启转换
|
||||
*/
|
||||
private Boolean enable = false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package io.metersphere.api.dto.schema;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class JsonSchemaItem {
|
||||
private Object example;
|
||||
private String id;
|
||||
private String title;
|
||||
private String type = "string";
|
||||
private String description;
|
||||
private JsonSchemaItem items;
|
||||
private Map<String, Object> mock;
|
||||
private Map<String, JsonSchemaItem> properties;
|
||||
private JsonSchemaItem additionalProperties;
|
||||
private List<String> required;
|
||||
private String pattern;
|
||||
private Integer maxLength;
|
||||
private Integer minLength;
|
||||
private BigDecimal minimum;
|
||||
private BigDecimal maximum;
|
||||
private String schema;
|
||||
private String format;
|
||||
private List<String> enumString;
|
||||
private List<Number> enumInteger;
|
||||
private List<BigDecimal> enumNumber;
|
||||
private Map<String, Object> extensions = null;
|
||||
|
||||
|
||||
public JsonSchemaItem() {
|
||||
this.mock = new LinkedHashMap<>();
|
||||
this.mock.put("mock", "");
|
||||
}
|
||||
|
||||
public JsonSchemaItem(String type) {
|
||||
this.type = type;
|
||||
this.initParam(type);
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
this.initParam(type);
|
||||
}
|
||||
|
||||
private void initParam(String type) {
|
||||
if (type.equals("object")) {
|
||||
this.properties = new LinkedHashMap<>();
|
||||
} else if (type.equals("array")) {
|
||||
this.items = new JsonSchemaItem();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package io.metersphere.api.enums;
|
||||
|
||||
public class PropertyConstant {
|
||||
public final static String REQUIRED = "required";
|
||||
public final static String ALL_OF = "allOf";
|
||||
public final static String PROPERTIES = "properties";
|
||||
public final static String ADDITIONAL_PROPERTIES = "additionalProperties";
|
||||
public final static String TYPE = "type";
|
||||
public final static String MS_OBJECT = "MS-OBJECT";
|
||||
public final static String ARRAY = "array";
|
||||
public final static String OBJECT = "object";
|
||||
public final static String DEFAULT = "default";
|
||||
public final static String STRING = "string";
|
||||
public final static String BOOLEAN = "boolean";
|
||||
public final static String NUMBER = "number";
|
||||
public final static String INTEGER = "integer";
|
||||
public final static String MOCK = "mock";
|
||||
public final static String NULL = "null";
|
||||
public final static String ENUM = "enum";
|
||||
public final static String ITEMS = "items";
|
||||
public final static String ITEM = "_item";
|
||||
public final static String NONE = "none";
|
||||
public final static String ROOT = "root";
|
||||
public final static String XML_PATH = "XML_PATH";
|
||||
public final static String ASS_OPTION = "ASS_OPTION";
|
||||
public final static String EXPECTED_VALUE = "EXPECTED_VALUE";
|
||||
public final static String ELEMENT_CONDITION = "ElementCondition";
|
||||
public final static String ENVIRONMENT = "useEnvironment";
|
||||
public final static String ENVIRONMENT_ID = "environmentId";
|
||||
public final static String DATASOURCE_ID = "dataSourceId";
|
||||
public final static String PROJECT_ID = "projectId";
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@ package io.metersphere.api.mapper;
|
|||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.importdto.ApiDefinitionImportDTO;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImportDTO;
|
||||
import io.metersphere.system.dto.table.TableBatchProcessDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
|
|
@ -129,14 +129,14 @@
|
|||
</foreach>
|
||||
and deleted = #{deleted}
|
||||
</select>
|
||||
<select id="importList" resultType="io.metersphere.api.dto.importdto.ApiDefinitionImportDTO">
|
||||
<select id="importList" resultType="io.metersphere.api.dto.definition.importdto.ApiDefinitionImportDTO">
|
||||
select
|
||||
api_definition.id, api_definition.`name`, api_definition.protocol, api_definition.`method`,
|
||||
api_definition.`path`, api_definition.version_id,
|
||||
api_definition.ref_id
|
||||
api_definition.ref_id, api_definition.module_id
|
||||
from api_definition
|
||||
LEFT JOIN project_version ON project_version.id = api_definition.version_id
|
||||
where api_definition.deleted = true
|
||||
where api_definition.deleted = false
|
||||
<include refid="queryWhereCondition"/>
|
||||
</select>
|
||||
<select id="selectIdsByIdsAndDeleted" resultType="java.lang.String">
|
||||
|
|
|
@ -1,23 +1,686 @@
|
|||
package io.metersphere.api.parser.api;
|
||||
|
||||
import io.metersphere.api.dto.definition.HttpResponse;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImportDTO;
|
||||
import io.metersphere.api.dto.request.ImportRequest;
|
||||
import io.metersphere.api.dto.request.http.*;
|
||||
import io.metersphere.api.dto.request.http.auth.NoAuth;
|
||||
import io.metersphere.api.dto.request.http.body.*;
|
||||
import io.metersphere.api.dto.schema.JsonSchemaItem;
|
||||
import io.metersphere.api.enums.PropertyConstant;
|
||||
import io.metersphere.api.parser.ImportParser;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.LogUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.swagger.parser.OpenAPIParser;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import io.swagger.v3.oas.models.media.*;
|
||||
import io.swagger.v3.oas.models.parameters.*;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponses;
|
||||
import io.swagger.v3.parser.core.models.AuthorizationValue;
|
||||
import io.swagger.v3.parser.core.models.SwaggerParseResult;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class Swagger3Parser<T> implements ImportParser<T> {
|
||||
public class Swagger3Parser<T> implements ImportParser<ApiDefinitionImport> {
|
||||
|
||||
protected String projectId;
|
||||
private Components components;
|
||||
|
||||
public static final String PATH = "path";
|
||||
public static final String FORM_DATA = "formData";
|
||||
public static final String FILE = "file";
|
||||
public static final String HEADER = "header";
|
||||
public static final String BODY = "body";
|
||||
public static final String COOKIE = "cookie";
|
||||
public static final String QUERY = "query";
|
||||
|
||||
@Override
|
||||
public T parse(InputStream source, ImportRequest request) throws Exception {
|
||||
public ApiDefinitionImport parse(InputStream source, ImportRequest request) throws Exception {
|
||||
LogUtils.info("Swagger3Parser parse");
|
||||
String apiTestStr = getApiTestStr(source);
|
||||
List<AuthorizationValue> auths = setAuths(request);
|
||||
SwaggerParseResult result = null;
|
||||
if (StringUtils.isNotBlank(request.getSwaggerUrl())) {
|
||||
result = new OpenAPIParser().readLocation(request.getSwaggerUrl(), auths, null);
|
||||
if (result == null || result.getOpenAPI() == null || !result.getOpenAPI().getOpenapi().startsWith("3.0") || result.isOpenapi31()) {
|
||||
throw new MSException(Translator.get("swagger_parse_error_with_auth"));
|
||||
}
|
||||
} else {
|
||||
result = new OpenAPIParser().readContents(apiTestStr, null, null);
|
||||
if (result == null || result.getOpenAPI() == null || !result.getOpenAPI().getOpenapi().startsWith("3.0") || result.isOpenapi31()) {
|
||||
throw new MSException(Translator.get("swagger_parse_error"));
|
||||
}
|
||||
}
|
||||
ApiDefinitionImport apiDefinitionImport = new ApiDefinitionImport();
|
||||
OpenAPI openAPI = result.getOpenAPI();
|
||||
apiDefinitionImport.setData(parseRequests(openAPI, request));
|
||||
return apiDefinitionImport;
|
||||
}
|
||||
|
||||
// todo: 检查swagger文件版本
|
||||
private List<AuthorizationValue> setAuths(ImportRequest request) {
|
||||
List<AuthorizationValue> auths = new ArrayList<>();
|
||||
// TODO 如果有 BaseAuth 参数,base64 编码后转换成 headers
|
||||
|
||||
// todo:检查文件的合规性
|
||||
// 设置 headers
|
||||
if (!CollectionUtils.isEmpty(request.getHeaders())) {
|
||||
for (Header keyValue : request.getHeaders()) {
|
||||
// 当有 key 时才进行设置
|
||||
if (keyValue.getValue() != null) {
|
||||
AuthorizationValue authorizationValue = new AuthorizationValue();
|
||||
authorizationValue.setType("header");
|
||||
authorizationValue.setKeyName(keyValue.getKey());
|
||||
authorizationValue.setValue(String.valueOf(keyValue.getValue()));
|
||||
authorizationValue.setUrlMatcher((url) -> true);
|
||||
auths.add(authorizationValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置 query 参数
|
||||
if (!CollectionUtils.isEmpty(request.getArguments())) {
|
||||
StringBuilder pathBuilder = new StringBuilder();
|
||||
pathBuilder.append(request.getSwaggerUrl());
|
||||
if (StringUtils.isNotBlank(request.getSwaggerUrl()) && !request.getSwaggerUrl().contains("?")) {
|
||||
pathBuilder.append("?");
|
||||
}
|
||||
for (QueryParam keyValue : request.getArguments()) {
|
||||
if (StringUtils.isNotBlank(keyValue.getKey())) {
|
||||
AuthorizationValue authorizationValue = new AuthorizationValue();
|
||||
authorizationValue.setType("query");
|
||||
authorizationValue.setKeyName(keyValue.getKey());
|
||||
try {
|
||||
authorizationValue.setValue(URLEncoder.encode(String.valueOf(keyValue.getValue()), StandardCharsets.UTF_8));
|
||||
} catch (Exception e) {
|
||||
LogUtils.info("swagger3 url encode error: " + e);
|
||||
}
|
||||
pathBuilder.append(keyValue.getKey()).append("=").append(authorizationValue.getValue()).append("&");
|
||||
}
|
||||
}
|
||||
request.setSwaggerUrl(pathBuilder.substring(0, pathBuilder.length() - 1));
|
||||
}
|
||||
return CollectionUtils.size(auths) == 0 ? null : auths;
|
||||
}
|
||||
|
||||
// todo:解析文件pojo
|
||||
protected String getApiTestStr(InputStream source) {
|
||||
StringBuilder testStr = null;
|
||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8))) {
|
||||
testStr = new StringBuilder();
|
||||
String inputStr;
|
||||
while ((inputStr = bufferedReader.readLine()) != null) {
|
||||
testStr.append(inputStr);
|
||||
}
|
||||
source.close();
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(e.getMessage(), e);
|
||||
throw new MSException(e.getMessage());
|
||||
}
|
||||
return StringUtils.isNotBlank(testStr) ? testStr.toString() : StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
private List<ApiDefinitionImportDTO> parseRequests(OpenAPI openAPI, ImportRequest importRequest) {
|
||||
|
||||
Paths paths = openAPI.getPaths();
|
||||
|
||||
Set<String> pathNames = paths.keySet();
|
||||
|
||||
this.components = openAPI.getComponents();
|
||||
|
||||
List<ApiDefinitionImportDTO> results = new ArrayList<>();
|
||||
|
||||
for (String pathName : pathNames) {
|
||||
PathItem pathItem = paths.get(pathName);
|
||||
|
||||
Map<String, Operation> operationsMap = new HashMap<>();
|
||||
operationsMap.put(HttpMethod.GET.name(), pathItem.getGet());
|
||||
operationsMap.put(HttpMethod.POST.name(), pathItem.getPost());
|
||||
operationsMap.put(HttpMethod.DELETE.name(), pathItem.getDelete());
|
||||
operationsMap.put(HttpMethod.PUT.name(), pathItem.getPut());
|
||||
operationsMap.put(HttpMethod.PATCH.name(), pathItem.getPatch());
|
||||
operationsMap.put(HttpMethod.HEAD.name(), pathItem.getHead());
|
||||
operationsMap.put(HttpMethod.OPTIONS.name(), pathItem.getOptions());
|
||||
operationsMap.put(HttpMethod.TRACE.name(), pathItem.getTrace());
|
||||
|
||||
for (String method : operationsMap.keySet()) {
|
||||
Operation operation = operationsMap.get(method);
|
||||
if (operation != null) {
|
||||
//构建基本请求
|
||||
ApiDefinitionImportDTO apiDefinitionDTO = buildApiDefinition(operation, pathName, method, importRequest);
|
||||
//构建请求参数
|
||||
MsHTTPElement request = buildRequest(apiDefinitionDTO.getName(), pathName, method);
|
||||
parseParameters(operation, request);
|
||||
parseParameters(pathItem, request);
|
||||
//构建请求体
|
||||
parseRequestBody(operation.getRequestBody(), request.getBody());
|
||||
apiDefinitionDTO.setRequest(request);
|
||||
|
||||
//解析请求内容
|
||||
parseResponse(operation.getResponses(), apiDefinitionDTO.getResponse());
|
||||
results.add(apiDefinitionDTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private void parseRequestBody(RequestBody requestBody, Body body) {
|
||||
if (requestBody != null) {
|
||||
Content content = requestBody.getContent();
|
||||
if (content != null) {
|
||||
content.forEach((key, value) -> {
|
||||
setBodyData(key, value, body);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
body.setBodyType(Body.BodyType.NONE.name());
|
||||
body.setNoneBody(new NoneBody());
|
||||
}
|
||||
}
|
||||
|
||||
private void parseWWWFormBody(JsonSchemaItem item, Body body) {
|
||||
WWWFormBody wwwFormBody = new WWWFormBody();
|
||||
List<String> required = item.getRequired();
|
||||
List<FormDataKV> formDataKVS = new ArrayList<>();
|
||||
item.getProperties().forEach((key, value) -> {
|
||||
if (value != null && !StringUtils.equals(PropertyConstant.OBJECT, value.getType())) {
|
||||
FormDataKV formDataKV = new FormDataKV();
|
||||
formDataKV.setKey(key);
|
||||
formDataKV.setValue(String.valueOf(value.getExample()));
|
||||
formDataKV.setRequired(CollectionUtils.isNotEmpty(required) && required.contains(key));
|
||||
formDataKV.setDescription(value.getDescription());
|
||||
formDataKV.setParamType(value.getType());
|
||||
formDataKV.setMinLength(value.getMinLength());
|
||||
formDataKV.setMaxLength(value.getMaxLength());
|
||||
formDataKVS.add(formDataKV);
|
||||
}
|
||||
});
|
||||
wwwFormBody.setFromValues(formDataKVS);
|
||||
body.setWwwFormBody(wwwFormBody);
|
||||
}
|
||||
|
||||
|
||||
private void parseResponse(ApiResponses responseBody, List<HttpResponse> response) {
|
||||
if (responseBody != null) {
|
||||
responseBody.forEach((key, value) -> {
|
||||
HttpResponse httpResponse = new HttpResponse();
|
||||
//TODO headers
|
||||
httpResponse.setStatusCode(key);
|
||||
Body body = new Body();
|
||||
Map<String, io.swagger.v3.oas.models.headers.Header> headers = value.getHeaders();
|
||||
if (MapUtils.isNotEmpty(headers)) {
|
||||
List<Header> headerList = new ArrayList<>();
|
||||
headers.forEach((k, v) -> {
|
||||
Header header = new Header();
|
||||
header.setKey(k);
|
||||
header.setValue(String.valueOf(v.getExample()));
|
||||
header.setDescription(getDefaultStringValue(v.getDescription()));
|
||||
headerList.add(header);
|
||||
});
|
||||
httpResponse.setHeaders(headerList);
|
||||
}
|
||||
if (value.getContent() != null) {
|
||||
value.getContent().forEach((k, v) -> {
|
||||
setBodyData(k, v, body);
|
||||
});
|
||||
} else {
|
||||
body.setBodyType(Body.BodyType.NONE.name());
|
||||
}
|
||||
httpResponse.setBody(body);
|
||||
response.add(httpResponse);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setBodyData(String k, io.swagger.v3.oas.models.media.MediaType value, Body body) {
|
||||
//TODO body 默认如果json格式
|
||||
JsonSchemaItem jsonSchemaItem = parseSchema(value.getSchema());
|
||||
switch (k) {
|
||||
case MediaType.APPLICATION_JSON_VALUE, MediaType.ALL_VALUE -> {
|
||||
body.setBodyType(Body.BodyType.JSON.name());
|
||||
JsonBody jsonBody = new JsonBody();
|
||||
jsonBody.setJsonSchema(jsonSchemaItem);
|
||||
jsonBody.setEnableJsonSchema(true);
|
||||
if (ObjectUtils.isNotEmpty(value.getExample())) {
|
||||
jsonBody.setJsonValue(ApiDataUtils.toJSONString(value.getExample()));
|
||||
}
|
||||
body.setJsonBody(jsonBody);
|
||||
}
|
||||
case MediaType.APPLICATION_XML_VALUE -> {
|
||||
if (StringUtils.isBlank(body.getBodyType())) {
|
||||
body.setBodyType(Body.BodyType.XML.name());
|
||||
}
|
||||
XmlBody xml = new XmlBody();
|
||||
//xml.setValue(XMLUtils.jsonToXmlStr(jsonValue));
|
||||
body.setXmlBody(xml);
|
||||
}
|
||||
case MediaType.APPLICATION_FORM_URLENCODED_VALUE -> {
|
||||
if (StringUtils.isBlank(body.getBodyType())) {
|
||||
body.setBodyType(Body.BodyType.WWW_FORM.name());
|
||||
}
|
||||
parseWWWFormBody(jsonSchemaItem, body);
|
||||
}
|
||||
case MediaType.MULTIPART_FORM_DATA_VALUE -> {
|
||||
if (StringUtils.isBlank(body.getBodyType())) {
|
||||
body.setBodyType(Body.BodyType.FORM_DATA.name());
|
||||
}
|
||||
}
|
||||
case MediaType.APPLICATION_OCTET_STREAM_VALUE -> {
|
||||
if (StringUtils.isBlank(body.getBodyType())) {
|
||||
body.setBodyType(Body.BodyType.BINARY.name());
|
||||
}
|
||||
}
|
||||
case MediaType.TEXT_PLAIN_VALUE -> {
|
||||
if (StringUtils.isBlank(body.getBodyType())) {
|
||||
body.setBodyType(Body.BodyType.RAW.name());
|
||||
}
|
||||
RawBody rawBody = new RawBody();
|
||||
body.setRawBody(rawBody);
|
||||
}
|
||||
default -> body.setBodyType(Body.BodyType.NONE.name());
|
||||
}
|
||||
}
|
||||
|
||||
private ApiDefinitionImportDTO buildApiDefinition(Operation operation, String path, String
|
||||
method, ImportRequest importRequest) {
|
||||
String name;
|
||||
if (StringUtils.isNotBlank(operation.getSummary())) {
|
||||
name = operation.getSummary();
|
||||
} else if (StringUtils.isNotBlank(operation.getOperationId())) {
|
||||
name = operation.getOperationId();
|
||||
} else {
|
||||
name = path;
|
||||
}
|
||||
ApiDefinitionImportDTO apiDefinition = new ApiDefinitionImportDTO();
|
||||
apiDefinition.setName(name);
|
||||
apiDefinition.setPath(formatPath(path));
|
||||
apiDefinition.setProtocol("HTTP");
|
||||
apiDefinition.setMethod(method);
|
||||
apiDefinition.setProjectId(this.projectId);
|
||||
if (StringUtils.equalsIgnoreCase("schedule", importRequest.getType())) {
|
||||
apiDefinition.setCreateUser(importRequest.getUserId());
|
||||
} else {
|
||||
apiDefinition.setCreateUser(SessionUtils.getUserId());
|
||||
}
|
||||
apiDefinition.setModulePath(CollectionUtils.isNotEmpty(operation.getTags()) ? StringUtils.join("/", operation.getTags().get(0)) : StringUtils.EMPTY);
|
||||
apiDefinition.setResponse(new ArrayList<>());
|
||||
return apiDefinition;
|
||||
}
|
||||
|
||||
protected MsHTTPElement buildRequest(String name, String path, String method) {
|
||||
MsHTTPElement request = new MsHTTPElement();
|
||||
request.setName(name);
|
||||
// 路径去掉域名/IP 地址,保留方法名称及参数
|
||||
request.setPath(formatPath(path));
|
||||
request.setMethod(method);
|
||||
request.setHeaders(new ArrayList<>());
|
||||
request.setQuery(new ArrayList<>());
|
||||
request.setRest(new ArrayList<>());
|
||||
request.setBody(new Body());
|
||||
MsHTTPConfig httpConfig = new MsHTTPConfig();
|
||||
httpConfig.setConnectTimeout(60000L);
|
||||
httpConfig.setResponseTimeout(60000L);
|
||||
request.setOtherConfig(httpConfig);
|
||||
request.setAuthConfig(new NoAuth());
|
||||
return request;
|
||||
}
|
||||
|
||||
private void parseParameters(Operation operation, MsHTTPElement request) {
|
||||
|
||||
List<Parameter> parameters = operation.getParameters();
|
||||
|
||||
if (CollectionUtils.isEmpty(parameters)) {
|
||||
return;
|
||||
}
|
||||
parameters.forEach(parameter -> {
|
||||
if (parameter instanceof QueryParameter queryParameter) {
|
||||
parseQueryParameters(queryParameter, request.getQuery());
|
||||
} else if (parameter instanceof PathParameter pathParameter) {
|
||||
parsePathParameters(pathParameter, request.getRest());
|
||||
} else if (parameter instanceof HeaderParameter headerParameter) {
|
||||
parseHeaderParameters(headerParameter, request.getHeaders());
|
||||
} else if (parameter instanceof CookieParameter cookieParameter) {
|
||||
parseCookieParameters(cookieParameter, request.getHeaders());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void parseParameters(PathItem path, MsHTTPElement request) {
|
||||
if (path.getParameters() == null) {
|
||||
return;
|
||||
}
|
||||
List<Parameter> parameters = path.getParameters();
|
||||
// 处理特殊格式 rest参数是和请求平级的情况
|
||||
|
||||
for (Parameter parameter : parameters) {
|
||||
if (StringUtils.isNotBlank(parameter.getIn())) {
|
||||
switch (parameter.getIn()) {
|
||||
case PATH -> parsePathParameters((PathParameter) parameter, request.getRest());
|
||||
case QUERY -> parseQueryParameters((QueryParameter) parameter, request.getQuery());
|
||||
case HEADER -> parseHeaderParameters((HeaderParameter) parameter, request.getHeaders());
|
||||
case COOKIE -> parseCookieParameters((CookieParameter) parameter, request.getHeaders());
|
||||
default -> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void parseQueryParameters(QueryParameter queryParameter, List<QueryParam> arguments) {
|
||||
QueryParam queryParam = new QueryParam();
|
||||
queryParam.setKey(getDefaultStringValue(queryParameter.getName()));
|
||||
queryParam.setRequired(queryParameter.getRequired());
|
||||
queryParam.setDescription(getDefaultStringValue(queryParameter.getDescription()));
|
||||
if (queryParameter.getSchema() != null) {
|
||||
queryParam.setParamType(queryParameter.getSchema().getType());
|
||||
queryParam.setValue(getDefaultStringValue(String.valueOf(queryParameter.getSchema().getExample())));
|
||||
queryParam.setMinLength(queryParameter.getSchema().getMinLength());
|
||||
queryParam.setMaxLength(queryParameter.getSchema().getMaxLength());
|
||||
}
|
||||
arguments.add(queryParam);
|
||||
}
|
||||
|
||||
|
||||
private void parseCookieParameters(CookieParameter cookieParameter, List<Header> headers) {
|
||||
Header headerParams = new Header();
|
||||
headerParams.setKey(getDefaultStringValue(cookieParameter.getName()));
|
||||
headerParams.setDescription(getDefaultStringValue(cookieParameter.getDescription()));
|
||||
if (cookieParameter.getSchema() != null) {
|
||||
headerParams.setValue(getDefaultStringValue(String.valueOf(cookieParameter.getSchema().getExample())));
|
||||
}
|
||||
headers.add(headerParams);
|
||||
}
|
||||
|
||||
private void parseHeaderParameters(HeaderParameter headerParameter, List<Header> headers) {
|
||||
Header headerParams = new Header();
|
||||
headerParams.setKey(getDefaultStringValue(headerParameter.getName()));
|
||||
headerParams.setDescription(getDefaultStringValue(headerParameter.getDescription()));
|
||||
if (headerParameter.getSchema() != null) {
|
||||
headerParams.setValue(getDefaultStringValue(String.valueOf(headerParameter.getSchema().getExample())));
|
||||
}
|
||||
headers.add(headerParams);
|
||||
}
|
||||
|
||||
|
||||
private void parsePathParameters(PathParameter parameter, List<RestParam> rest) {
|
||||
RestParam restParam = new RestParam();
|
||||
restParam.setKey(getDefaultStringValue(parameter.getName()));
|
||||
restParam.setRequired(parameter.getRequired());
|
||||
restParam.setDescription(getDefaultStringValue(parameter.getDescription()));
|
||||
if (parameter.getSchema() != null) {
|
||||
restParam.setParamType(parameter.getSchema().getType());
|
||||
restParam.setValue(getDefaultStringValue(String.valueOf(parameter.getSchema().getExample())));
|
||||
restParam.setMinLength(parameter.getSchema().getMinLength());
|
||||
restParam.setMaxLength(parameter.getSchema().getMaxLength());
|
||||
}
|
||||
rest.add(restParam);
|
||||
}
|
||||
|
||||
private String getDefaultStringValue(String val) {
|
||||
return StringUtils.isBlank(val) ? StringUtils.EMPTY : val;
|
||||
}
|
||||
|
||||
private Schema getModelByRef(String ref) {
|
||||
if (StringUtils.isBlank(ref)) {
|
||||
return null;
|
||||
}
|
||||
if (ref.split("/").length > 3) {
|
||||
ref = ref.replace("#/components/schemas/", StringUtils.EMPTY);
|
||||
}
|
||||
if (this.components.getSchemas() != null) return this.components.getSchemas().get(ref);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private JsonSchemaItem parseSchema(Schema schema) {
|
||||
if (schema != null) {
|
||||
String refName = schema.get$ref();
|
||||
Schema modelByRef = null;
|
||||
if (StringUtils.isNotBlank(refName)) {
|
||||
modelByRef = getModelByRef(refName);
|
||||
} else {
|
||||
modelByRef = schema;
|
||||
}
|
||||
|
||||
if (modelByRef != null) {
|
||||
if (modelByRef instanceof ArraySchema arraySchema) {
|
||||
return parseArraySchema(arraySchema.getItems());
|
||||
} else if (modelByRef instanceof ObjectSchema objectSchema) {
|
||||
return parseObject(objectSchema);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private JsonSchemaItem parseMapObject(MapSchema mapSchema) {
|
||||
JsonSchemaItem jsonSchemaItem = new JsonSchemaItem();
|
||||
jsonSchemaItem.setType(PropertyConstant.OBJECT);
|
||||
jsonSchemaItem.setRequired(mapSchema.getRequired());
|
||||
jsonSchemaItem.setDescription(mapSchema.getDescription());
|
||||
Object value = mapSchema.getAdditionalProperties();
|
||||
Map<String, JsonSchemaItem> jsonSchemaProperties = new LinkedHashMap<>();
|
||||
if (ObjectUtils.isEmpty(value)) {
|
||||
return jsonSchemaItem;
|
||||
}
|
||||
JsonSchemaItem item = new JsonSchemaItem();
|
||||
if (value instanceof IntegerSchema integerSchema) {
|
||||
item = parseInteger(integerSchema);
|
||||
} else if (value instanceof StringSchema stringSchema) {
|
||||
item = parseString(stringSchema);
|
||||
} else if (value instanceof NumberSchema numberSchema) {
|
||||
item = parseNumber(numberSchema);
|
||||
} else if (value instanceof BooleanSchema booleanSchema) {
|
||||
item = parseBoolean(booleanSchema);
|
||||
} else if (value instanceof ArraySchema arraySchema) {
|
||||
item = parseArraySchema(arraySchema.getItems());
|
||||
} else if (value instanceof ObjectSchema objectSchemaItem) {
|
||||
item = parseObject(objectSchemaItem);
|
||||
}
|
||||
jsonSchemaProperties.put(StringUtils.EMPTY, item);
|
||||
jsonSchemaItem.setProperties(jsonSchemaProperties);
|
||||
return jsonSchemaItem;
|
||||
}
|
||||
|
||||
private JsonSchemaItem parseObject(ObjectSchema objectSchema) {
|
||||
JsonSchemaItem jsonSchemaItem = new JsonSchemaItem();
|
||||
jsonSchemaItem.setType(PropertyConstant.OBJECT);
|
||||
jsonSchemaItem.setRequired(objectSchema.getRequired());
|
||||
jsonSchemaItem.setDescription(objectSchema.getDescription());
|
||||
Map<String, Schema> properties = objectSchema.getProperties();
|
||||
Map<String, JsonSchemaItem> jsonSchemaProperties = new LinkedHashMap<>();
|
||||
if (MapUtils.isNotEmpty(properties)) {
|
||||
properties.forEach((key, value) -> {
|
||||
JsonSchemaItem item = new JsonSchemaItem();
|
||||
if (value instanceof IntegerSchema integerSchema) {
|
||||
item = parseInteger(integerSchema);
|
||||
} else if (value instanceof StringSchema stringSchema) {
|
||||
item = parseString(stringSchema);
|
||||
} else if (value instanceof NumberSchema numberSchema) {
|
||||
item = parseNumber(numberSchema);
|
||||
} else if (value instanceof BooleanSchema booleanSchema) {
|
||||
item = parseBoolean(booleanSchema);
|
||||
} else if (value instanceof ArraySchema arraySchema) {
|
||||
if (!isRef(arraySchema.getItems(), 0)) {
|
||||
JsonSchemaItem arrayItem = new JsonSchemaItem();
|
||||
arrayItem.setType(PropertyConstant.ARRAY);
|
||||
arrayItem.setItems(new JsonSchemaItem());
|
||||
item = arrayItem;
|
||||
jsonSchemaProperties.put(key, item);
|
||||
return;
|
||||
}
|
||||
item = parseArraySchema(arraySchema.getItems());
|
||||
} else if (value instanceof ObjectSchema objectSchemaItem) {
|
||||
if (!isRef(objectSchemaItem, 0)) {
|
||||
JsonSchemaItem objectItem = new JsonSchemaItem();
|
||||
objectItem.setType(PropertyConstant.OBJECT);
|
||||
objectItem.setProperties(new LinkedHashMap<>());
|
||||
item = objectItem;
|
||||
jsonSchemaProperties.put(key, item);
|
||||
return;
|
||||
}
|
||||
item = parseObject(objectSchemaItem);
|
||||
} else if (StringUtils.equals(value.getType(), "null")) {
|
||||
item = parseNull();
|
||||
} else if (value instanceof MapSchema mapSchema) {
|
||||
item = parseMapObject(mapSchema);
|
||||
} else if (value instanceof Schema<?> items) {
|
||||
/*if (StringUtils.isNotBlank(items.get$ref()) && StringUtils.equals(items.get$ref(), ref)) {
|
||||
return;
|
||||
}*/
|
||||
item = parseSchema(items);
|
||||
}
|
||||
jsonSchemaProperties.put(key, item);
|
||||
});
|
||||
}
|
||||
jsonSchemaItem.setProperties(jsonSchemaProperties);
|
||||
return jsonSchemaItem;
|
||||
}
|
||||
|
||||
//判断对象是否存在一直引用
|
||||
private boolean isRef(Schema schema, int level) {
|
||||
if (schema == null) {
|
||||
return false;
|
||||
}
|
||||
if (level > 20) {
|
||||
return true;
|
||||
}
|
||||
if (StringUtils.isNotBlank(schema.get$ref())) {
|
||||
return false;
|
||||
}
|
||||
if (schema instanceof ArraySchema arraySchema) {
|
||||
return isRef(arraySchema.getItems(), level + 1);
|
||||
}
|
||||
if (schema instanceof ObjectSchema objectSchema) {
|
||||
Map<String, Schema> properties = objectSchema.getProperties();
|
||||
if (MapUtils.isNotEmpty(properties)) {
|
||||
int finalLevel = level;
|
||||
properties.forEach((key, value) -> {
|
||||
if (value instanceof ArraySchema arraySchemaItem) {
|
||||
isRef(arraySchemaItem.getItems(), finalLevel + 1);
|
||||
}
|
||||
if (value instanceof ObjectSchema objectSchemaItem) {
|
||||
isRef(objectSchemaItem, finalLevel + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private JsonSchemaItem parseString(StringSchema stringSchema) {
|
||||
JsonSchemaItem jsonSchemaString = new JsonSchemaItem();
|
||||
jsonSchemaString.setType(PropertyConstant.STRING);
|
||||
jsonSchemaString.setFormat(StringUtils.isNotBlank(stringSchema.getFormat()) ? stringSchema.getFormat() : StringUtils.EMPTY);
|
||||
jsonSchemaString.setDescription(getDefaultStringValue(stringSchema.getDescription()));
|
||||
jsonSchemaString.setExample(stringSchema.getExample());
|
||||
if (stringSchema.getMaxLength() != null) {
|
||||
jsonSchemaString.setMaxLength(stringSchema.getMaxLength());
|
||||
}
|
||||
if (stringSchema.getMinLength() != null) {
|
||||
jsonSchemaString.setMinLength(stringSchema.getMinLength());
|
||||
}
|
||||
jsonSchemaString.setPattern(stringSchema.getPattern());
|
||||
jsonSchemaString.setEnumString(stringSchema.getEnum());
|
||||
if (stringSchema.getExample() == null && CollectionUtils.isNotEmpty(stringSchema.getEnum())) {
|
||||
jsonSchemaString.setExample(stringSchema.getEnum().get(0));
|
||||
}
|
||||
return jsonSchemaString;
|
||||
}
|
||||
|
||||
private JsonSchemaItem parseInteger(IntegerSchema integerSchema) {
|
||||
JsonSchemaItem jsonSchemaInteger = new JsonSchemaItem();
|
||||
jsonSchemaInteger.setType(PropertyConstant.INTEGER);
|
||||
jsonSchemaInteger.setFormat(StringUtils.isNotBlank(integerSchema.getFormat()) ? integerSchema.getFormat() : StringUtils.EMPTY);
|
||||
jsonSchemaInteger.setDescription(StringUtils.isNotBlank(integerSchema.getDescription()) ? integerSchema.getDescription() : StringUtils.EMPTY);
|
||||
jsonSchemaInteger.setExample(integerSchema.getExample());
|
||||
jsonSchemaInteger.setMaximum(integerSchema.getMaximum());
|
||||
jsonSchemaInteger.setMinimum(integerSchema.getMinimum());
|
||||
jsonSchemaInteger.setEnumInteger(integerSchema.getEnum());
|
||||
return jsonSchemaInteger;
|
||||
}
|
||||
|
||||
private JsonSchemaItem parseNumber(NumberSchema numberSchema) {
|
||||
JsonSchemaItem jsonSchemaNumber = new JsonSchemaItem();
|
||||
jsonSchemaNumber.setType(PropertyConstant.NUMBER);
|
||||
jsonSchemaNumber.setDescription(StringUtils.isNotBlank(numberSchema.getDescription()) ? numberSchema.getDescription() : StringUtils.EMPTY);
|
||||
jsonSchemaNumber.setExample(numberSchema.getExample());
|
||||
jsonSchemaNumber.setEnumNumber(numberSchema.getEnum());
|
||||
return jsonSchemaNumber;
|
||||
}
|
||||
|
||||
private JsonSchemaItem parseBoolean(BooleanSchema booleanSchema) {
|
||||
JsonSchemaItem jsonSchemaBoolean = new JsonSchemaItem();
|
||||
jsonSchemaBoolean.setType(PropertyConstant.BOOLEAN);
|
||||
jsonSchemaBoolean.setDescription(getDefaultStringValue(booleanSchema.getDescription()));
|
||||
jsonSchemaBoolean.setExample(booleanSchema.getExample());
|
||||
return jsonSchemaBoolean;
|
||||
}
|
||||
|
||||
private JsonSchemaItem parseNull() {
|
||||
JsonSchemaItem jsonSchemaNull = new JsonSchemaItem();
|
||||
jsonSchemaNull.setType(PropertyConstant.NULL);
|
||||
return jsonSchemaNull;
|
||||
}
|
||||
|
||||
private JsonSchemaItem parseArraySchema(Schema<?> items) {
|
||||
JsonSchemaItem jsonSchemaArray = new JsonSchemaItem();
|
||||
jsonSchemaArray.setType(PropertyConstant.ARRAY);
|
||||
Schema itemsSchema = null;
|
||||
if (StringUtils.isNotBlank(items.get$ref())) {
|
||||
itemsSchema = getModelByRef(items.get$ref());
|
||||
} else {
|
||||
itemsSchema = items;
|
||||
}
|
||||
if (itemsSchema instanceof IntegerSchema integerSchema) {
|
||||
jsonSchemaArray.setItems(parseInteger(integerSchema));
|
||||
} else if (itemsSchema instanceof StringSchema stringSchema) {
|
||||
jsonSchemaArray.setItems(parseString(stringSchema));
|
||||
} else if (itemsSchema instanceof NumberSchema numberSchema) {
|
||||
jsonSchemaArray.setItems(parseNumber(numberSchema));
|
||||
} else if (itemsSchema instanceof BooleanSchema booleanSchema) {
|
||||
jsonSchemaArray.setItems(parseBoolean(booleanSchema));
|
||||
} else if (itemsSchema instanceof ArraySchema arraySchema) {
|
||||
jsonSchemaArray.setItems(parseArraySchema(arraySchema.getItems()));
|
||||
} else if (itemsSchema instanceof ObjectSchema objectSchema) {
|
||||
jsonSchemaArray.setItems(parseObject(objectSchema));
|
||||
} else if (ObjectUtils.isNotEmpty(itemsSchema) && StringUtils.equals("null", itemsSchema.getType())) {
|
||||
jsonSchemaArray.setItems(parseNull());
|
||||
}
|
||||
return jsonSchemaArray;
|
||||
}
|
||||
|
||||
private String formatPath(String url) {
|
||||
try {
|
||||
URI urlObject = new URI(url);
|
||||
String path = StringUtils.isBlank(urlObject.getPath()) ? "/" : urlObject.getPath();
|
||||
StringBuilder pathBuffer = new StringBuilder(path);
|
||||
if (StringUtils.isNotEmpty(urlObject.getQuery())) {
|
||||
pathBuffer.append("?").append(urlObject.getQuery());
|
||||
}
|
||||
return pathBuffer.toString();
|
||||
} catch (Exception ex) {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public class MsJsonBodyConverter extends MsBodyConverter<JsonBody> {
|
|||
|
||||
/**
|
||||
* 将json中的 @xxx 转换成 ${__Mock(@xxx)}
|
||||
*
|
||||
* @param jsonStr
|
||||
* @return
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,647 @@
|
|||
package io.metersphere.api.service.definition;
|
||||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.domain.ApiDefinitionBlob;
|
||||
import io.metersphere.api.domain.ApiDefinitionBlobExample;
|
||||
import io.metersphere.api.domain.ApiDefinitionModule;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionPageRequest;
|
||||
import io.metersphere.api.dto.definition.ApiModuleRequest;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDeatlWithData;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDeatlWithDataUpdate;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImportDTO;
|
||||
import io.metersphere.api.dto.request.ImportRequest;
|
||||
import io.metersphere.api.dto.request.http.Header;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.dto.request.http.QueryParam;
|
||||
import io.metersphere.api.dto.request.http.RestParam;
|
||||
import io.metersphere.api.dto.request.http.body.*;
|
||||
import io.metersphere.api.dto.schema.JsonSchemaItem;
|
||||
import io.metersphere.api.enums.PropertyConstant;
|
||||
import io.metersphere.api.mapper.*;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||
import io.metersphere.project.mapper.ProjectApplicationMapper;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.uid.NumGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
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.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ApiDefinitionImportUtilService {
|
||||
|
||||
private static final String UNPLANNED_API = "api_unplanned_request";
|
||||
private static final String MODULE = "modulePath";
|
||||
public static final Long ORDER_STEP = 5000L;
|
||||
private final ThreadLocal<Long> currentApiOrder = new ThreadLocal<>();
|
||||
private final ThreadLocal<Long> currentApiCaseOrder = new ThreadLocal<>();
|
||||
private final ThreadLocal<Long> currentModuleOrder = new ThreadLocal<>();
|
||||
@Resource
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
@Resource
|
||||
private ExtBaseProjectVersionMapper extBaseProjectVersionMapper;
|
||||
@Resource
|
||||
private ProjectApplicationMapper projectApplicationMapper;
|
||||
@Resource
|
||||
private ExtApiDefinitionModuleMapper extApiDefinitionModuleMapper;
|
||||
@Resource
|
||||
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
||||
@Resource
|
||||
private ApiDefinitionBlobMapper apiDefinitionBlobMapper;
|
||||
@Resource
|
||||
private ApiTestCaseService apiTestCaseService;
|
||||
@Resource
|
||||
private ApiDefinitionModuleService apiDefinitionModuleService;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private OperationLogService operationLogService;
|
||||
|
||||
public void checkFileSuffixName(ImportRequest request, String suffixName) {
|
||||
if ("jmx".equalsIgnoreCase(suffixName)) {
|
||||
if (!"JMeter".equalsIgnoreCase(request.getPlatform())) {
|
||||
throw new MSException(Translator.get("file_format_does_not_meet_requirements"));
|
||||
}
|
||||
}
|
||||
if ("har".equalsIgnoreCase(suffixName)) {
|
||||
if (!"Har".equalsIgnoreCase(request.getPlatform())) {
|
||||
throw new MSException(Translator.get("file_format_does_not_meet_requirements"));
|
||||
}
|
||||
}
|
||||
if ("json".equalsIgnoreCase(suffixName)) {
|
||||
if ("Har".equalsIgnoreCase(request.getPlatform()) || "Jmeter".equalsIgnoreCase(request.getPlatform())) {
|
||||
throw new MSException(Translator.get("file_format_does_not_meet_requirements"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void importApi(ImportRequest request, ApiDefinitionImport apiImport) {
|
||||
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(request.getProjectId());
|
||||
request.setDefaultVersion(defaultVersion);
|
||||
if (request.getVersionId() == null) {
|
||||
request.setVersionId(defaultVersion);
|
||||
}
|
||||
List<ApiDefinitionImportDTO> initData = apiImport.getData();
|
||||
|
||||
//TODO 查询项目菜单参数
|
||||
/*ProjectApplicationExample applicationExample = new ProjectApplicationExample();
|
||||
applicationExample.createCriteria().andProjectIdEqualTo(request.getProjectId()).andTypeEqualTo("API_URL_REPEATABLE");
|
||||
List<ProjectApplication> projectApplications = projectApplicationMapper.selectByExample(applicationExample);
|
||||
if (CollectionUtils.isNotEmpty(projectApplications)) {
|
||||
String typeValue = projectApplications.get(0).getTypeValue();
|
||||
}*/
|
||||
//过滤(一次只导入一个协议)
|
||||
List<ApiDefinitionImportDTO> filterData = initData.stream().filter(t -> t.getProtocol().equals(request.getProtocol())).collect(Collectors.toList());
|
||||
if (filterData.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//处理数据,判断数据是否重复
|
||||
dealWithData(request, filterData);
|
||||
|
||||
}
|
||||
|
||||
private void dealWithData(ImportRequest request, List<ApiDefinitionImportDTO> importData) {
|
||||
//查询数据库中所有的数据, 用于判断是否重复
|
||||
ApiDefinitionPageRequest pageRequest = new ApiDefinitionPageRequest();
|
||||
pageRequest.setProjectId(request.getProjectId());
|
||||
pageRequest.setProtocol(request.getProtocol());
|
||||
//TODO 如果是有版本的话 需要加上版本的判断
|
||||
List<ApiDefinitionImportDTO> apiLists = extApiDefinitionMapper.importList(pageRequest);
|
||||
List<BaseTreeNode> apiModules = this.buildTreeData(request.getProjectId(), request.getProtocol());
|
||||
//将apiModules转换成新的map 要求key是attachInfo中的modulePath 使用stream实现
|
||||
Map<String, BaseTreeNode> modulePathMap = apiModules.stream().collect(Collectors.toMap(t -> t.getAttachInfo().get(MODULE), t -> t));
|
||||
Map<String, BaseTreeNode> idModuleMap = apiModules.stream().collect(Collectors.toMap(BaseTreeNode::getId, apiModuleDTO -> apiModuleDTO));
|
||||
//如果导入的时候选择了模块,需要把所有的导入数据的模块路径前面拼接上选择的模块路径
|
||||
if (StringUtils.isNotBlank(request.getModuleId())) {
|
||||
BaseTreeNode baseTreeNode = idModuleMap.get(request.getModuleId());
|
||||
String modulePath = baseTreeNode.getAttachInfo().get(MODULE);
|
||||
importData.forEach(t -> {
|
||||
t.setModulePath(modulePath + t.getModulePath());
|
||||
});
|
||||
}
|
||||
//去掉apiLists中不存在的模块数据
|
||||
apiLists = apiLists.stream().filter(t -> modulePathMap.containsKey(t.getModulePath())).toList();
|
||||
apiLists.forEach(t -> {
|
||||
t.setModulePath(idModuleMap.get(t.getModuleId()) != null ? idModuleMap.get(t.getModuleId()).getAttachInfo().get(MODULE) : StringUtils.EMPTY);
|
||||
});
|
||||
ApiDeatlWithData apiDeatlWithData = new ApiDeatlWithData();
|
||||
//判断数据是否是唯一的
|
||||
checkApiDataOnly(request, importData, apiLists, apiDeatlWithData);
|
||||
|
||||
ApiDeatlWithDataUpdate apiDeatlWithDataUpdate = new ApiDeatlWithDataUpdate();
|
||||
getNeedUpdateData(request, apiDeatlWithData, apiDeatlWithDataUpdate);
|
||||
|
||||
//数据入库
|
||||
insertData(modulePathMap, idModuleMap, apiDeatlWithDataUpdate, request);
|
||||
|
||||
}
|
||||
|
||||
public Long getNextOrder(String projectId) {
|
||||
Long pos = extApiDefinitionMapper.getPos(projectId);
|
||||
return (pos == null ? 0 : pos) + ORDER_STEP;
|
||||
}
|
||||
|
||||
public Long getImportNextOrder(String projectId) {
|
||||
Long order = currentApiOrder.get();
|
||||
if (order == null) {
|
||||
order = getNextOrder(projectId);
|
||||
}
|
||||
order = order + ORDER_STEP;
|
||||
currentApiOrder.set(order);
|
||||
return order;
|
||||
}
|
||||
|
||||
public Long getImportNextCaseOrder(String projectId) {
|
||||
Long order = currentApiCaseOrder.get();
|
||||
if (order == null) {
|
||||
order = apiTestCaseService.getNextOrder(projectId);
|
||||
}
|
||||
order = order + ORDER_STEP;
|
||||
currentApiCaseOrder.set(order);
|
||||
return order;
|
||||
}
|
||||
|
||||
public Long getImportNextModuleOrder(String projectId) {
|
||||
Long order = currentModuleOrder.get();
|
||||
if (order == null) {
|
||||
order = apiDefinitionModuleService.getNextOrder(projectId);
|
||||
}
|
||||
order = order + ORDER_STEP;
|
||||
currentModuleOrder.set(order);
|
||||
return order;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void insertData(Map<String, BaseTreeNode> modulePathMap,
|
||||
Map<String, BaseTreeNode> idModuleMap,
|
||||
ApiDeatlWithDataUpdate apiDeatlWithDataUpdate,
|
||||
ImportRequest request) {
|
||||
//先判断是否需要新增模块
|
||||
List<ApiDefinitionImportDTO> addModuleData = apiDeatlWithDataUpdate.getAddModuleData();
|
||||
List<ApiDefinitionImportDTO> updateModuleData = apiDeatlWithDataUpdate.getUpdateModuleData();
|
||||
//取addModuleData的模块放到set中 生成一个新的set
|
||||
Set<String> moduleSet = addModuleData.stream().map(ApiDefinitionImportDTO::getModulePath).collect(Collectors.toSet());
|
||||
//取updateModuleData的模块放到set中 生成一个新的set
|
||||
Set<String> updateModuleSet = updateModuleData.stream().map(ApiDefinitionImportDTO::getModulePath).collect(Collectors.toSet());
|
||||
moduleSet.addAll(updateModuleSet);
|
||||
//将modulePathMap的key转成set
|
||||
Set<String> modulePathSet = modulePathMap.keySet();
|
||||
//取modulePathSet中不存在的
|
||||
Set<String> differenceSet = moduleSet.stream().filter(t -> !modulePathSet.contains(t)).collect(Collectors.toSet());
|
||||
//不存在的需要新增
|
||||
List<BaseTreeNode> addModuleList = new ArrayList<>();
|
||||
|
||||
currentApiCaseOrder.remove();
|
||||
currentApiOrder.remove();
|
||||
currentModuleOrder.remove();
|
||||
differenceSet.forEach(item -> {
|
||||
//解析modulePath 格式为/a/b/c
|
||||
String[] split = item.split("/");
|
||||
//一层一层的创建
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
String path = StringUtils.join(split, "/", 0, i + 1);
|
||||
BaseTreeNode baseTreeNode = modulePathMap.get(path);
|
||||
if (baseTreeNode == null) {
|
||||
//创建模块
|
||||
BaseTreeNode module = new BaseTreeNode();
|
||||
module.setId(IDGenerator.nextStr());
|
||||
module.setName(split[i]);
|
||||
module.setParentId(i == 0 ? ModuleConstants.ROOT_NODE_PARENT_ID : modulePathMap.get(StringUtils.join(split, "/", 0, i)).getId());
|
||||
addModuleList.add(module);
|
||||
modulePathMap.put(path, module);
|
||||
idModuleMap.put(module.getId(), module);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//创建模块
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
ApiDefinitionModuleMapper moduleMapper = sqlSession.getMapper(ApiDefinitionModuleMapper.class);
|
||||
ApiDefinitionMapper apiMapper = sqlSession.getMapper(ApiDefinitionMapper.class);
|
||||
ApiDefinitionBlobMapper apiBlobMapper = sqlSession.getMapper(ApiDefinitionBlobMapper.class);
|
||||
|
||||
addModuleList.forEach(t -> {
|
||||
ApiDefinitionModule module = new ApiDefinitionModule();
|
||||
module.setId(t.getId());
|
||||
module.setName(t.getName());
|
||||
module.setParentId(t.getParentId());
|
||||
module.setProjectId(request.getProjectId());
|
||||
module.setCreateUser(request.getUserId());
|
||||
module.setPos(getImportNextModuleOrder(request.getProjectId()));
|
||||
module.setCreateTime(System.currentTimeMillis());
|
||||
module.setUpdateUser(request.getUserId());
|
||||
module.setUpdateTime(System.currentTimeMillis());
|
||||
moduleMapper.insertSelective(module);
|
||||
});
|
||||
|
||||
//取出需要更新的数据的id
|
||||
List<String> updateModuleLists = updateModuleData.stream().map(ApiDefinitionImportDTO::getId).toList();
|
||||
|
||||
//更新模块数据
|
||||
updateModuleData.forEach(t -> {
|
||||
ApiDefinition apiDefinition = new ApiDefinition();
|
||||
apiDefinition.setId(t.getId());
|
||||
apiDefinition.setModuleId(modulePathMap.get(t.getModulePath()).getId());
|
||||
apiDefinition.setUpdateUser(request.getUserId());
|
||||
apiDefinition.setUpdateTime(System.currentTimeMillis());
|
||||
apiMapper.updateByPrimaryKeySelective(apiDefinition);
|
||||
});
|
||||
List<LogDTO> operationLogs = new ArrayList<>();
|
||||
List<ApiDefinitionImportDTO> updateRequestData = apiDeatlWithDataUpdate.getUpdateRequestData();
|
||||
updateRequestData.forEach(t -> {
|
||||
if (CollectionUtils.isNotEmpty(updateModuleLists) && updateModuleLists.contains(t.getId())) {
|
||||
ApiDefinition apiDefinition = new ApiDefinition();
|
||||
apiDefinition.setId(t.getId());
|
||||
apiDefinition.setUpdateUser(request.getUserId());
|
||||
apiDefinition.setUpdateTime(System.currentTimeMillis());
|
||||
apiMapper.updateByPrimaryKeySelective(apiDefinition);
|
||||
}
|
||||
//更新blob数据
|
||||
ApiDefinitionBlob apiDefinitionBlob = new ApiDefinitionBlob();
|
||||
apiDefinitionBlob.setId(t.getId());
|
||||
apiDefinitionBlob.setRequest(JSON.toJSONBytes(t.getRequest()));
|
||||
apiDefinitionBlob.setResponse(JSON.toJSONBytes(t.getResponse()));
|
||||
apiBlobMapper.updateByPrimaryKeySelective(apiDefinitionBlob);
|
||||
});
|
||||
Map<String, ApiDefinitionImportDTO> logData = apiDeatlWithDataUpdate.getLogData();
|
||||
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
|
||||
if (MapUtils.isNotEmpty(logData)) {
|
||||
logData.forEach((k, v) -> {
|
||||
ApiDefinitionDTO apiDefinitionDTO = new ApiDefinitionDTO();
|
||||
BeanUtils.copyBean(apiDefinitionDTO, v);
|
||||
LogDTO dto = new LogDTO(
|
||||
project.getId(),
|
||||
project.getOrganizationId(),
|
||||
v.getId(),
|
||||
request.getUserId(),
|
||||
OperationLogType.IMPORT.name(),
|
||||
OperationLogModule.API_DEFINITION,
|
||||
v.getName());
|
||||
dto.setHistory(true);
|
||||
dto.setPath("/api/definition/import");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(apiDefinitionDTO));
|
||||
operationLogs.add(dto);
|
||||
});
|
||||
}
|
||||
addModuleData.forEach(t -> {
|
||||
ApiDefinition apiDefinition = new ApiDefinition();
|
||||
BeanUtils.copyBean(apiDefinition, t);
|
||||
apiDefinition.setId(IDGenerator.nextStr());
|
||||
apiDefinition.setModuleId(modulePathMap.get(t.getModulePath()).getId());
|
||||
apiDefinition.setProjectId(request.getProjectId());
|
||||
apiDefinition.setProtocol(request.getProtocol());
|
||||
apiDefinition.setCreateUser(request.getUserId());
|
||||
apiDefinition.setPos(getImportNextOrder(request.getProjectId()));
|
||||
apiDefinition.setCreateTime(System.currentTimeMillis());
|
||||
apiDefinition.setUpdateUser(request.getUserId());
|
||||
apiDefinition.setUpdateTime(System.currentTimeMillis());
|
||||
apiDefinition.setNum(NumGenerator.nextNum(request.getProjectId(), ApplicationNumScope.API_DEFINITION));
|
||||
apiDefinition.setLatest(true);
|
||||
apiDefinition.setStatus("Underway");
|
||||
apiDefinition.setRefId(apiDefinition.getId());
|
||||
apiDefinition.setVersionId(request.getVersionId());
|
||||
apiMapper.insertSelective(apiDefinition);
|
||||
//插入blob数据
|
||||
ApiDefinitionBlob apiDefinitionBlob = new ApiDefinitionBlob();
|
||||
apiDefinitionBlob.setId(apiDefinition.getId());
|
||||
apiDefinitionBlob.setRequest(JSON.toJSONBytes(t.getRequest()));
|
||||
apiDefinitionBlob.setResponse(JSON.toJSONBytes(t.getResponse()));
|
||||
apiBlobMapper.insertSelective(apiDefinitionBlob);
|
||||
ApiDefinitionDTO apiDefinitionDTO = new ApiDefinitionDTO();
|
||||
BeanUtils.copyBean(apiDefinitionDTO, t);
|
||||
LogDTO dto = new LogDTO(
|
||||
project.getId(),
|
||||
project.getOrganizationId(),
|
||||
t.getId(),
|
||||
request.getUserId(),
|
||||
OperationLogType.IMPORT.name(),
|
||||
OperationLogModule.API_DEFINITION,
|
||||
t.getName());
|
||||
dto.setHistory(true);
|
||||
dto.setPath("/api/definition/import");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(apiDefinitionDTO));
|
||||
});
|
||||
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
operationLogService.batchAdd(operationLogs);
|
||||
}
|
||||
|
||||
private void getNeedUpdateData(ImportRequest request, ApiDeatlWithData apiDeatlWithData, ApiDeatlWithDataUpdate apiDeatlWithDataUpdate) {
|
||||
List<String> sameList = apiDeatlWithData.getSameList();
|
||||
List<String> differenceList = apiDeatlWithData.getDifferenceList();
|
||||
Map<String, ApiDefinitionImportDTO> apiDateMap = apiDeatlWithData.getApiDateMap();
|
||||
Map<String, ApiDefinitionImportDTO> importDataMap = apiDeatlWithData.getImportDataMap();
|
||||
List<ApiDefinitionImportDTO> updateModuleData = new ArrayList<>();
|
||||
List<ApiDefinitionImportDTO> updateRequestData = new ArrayList<>();
|
||||
List<ApiDefinitionImportDTO> addData = new ArrayList<>();
|
||||
//判断参数是否一样 一样的参数需要判断是否需要覆盖模块 如果需要就要update数据, 如果不需要 就直接跳过
|
||||
if (CollectionUtils.isNotEmpty(sameList) && getFullCoverage(request.getCoverData())) {
|
||||
//需要覆盖数据的 会判断是否需要覆盖模块
|
||||
List<ApiDefinitionImportDTO> sameData = sameList.stream().map(apiDateMap::get).toList();
|
||||
//取所有id为新的list 需要取查询blob的数据
|
||||
List<String> sameIds = sameData.stream().map(ApiDefinitionImportDTO::getId).toList();
|
||||
ApiDefinitionBlobExample blobExample = new ApiDefinitionBlobExample();
|
||||
blobExample.createCriteria().andIdIn(sameIds);
|
||||
List<ApiDefinitionBlob> apiDefinitionBlobs = apiDefinitionBlobMapper.selectByExampleWithBLOBs(blobExample);
|
||||
Map<String, ApiDefinitionImportDTO> logMap = new HashMap<>();
|
||||
Map<String, ApiDefinitionBlob> blobMap = apiDefinitionBlobs.stream().collect(Collectors.toMap(ApiDefinitionBlob::getId, t -> t));
|
||||
//判断参数是否一样
|
||||
for (ApiDefinitionImportDTO apiDefinitionDTO : sameData) {
|
||||
ApiDefinitionImportDTO importDTO = importDataMap.get(apiDefinitionDTO.getMethod() + apiDefinitionDTO.getPath());
|
||||
ApiDefinitionBlob apiDefinitionBlob = blobMap.get(apiDefinitionDTO.getId());
|
||||
if (apiDefinitionBlob != null) {
|
||||
MsHTTPElement dbRequest = ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), MsHTTPElement.class);
|
||||
//判断参数是否一样 参数类型有 请求头 请求参数 请求体
|
||||
boolean isSame = dataIsSame(dbRequest, (MsHTTPElement) importDTO.getRequest());
|
||||
//判断是否开启模块覆盖
|
||||
if (getFullCoverage(request.getCoverModule())) {
|
||||
//判断模块是否一样
|
||||
if (!StringUtils.equals(apiDefinitionDTO.getModulePath(), importDTO.getModulePath())) {
|
||||
//不一样的模块需要更
|
||||
apiDefinitionDTO.setModulePath(apiDefinitionDTO.getModulePath());
|
||||
updateModuleData.add(apiDefinitionDTO);
|
||||
logMap.put(apiDefinitionDTO.getId(), importDTO);
|
||||
}
|
||||
}
|
||||
//不相同的数据需要覆盖 所以这里记录id就可以
|
||||
if (!isSame) {
|
||||
importDTO.setId(apiDefinitionDTO.getId());
|
||||
updateRequestData.add(importDTO);
|
||||
logMap.put(apiDefinitionDTO.getId(), importDTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//不存在的数据是肯定要插入的 TODO 这里需要判断是否需要创建模块
|
||||
if (CollectionUtils.isNotEmpty(differenceList)) {
|
||||
addData = differenceList.stream().map(importDataMap::get).toList();
|
||||
}
|
||||
apiDeatlWithDataUpdate.setUpdateModuleData(updateModuleData);
|
||||
apiDeatlWithDataUpdate.setUpdateRequestData(updateRequestData);
|
||||
apiDeatlWithDataUpdate.setAddModuleData(addData);
|
||||
}
|
||||
|
||||
private void checkApiDataOnly(ImportRequest request,
|
||||
List<ApiDefinitionImportDTO> importData,
|
||||
List<ApiDefinitionImportDTO> apiLists,
|
||||
ApiDeatlWithData apiDeatlWithData) {
|
||||
//判断是否是同一接口 需要返回的数据 需要insert的 update的
|
||||
switch (request.getUniquelyIdentifies()) {
|
||||
case "Method & Path" -> methodAndPath(importData, apiLists, apiDeatlWithData);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void methodAndPath(List<ApiDefinitionImportDTO> importData,
|
||||
List<ApiDefinitionImportDTO> lists,
|
||||
ApiDeatlWithData apiDeatlWithData) {
|
||||
|
||||
Map<String, ApiDefinitionImportDTO> apiDateMap = lists.stream().collect(Collectors.toMap(t -> t.getMethod() + t.getPath(), t -> t));
|
||||
Map<String, ApiDefinitionImportDTO> importDataMap = importData.stream().collect(Collectors.toMap(t -> t.getMethod() + t.getPath(), t -> t));
|
||||
//判断是否重复
|
||||
List<String> orgList = apiDateMap.keySet().stream().toList();
|
||||
List<String> importList = importDataMap.keySet().stream().toList();
|
||||
//取交集数据
|
||||
List<String> sameList = importList.stream().filter(orgList::contains).toList();
|
||||
// 不同接口的数据
|
||||
List<String> differenceList = importList.stream().filter(t -> !orgList.contains(t)).toList();
|
||||
apiDeatlWithData.setSameList(sameList);
|
||||
apiDeatlWithData.setDifferenceList(differenceList);
|
||||
apiDeatlWithData.setApiDateMap(apiDateMap);
|
||||
apiDeatlWithData.setImportDataMap(importDataMap);
|
||||
}
|
||||
|
||||
public boolean dataIsSame(MsHTTPElement dbRequest, MsHTTPElement importRequest) {
|
||||
boolean same = true;
|
||||
//判断请求头是否一样
|
||||
List<Header> dbHeaders = dbRequest.getHeaders();
|
||||
List<Header> importHeaders = importRequest.getHeaders();
|
||||
if (CollectionUtils.isNotEmpty(dbHeaders) || CollectionUtils.isNotEmpty(importHeaders)) {
|
||||
List<String> dbHeaderKeys = dbHeaders.stream().map(Header::getKey).toList();
|
||||
List<String> importHeaderKeys = importHeaders.stream().map(Header::getKey).toList();
|
||||
if (!paramsIsSame(dbHeaderKeys, importHeaderKeys)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//判断请求参数是否一样 query rest body
|
||||
List<QueryParam> dbQuery = dbRequest.getQuery();
|
||||
List<QueryParam> importQuery = importRequest.getQuery();
|
||||
if (CollectionUtils.isNotEmpty(dbQuery) || CollectionUtils.isNotEmpty(importQuery)) {
|
||||
List<String> dbQueryKeys = dbQuery.stream().map(QueryParam::getKey).toList();
|
||||
List<String> importQueryKeys = importQuery.stream().map(QueryParam::getKey).toList();
|
||||
if (!paramsIsSame(dbQueryKeys, importQueryKeys)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
List<RestParam> dbRest = dbRequest.getRest();
|
||||
List<RestParam> importRest = importRequest.getRest();
|
||||
if (CollectionUtils.isNotEmpty(dbRest) || CollectionUtils.isNotEmpty(importRest)) {
|
||||
List<String> dbRestKeys = dbRest.stream().map(RestParam::getKey).toList();
|
||||
List<String> importRestKeys = importRest.stream().map(RestParam::getKey).toList();
|
||||
if (!paramsIsSame(dbRestKeys, importRestKeys)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//判断请求体是否一样
|
||||
if (dbRequest.getBody() != null || importRequest.getBody() != null) {
|
||||
//判断请求体的参数
|
||||
Body dbbody = dbRequest.getBody();
|
||||
Body importBody = importRequest.getBody();
|
||||
if (dbbody != null && importBody != null) {
|
||||
//判断null类型
|
||||
StringUtils.equals(String.valueOf(dbbody.getNoneBody()), String.valueOf(importBody.getNoneBody()));
|
||||
//判断form类型
|
||||
FormDataBody formDataBody = dbbody.getFormDataBody();
|
||||
FormDataBody importFormDataBody = importBody.getFormDataBody();
|
||||
if (ObjectUtils.isNotEmpty(formDataBody) || ObjectUtils.isNotEmpty(importFormDataBody)) {
|
||||
List<FormDataKV> fromValues = formDataBody.getFromValues();
|
||||
List<FormDataKV> importFromValues = importFormDataBody.getFromValues();
|
||||
if (CollectionUtils.isNotEmpty(fromValues) || CollectionUtils.isNotEmpty(importFromValues)) {
|
||||
List<String> dbFormKeys = fromValues.stream().map(FormDataKV::getKey).toList();
|
||||
List<String> importFormKeys = importFromValues.stream().map(FormDataKV::getKey).toList();
|
||||
if (!paramsIsSame(dbFormKeys, importFormKeys)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//判读www类型
|
||||
WWWFormBody wwwBody = dbbody.getWwwFormBody();
|
||||
WWWFormBody importWwwBody = importBody.getWwwFormBody();
|
||||
if (ObjectUtils.isNotEmpty(wwwBody) || ObjectUtils.isNotEmpty(importWwwBody)) {
|
||||
List<FormDataKV> wwwValues = wwwBody.getFromValues();
|
||||
List<FormDataKV> importWwwValues = importWwwBody.getFromValues();
|
||||
if (CollectionUtils.isNotEmpty(wwwValues) || CollectionUtils.isNotEmpty(importWwwValues)) {
|
||||
List<String> dbWwwKeys = wwwValues.stream().map(FormDataKV::getKey).toList();
|
||||
List<String> importWwwKeys = importWwwValues.stream().map(FormDataKV::getKey).toList();
|
||||
if (!paramsIsSame(dbWwwKeys, importWwwKeys)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO 判断binary类型
|
||||
|
||||
//判断raw类型
|
||||
RawBody rawBody = dbbody.getRawBody();
|
||||
RawBody importRawBody = importBody.getRawBody();
|
||||
if (ObjectUtils.isNotEmpty(rawBody) || ObjectUtils.isNotEmpty(importRawBody)) {
|
||||
return false;
|
||||
}
|
||||
//判断json类型
|
||||
JsonBody jsonBody = dbbody.getJsonBody();
|
||||
JsonBody importJsonBody = importBody.getJsonBody();
|
||||
if (ObjectUtils.isNotEmpty(jsonBody) || ObjectUtils.isNotEmpty(importJsonBody)) {
|
||||
if (StringUtils.isNotBlank(jsonBody.getJsonValue()) || StringUtils.isNotBlank(importJsonBody.getJsonValue())) {
|
||||
return false;
|
||||
}
|
||||
//判断jsonschema
|
||||
JsonSchemaItem jsonSchema = jsonBody.getJsonSchema();
|
||||
JsonSchemaItem importJsonSchema = importJsonBody.getJsonSchema();
|
||||
if (jsonSchema != null && importJsonSchema != null) {
|
||||
return jsonSchemaIsSame(jsonSchema, importJsonSchema);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return same;
|
||||
}
|
||||
|
||||
//判断jsonschema的参数是否一样
|
||||
private static boolean jsonSchemaIsSame(JsonSchemaItem jsonSchema, JsonSchemaItem importJsonSchema) {
|
||||
boolean same = true;
|
||||
if (jsonSchema == null && importJsonSchema == null) {
|
||||
return true;
|
||||
}
|
||||
if (!StringUtils.equals(jsonSchema.getType(), importJsonSchema.getType())) {
|
||||
return false;
|
||||
}
|
||||
if (StringUtils.equals(jsonSchema.getType(), PropertyConstant.OBJECT)) {
|
||||
Map<String, JsonSchemaItem> properties = jsonSchema.getProperties();
|
||||
Map<String, JsonSchemaItem> importProperties = importJsonSchema.getProperties();
|
||||
if (MapUtils.isNotEmpty(properties) || MapUtils.isNotEmpty(importProperties)) {
|
||||
List<String> dbJsonKeys = properties.keySet().stream().toList();
|
||||
List<String> importJsonKeys = importProperties.keySet().stream().toList();
|
||||
if (!paramsIsSame(dbJsonKeys, importJsonKeys)) {
|
||||
return false;
|
||||
}
|
||||
//遍历判断每个参数是否一样
|
||||
for (String key : dbJsonKeys) {
|
||||
JsonSchemaItem jsonSchemaItem = properties.get(key);
|
||||
JsonSchemaItem importJsonSchemaItem = importProperties.get(key);
|
||||
if (!jsonSchemaIsSame(jsonSchemaItem, importJsonSchemaItem)) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (StringUtils.equals(jsonSchema.getType(), PropertyConstant.ARRAY)) {
|
||||
JsonSchemaItem items = jsonSchema.getItems();
|
||||
JsonSchemaItem importItems = importJsonSchema.getItems();
|
||||
if (items != null && importItems != null) {
|
||||
if (!jsonSchemaIsSame(items, importItems)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return same;
|
||||
}
|
||||
|
||||
private static boolean paramsIsSame(List<String> dbRestKeys, List<String> importRestKeys) {
|
||||
if (dbRestKeys.size() != importRestKeys.size()) {
|
||||
return false;
|
||||
}
|
||||
//看看是否有差集
|
||||
List<String> differenceRest = dbRestKeys.stream().filter(t -> !importRestKeys.contains(t)).toList();
|
||||
return CollectionUtils.isEmpty(differenceRest);
|
||||
}
|
||||
|
||||
private Boolean getFullCoverage(Boolean fullCoverage) {
|
||||
if (fullCoverage == null) {
|
||||
fullCoverage = false;
|
||||
}
|
||||
return fullCoverage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造树结构 但是这里需要module的path
|
||||
*
|
||||
* @param projectId
|
||||
* @param protocol
|
||||
* @return
|
||||
*/
|
||||
public List<BaseTreeNode> buildTreeData(String projectId, String protocol) {
|
||||
ApiModuleRequest request = new ApiModuleRequest();
|
||||
request.setProjectId(projectId);
|
||||
request.setProtocol(protocol);
|
||||
List<BaseTreeNode> fileModuleList = extApiDefinitionModuleMapper.selectBaseByRequest(request);
|
||||
return this.buildTreeAndCountResource(fileModuleList, true, Translator.get(UNPLANNED_API));
|
||||
|
||||
}
|
||||
|
||||
public List<BaseTreeNode> buildTreeAndCountResource(List<BaseTreeNode> traverseList, boolean haveVirtualRootNode, String virtualRootName) {
|
||||
List<BaseTreeNode> baseTreeNodeList = new ArrayList<>();
|
||||
if (haveVirtualRootNode) {
|
||||
BaseTreeNode defaultNode = new BaseTreeNode(ModuleConstants.DEFAULT_NODE_ID, virtualRootName, ModuleConstants.NODE_TYPE_DEFAULT, ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||
defaultNode.setAttachInfo(Map.of(MODULE, StringUtils.join("/", defaultNode.getName())));
|
||||
baseTreeNodeList.add(defaultNode);
|
||||
}
|
||||
int lastSize = 0;
|
||||
Map<String, BaseTreeNode> baseTreeNodeMap = new HashMap<>();
|
||||
while (CollectionUtils.isNotEmpty(traverseList) && traverseList.size() != lastSize) {
|
||||
lastSize = traverseList.size();
|
||||
List<BaseTreeNode> notMatchedList = new ArrayList<>();
|
||||
for (BaseTreeNode treeNode : traverseList) {
|
||||
if (StringUtils.equalsIgnoreCase(treeNode.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
||||
BaseTreeNode node = new BaseTreeNode(treeNode.getId(), treeNode.getName(), treeNode.getType(), treeNode.getParentId());
|
||||
node.setAttachInfo(Map.of(MODULE, StringUtils.join("/", node.getName())));
|
||||
baseTreeNodeList.add(node);
|
||||
baseTreeNodeMap.put(treeNode.getId(), node);
|
||||
} else {
|
||||
if (baseTreeNodeMap.containsKey(treeNode.getParentId())) {
|
||||
BaseTreeNode node = new BaseTreeNode(treeNode.getId(), treeNode.getName(), treeNode.getType(), treeNode.getParentId());
|
||||
node.setAttachInfo(Map.of(MODULE, StringUtils.join(baseTreeNodeMap.get(treeNode.getParentId()).getAttachInfo().get(MODULE), "/", node.getName())));
|
||||
baseTreeNodeList.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
traverseList = notMatchedList;
|
||||
}
|
||||
return baseTreeNodeList;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -6,11 +6,17 @@ import io.metersphere.api.controller.result.ApiResultCode;
|
|||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImport;
|
||||
import io.metersphere.api.dto.definition.importdto.ApiDefinitionImportDTO;
|
||||
import io.metersphere.api.dto.request.ImportRequest;
|
||||
import io.metersphere.api.mapper.*;
|
||||
import io.metersphere.api.parser.ImportParser;
|
||||
import io.metersphere.api.parser.ImportParserFactory;
|
||||
import io.metersphere.api.service.ApiFileResourceService;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.project.service.ProjectService;
|
||||
import io.metersphere.sdk.constants.ApiReportStatus;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
|
@ -93,11 +99,15 @@ public class ApiDefinitionService {
|
|||
|
||||
@Resource
|
||||
private ApiDefinitionLogService apiDefinitionLogService;
|
||||
@Resource
|
||||
private ApiDefinitionImportUtilService apiDefinitionImportUtilService;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionMockService apiDefinitionMockService;
|
||||
|
||||
public List<ApiDefinitionDTO> getApiDefinitionPage(ApiDefinitionPageRequest request, String userId){
|
||||
public List<ApiDefinitionDTO> getApiDefinitionPage(ApiDefinitionPageRequest request, String userId) {
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
|
||||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
|
@ -106,7 +116,7 @@ public class ApiDefinitionService {
|
|||
return list;
|
||||
}
|
||||
|
||||
public List<ApiDefinitionDTO> getDocPage(ApiDefinitionPageRequest request, String userId){
|
||||
public List<ApiDefinitionDTO> getDocPage(ApiDefinitionPageRequest request, String userId) {
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
|
||||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
|
@ -115,7 +125,7 @@ public class ApiDefinitionService {
|
|||
return list;
|
||||
}
|
||||
|
||||
private void processApiDefinitionsDoc(List<ApiDefinitionDTO> list){
|
||||
private void processApiDefinitionsDoc(List<ApiDefinitionDTO> list) {
|
||||
Set<String> userIds = extractUserIds(list);
|
||||
Map<String, String> userMap = userLoginService.getUserNameMap(new ArrayList<>(userIds));
|
||||
|
||||
|
@ -137,7 +147,7 @@ public class ApiDefinitionService {
|
|||
});
|
||||
}
|
||||
|
||||
public ApiDefinitionDTO get(String id, String userId){
|
||||
public ApiDefinitionDTO get(String id, String userId) {
|
||||
// 1. 避免重复查询数据库,将查询结果传递给get方法
|
||||
ApiDefinition apiDefinition = checkApiDefinition(id);
|
||||
return getApiDefinitionInfo(id, userId, apiDefinition);
|
||||
|
@ -204,7 +214,7 @@ public class ApiDefinitionService {
|
|||
ApiDefinition originApiDefinition = checkApiDefinition(request.getId());
|
||||
ApiDefinition apiDefinition = new ApiDefinition();
|
||||
BeanUtils.copyBean(apiDefinition, request);
|
||||
if(request.getProtocol().equals(ModuleConstants.NODE_PROTOCOL_HTTP)){
|
||||
if (request.getProtocol().equals(ModuleConstants.NODE_PROTOCOL_HTTP)) {
|
||||
checkUpdateExist(apiDefinition);
|
||||
}
|
||||
apiDefinition.setStatus(request.getStatus());
|
||||
|
@ -243,7 +253,7 @@ public class ApiDefinitionService {
|
|||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
if (request.getType().equals("tags")) {
|
||||
handleTags(request, userId, ids);
|
||||
} else if(request.getType().equals("customs")){
|
||||
} else if (request.getType().equals("customs")) {
|
||||
// 自定义字段处理
|
||||
ApiDefinitionCustomFieldDTO customField = request.getCustomField();
|
||||
Map<String, String> customFieldMap = Collections.singletonMap(customField.getId(), customField.getValue());
|
||||
|
@ -254,7 +264,7 @@ public class ApiDefinitionService {
|
|||
apiDefinitionUpdateRequest.setId(id);
|
||||
handleUpdateCustomFields(apiDefinitionUpdateRequest, request.isAppend());
|
||||
});
|
||||
}else {
|
||||
} else {
|
||||
ApiDefinition apiDefinition = new ApiDefinition();
|
||||
BeanUtils.copyBean(apiDefinition, request);
|
||||
apiDefinition.setUpdateUser(userId);
|
||||
|
@ -347,7 +357,7 @@ public class ApiDefinitionService {
|
|||
|
||||
ApiDefinitionBlob copyApiDefinitionBlob = getApiDefinitionBlob(request.getId());
|
||||
ApiDefinitionBlob apiDefinitionBlob = new ApiDefinitionBlob();
|
||||
if(copyApiDefinitionBlob != null){
|
||||
if (copyApiDefinitionBlob != null) {
|
||||
apiDefinitionBlob.setId(apiDefinition.getId());
|
||||
apiDefinitionBlob.setRequest(copyApiDefinitionBlob.getRequest());
|
||||
apiDefinitionBlob.setResponse(copyApiDefinitionBlob.getResponse());
|
||||
|
@ -363,7 +373,7 @@ public class ApiDefinitionService {
|
|||
|
||||
public void delete(ApiDefinitionDeleteRequest request, String userId) {
|
||||
checkApiDefinition(request.getId());
|
||||
handleDeleteApiDefinition(Collections.singletonList(request.getId()),request.getDeleteAll(), request.getProjectId(), userId, false);
|
||||
handleDeleteApiDefinition(Collections.singletonList(request.getId()), request.getDeleteAll(), request.getProjectId(), userId, false);
|
||||
}
|
||||
|
||||
public void batchDelete(ApiDefinitionBatchRequest request, String userId) {
|
||||
|
@ -548,7 +558,7 @@ public class ApiDefinitionService {
|
|||
}
|
||||
|
||||
private String getCopyName(String name) {
|
||||
String copyName = "copy_" + name ;
|
||||
String copyName = "copy_" + name;
|
||||
if (copyName.length() > 255) {
|
||||
copyName = copyName.substring(0, 250) + copyName.substring(copyName.length() - 5);
|
||||
}
|
||||
|
@ -559,17 +569,17 @@ public class ApiDefinitionService {
|
|||
if (deleteAll) {
|
||||
//全部删除 进入回收站
|
||||
List<String> refIds = extApiDefinitionMapper.getRefIds(ids, false);
|
||||
if(CollectionUtils.isNotEmpty(refIds)){
|
||||
if (CollectionUtils.isNotEmpty(refIds)) {
|
||||
SubListUtils.dealForSubList(refIds, 2000, subRefIds -> {
|
||||
List<String> delApiIds = extApiDefinitionMapper.getIdsByRefId(subRefIds, false);
|
||||
SubListUtils.dealForSubList(delApiIds, 2000, subList -> {
|
||||
if(CollectionUtils.isNotEmpty(delApiIds)){
|
||||
if (CollectionUtils.isNotEmpty(delApiIds)) {
|
||||
// 删除接口相关数据到回收站
|
||||
deleteApiRelatedData(subList, userId, projectId);
|
||||
}
|
||||
});
|
||||
// 记录删除到回收站的日志, 单条注解记录
|
||||
if(isBatch){
|
||||
if (isBatch) {
|
||||
apiDefinitionLogService.batchDelLog(delApiIds, userId, projectId);
|
||||
}
|
||||
extApiDefinitionMapper.batchDeleteByRefId(subRefIds, userId, projectId);
|
||||
|
@ -583,21 +593,21 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
private void deleteAfterAction(List<ApiDefinitionVersionDTO> apiDefinitionVersions){
|
||||
apiDefinitionVersions.forEach(item->{
|
||||
clearLatestVersion(item.getRefId(),item.getProjectId());
|
||||
private void deleteAfterAction(List<ApiDefinitionVersionDTO> apiDefinitionVersions) {
|
||||
apiDefinitionVersions.forEach(item -> {
|
||||
clearLatestVersion(item.getRefId(), item.getProjectId());
|
||||
ApiDefinition latestData = getLatestData(item.getRefId(), item.getProjectId());
|
||||
updateLatestVersion(latestData.getId(),latestData.getProjectId());
|
||||
updateLatestVersion(latestData.getId(), latestData.getProjectId());
|
||||
});
|
||||
}
|
||||
|
||||
// 清除多版本最新标识
|
||||
private void clearLatestVersion(String refId, String projectId){
|
||||
private void clearLatestVersion(String refId, String projectId) {
|
||||
extApiDefinitionMapper.clearLatestVersion(refId, projectId);
|
||||
}
|
||||
|
||||
// 获取多版本最新一条数据
|
||||
private ApiDefinition getLatestData(String refId, String projectId){
|
||||
private ApiDefinition getLatestData(String refId, String projectId) {
|
||||
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
||||
apiDefinitionExample.createCriteria().andRefIdEqualTo(refId).andDeletedEqualTo(false).andProjectIdEqualTo(projectId);
|
||||
apiDefinitionExample.setOrderByClause("update_time DESC");
|
||||
|
@ -609,17 +619,17 @@ public class ApiDefinitionService {
|
|||
}
|
||||
|
||||
// 更新最新版本标识
|
||||
private void updateLatestVersion(String id, String projectId){
|
||||
private void updateLatestVersion(String id, String projectId) {
|
||||
extApiDefinitionMapper.updateLatestVersion(id, projectId);
|
||||
}
|
||||
|
||||
private void doDelete(List<String> ids, String userId, String projectId, boolean isBatch) {
|
||||
if(CollectionUtils.isNotEmpty(ids)){
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
// 需要判断是否存在多个版本问题
|
||||
ids.forEach(id -> {
|
||||
ApiDefinition apiDefinition = checkApiDefinition(id);
|
||||
// 删除的数据是否为最新版本的数据,如果是则需要查询是否有多版本数据存在,需要去除当前删除的数据,更新剩余版本数据中最近的一条数据为最新的数据
|
||||
if(apiDefinition.getLatest()){
|
||||
if (apiDefinition.getLatest()) {
|
||||
List<ApiDefinitionVersionDTO> apiDefinitionVersions = extApiDefinitionMapper.getApiDefinitionByRefId(apiDefinition.getRefId());
|
||||
if (apiDefinitionVersions.size() > 1) {
|
||||
deleteAfterAction(apiDefinitionVersions);
|
||||
|
@ -629,7 +639,7 @@ public class ApiDefinitionService {
|
|||
// 删除 case
|
||||
deleteApiRelatedData(ids, userId, projectId);
|
||||
// 记录删除到回收站的日志, 单条注解记录
|
||||
if(isBatch){
|
||||
if (isBatch) {
|
||||
apiDefinitionLogService.batchDelLog(ids, userId, projectId);
|
||||
}
|
||||
// 删除接口到回收站
|
||||
|
@ -638,10 +648,10 @@ public class ApiDefinitionService {
|
|||
|
||||
}
|
||||
|
||||
private void deleteApiRelatedData(List<String> apiIds, String userId, String projectId){
|
||||
private void deleteApiRelatedData(List<String> apiIds, String userId, String projectId) {
|
||||
// 是否存在 case 删除 case
|
||||
List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(apiIds, false);
|
||||
if(CollectionUtils.isNotEmpty(caseLists)){
|
||||
if (CollectionUtils.isNotEmpty(caseLists)) {
|
||||
List<String> caseIds = caseLists.stream().map(ApiTestCase::getId).distinct().toList();
|
||||
apiTestCaseService.batchDeleteToGc(caseIds, userId, projectId, true);
|
||||
}
|
||||
|
@ -655,7 +665,8 @@ public class ApiDefinitionService {
|
|||
// 恢复接口到接口列表
|
||||
handleRecoverApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId(), false);
|
||||
}
|
||||
public void handleRecoverApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch){
|
||||
|
||||
public void handleRecoverApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch) {
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doRecover(subList, userId, projectId, isBatch));
|
||||
}
|
||||
|
@ -663,7 +674,7 @@ public class ApiDefinitionService {
|
|||
|
||||
private void doRecover(List<String> apiIds, String userId, String projectId, boolean isBatch) {
|
||||
// 记录恢复数据之前的原数据日志,单条通过注解记录日志
|
||||
if(isBatch){
|
||||
if (isBatch) {
|
||||
apiDefinitionLogService.batchRecoverLog(apiIds, userId, projectId);
|
||||
}
|
||||
extApiDefinitionMapper.batchRecoverById(apiIds, userId, projectId);
|
||||
|
@ -693,7 +704,7 @@ public class ApiDefinitionService {
|
|||
}
|
||||
|
||||
private void handleModule(List<String> updateApiIds) {
|
||||
if(!updateApiIds.isEmpty()){
|
||||
if (!updateApiIds.isEmpty()) {
|
||||
ApiDefinition updateApiDefinition = new ApiDefinition();
|
||||
updateApiDefinition.setModuleId(ModuleConstants.DEFAULT_NODE_ID);
|
||||
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
||||
|
@ -715,13 +726,14 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
private void recoverApiRelatedData(List<String> apiIds, String userId, String projectId){
|
||||
private void recoverApiRelatedData(List<String> apiIds, String userId, String projectId) {
|
||||
// 是否存在 case 恢复 case
|
||||
List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(apiIds, true);
|
||||
if(CollectionUtils.isNotEmpty(caseLists)) {
|
||||
if (CollectionUtils.isNotEmpty(caseLists)) {
|
||||
apiTestCaseService.batchRecover(caseLists, userId, projectId);
|
||||
}
|
||||
}
|
||||
|
||||
public void trashDel(ApiDefinitionDeleteRequest request, String userId) {
|
||||
handleTrashDelApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId(), false);
|
||||
}
|
||||
|
@ -740,14 +752,14 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleTrashDelApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch){
|
||||
private void handleTrashDelApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch) {
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doTrashDel(subList, userId, projectId, isBatch));
|
||||
}
|
||||
}
|
||||
|
||||
private void doTrashDel(List<String> ids, String userId, String projectId, boolean isBatch){
|
||||
if(CollectionUtils.isNotEmpty(ids)){
|
||||
private void doTrashDel(List<String> ids, String userId, String projectId, boolean isBatch) {
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
// 删除上传的文件
|
||||
ids.forEach(id -> {
|
||||
String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, id);
|
||||
|
@ -762,7 +774,7 @@ public class ApiDefinitionService {
|
|||
trashDelApiRelatedData(ids, userId, projectId);
|
||||
|
||||
// 记录批量删除日志,单条删除通过注解记录
|
||||
if(isBatch){
|
||||
if (isBatch) {
|
||||
apiDefinitionLogService.batchTrashDelLog(ids, userId, projectId);
|
||||
}
|
||||
// 删除接口
|
||||
|
@ -773,13 +785,14 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
private void trashDelApiRelatedData(List<String> apiIds, String userId, String projectId){
|
||||
private void trashDelApiRelatedData(List<String> apiIds, String userId, String projectId) {
|
||||
// 是否存在 case 删除 case
|
||||
List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(apiIds, true);
|
||||
if(CollectionUtils.isNotEmpty(caseLists)) {
|
||||
if (CollectionUtils.isNotEmpty(caseLists)) {
|
||||
List<String> caseIds = caseLists.stream().map(ApiTestCase::getId).distinct().toList();
|
||||
// case 批量删除回收站
|
||||
apiTestCaseService.deleteResourceByIds(caseIds, projectId, userId);
|
||||
|
||||
}
|
||||
// 删除 mock
|
||||
apiDefinitionMockService.deleteByApiIds(apiIds, userId);
|
||||
|
@ -856,4 +869,45 @@ public class ApiDefinitionService {
|
|||
return apiDefinitionDocDTO;
|
||||
}
|
||||
|
||||
public ApiDefinitionImport apiTestImport(MultipartFile file, ImportRequest request) {
|
||||
if (file != null) {
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
if (StringUtils.isNotBlank(originalFilename)) {
|
||||
String suffixName = originalFilename.substring(originalFilename.indexOf(".") + 1);
|
||||
apiDefinitionImportUtilService.checkFileSuffixName(request, suffixName);
|
||||
}
|
||||
}
|
||||
ImportParser<?> runService = ImportParserFactory.getImportParser(request.getPlatform());
|
||||
ApiDefinitionImport apiImport = null;
|
||||
if (StringUtils.equals(request.getType(), "SCHEDULE")) {
|
||||
request.setProtocol("HTTP");
|
||||
}
|
||||
try {
|
||||
apiImport = (ApiDefinitionImport) Objects.requireNonNull(runService).parse(file == null ? null : file.getInputStream(), request);
|
||||
//TODO 处理mock数据
|
||||
// 发送通知
|
||||
} catch (Exception e) {
|
||||
// TODO 发送通知
|
||||
LogUtils.error(e.getMessage(), e);
|
||||
throw new MSException(Translator.get("parse_data_error"));
|
||||
}
|
||||
|
||||
try {
|
||||
apiDefinitionImportUtilService.importApi(request, apiImport);
|
||||
apiDefinitionMapper.selectByExample(new ApiDefinitionExample());
|
||||
if (CollectionUtils.isNotEmpty(apiImport.getData())) {
|
||||
List<String> names = apiImport.getData().stream().map(ApiDefinitionImportDTO::getName).collect(Collectors.toList());
|
||||
request.setName(String.join(",", names));
|
||||
List<String> ids = apiImport.getData().stream().map(ApiDefinitionImportDTO::getId).collect(Collectors.toList());
|
||||
request.setId(JSON.toJSONString(ids));
|
||||
}
|
||||
// 发送通知
|
||||
//apiDefinitionImportUtilService.sendImportNotice(request, apiImportSendNoticeDTOS, project);
|
||||
} catch (Exception e) {
|
||||
//apiDefinitionImportUtilService.sendFailMessage(request, project);
|
||||
LogUtils.error(e);
|
||||
throw new MSException(Translator.get("user_import_format_wrong"));
|
||||
}
|
||||
return apiImport;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.metersphere.api.constants.ApiDefinitionStatus;
|
|||
import io.metersphere.api.controller.result.ApiResultCode;
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.request.ImportRequest;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.mapper.*;
|
||||
import io.metersphere.api.model.CheckLogModel;
|
||||
|
@ -18,6 +19,7 @@ import io.metersphere.project.service.FileAssociationService;
|
|||
import io.metersphere.project.service.FileMetadataService;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.constants.SessionConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.file.FileCenter;
|
||||
import io.metersphere.sdk.file.FileRequest;
|
||||
|
@ -34,17 +36,30 @@ import org.apache.commons.lang3.StringUtils;
|
|||
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.HttpHeaders;
|
||||
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.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@AutoConfigureMockMvc
|
||||
public class ApiDefinitionControllerTests extends BaseTest {
|
||||
|
@ -226,7 +241,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
BeanUtils.copyBean(copyApiDefinition, request);
|
||||
Assertions.assertEquals(apiDefinition, copyApiDefinition);
|
||||
ApiDataUtils.setResolver(MsHTTPElement.class);
|
||||
if(apiDefinitionBlob != null){
|
||||
if (apiDefinitionBlob != null) {
|
||||
Assertions.assertEquals(msHttpElement, ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), AbstractMsTestElement.class));
|
||||
}
|
||||
return apiDefinition;
|
||||
|
@ -236,7 +251,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
@Order(2)
|
||||
@Sql(scripts = {"/dml/init_api_definition.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
public void get() throws Exception {
|
||||
if(apiDefinition == null){
|
||||
if (apiDefinition == null) {
|
||||
apiDefinition = apiDefinitionMapper.selectByPrimaryKey("1001");
|
||||
}
|
||||
// @@请求成功
|
||||
|
@ -252,11 +267,11 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
copyApiDefinitionDTO.setFollow(CollectionUtils.isNotEmpty(followers));
|
||||
|
||||
List<ApiDefinitionCustomFieldDTO> customFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(Collections.singletonList(apiDefinition.getId()), apiDefinition.getProjectId());
|
||||
if(!customFields.isEmpty()) {
|
||||
if (!customFields.isEmpty()) {
|
||||
Map<String, List<ApiDefinitionCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(ApiDefinitionCustomFieldDTO::getApiId));
|
||||
copyApiDefinitionDTO.setCustomFields(customFieldMap.get(apiDefinition.getId()));
|
||||
}
|
||||
if(apiDefinitionBlob != null){
|
||||
if (apiDefinitionBlob != null) {
|
||||
copyApiDefinitionDTO.setRequest(ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), AbstractMsTestElement.class));
|
||||
copyApiDefinitionDTO.setResponse(ApiDataUtils.parseArray(new String(apiDefinitionBlob.getResponse()), HttpResponse.class));
|
||||
}
|
||||
|
@ -273,7 +288,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
@Sql(scripts = {"/dml/init_api_definition.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
public void testUpdate() throws Exception {
|
||||
LogUtils.info("update api test");
|
||||
if(apiDefinition == null){
|
||||
if (apiDefinition == null) {
|
||||
apiDefinition = apiDefinitionMapper.selectByPrimaryKey("1001");
|
||||
}
|
||||
ApiDefinitionUpdateRequest request = new ApiDefinitionUpdateRequest();
|
||||
|
@ -382,6 +397,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
|
||||
/**
|
||||
* 校验上传的文件
|
||||
*
|
||||
* @param id
|
||||
* @param fileIds 全部的文件ID
|
||||
*/
|
||||
|
@ -411,6 +427,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
|
||||
/**
|
||||
* 校验上传的文件
|
||||
*
|
||||
* @param id
|
||||
* @param fileIds 全部的文件ID
|
||||
*/
|
||||
|
@ -430,25 +447,25 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
LogUtils.info("batch update api test");
|
||||
ApiDefinitionBatchUpdateRequest apiDefinitionBatchUpdateRequest = new ApiDefinitionBatchUpdateRequest();
|
||||
apiDefinitionBatchUpdateRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1001","1002","1005"));
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1001", "1002", "1005"));
|
||||
apiDefinitionBatchUpdateRequest.setExcludeIds(List.of("1005"));
|
||||
apiDefinitionBatchUpdateRequest.setSelectAll(false);
|
||||
apiDefinitionBatchUpdateRequest.setType("tags");
|
||||
// 修改标签,追加
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1001","1002"));
|
||||
apiDefinitionBatchUpdateRequest.setTags(new LinkedHashSet<>(List.of("tag-append","tag-append1")));
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1001", "1002"));
|
||||
apiDefinitionBatchUpdateRequest.setTags(new LinkedHashSet<>(List.of("tag-append", "tag-append1")));
|
||||
apiDefinitionBatchUpdateRequest.setAppend(true);
|
||||
this.requestPostWithOk(BATCH_UPDATE, apiDefinitionBatchUpdateRequest);
|
||||
assertBatchUpdateApiDefinition(apiDefinitionBatchUpdateRequest, List.of("1001","1002"));
|
||||
assertBatchUpdateApiDefinition(apiDefinitionBatchUpdateRequest, List.of("1001", "1002"));
|
||||
// 修改标签,覆盖
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1003","1004"));
|
||||
apiDefinitionBatchUpdateRequest.setTags(new LinkedHashSet<>(List.of("tag-append","tag-append1")));
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1003", "1004"));
|
||||
apiDefinitionBatchUpdateRequest.setTags(new LinkedHashSet<>(List.of("tag-append", "tag-append1")));
|
||||
apiDefinitionBatchUpdateRequest.setAppend(false);
|
||||
this.requestPostWithOk(BATCH_UPDATE, apiDefinitionBatchUpdateRequest);
|
||||
assertBatchUpdateApiDefinition(apiDefinitionBatchUpdateRequest, List.of("1003","1004"));
|
||||
assertBatchUpdateApiDefinition(apiDefinitionBatchUpdateRequest, List.of("1003", "1004"));
|
||||
// 自定义字段追加
|
||||
apiDefinitionBatchUpdateRequest.setType("customs");
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1002","1003","1004"));
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1002", "1003", "1004"));
|
||||
ApiDefinitionCustomFieldDTO field = new ApiDefinitionCustomFieldDTO();
|
||||
field.setId("test_field");
|
||||
field.setValue(JSON.toJSONString(List.of("test1-batch")));
|
||||
|
@ -500,16 +517,16 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
apiDefinitionExample.createCriteria().andIdIn(ids);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(apiDefinitionExample);
|
||||
apiDefinitions.forEach(item -> {
|
||||
if(request.getStatus() != null){
|
||||
if (request.getStatus() != null) {
|
||||
Assertions.assertEquals(item.getStatus(), request.getStatus());
|
||||
}
|
||||
if(request.getMethod() != null){
|
||||
if (request.getMethod() != null) {
|
||||
Assertions.assertEquals(item.getMethod(), request.getMethod());
|
||||
}
|
||||
if(request.getVersionId() != null) {
|
||||
if (request.getVersionId() != null) {
|
||||
Assertions.assertEquals(item.getVersionId(), request.getVersionId());
|
||||
}
|
||||
if(request.getTags() != null) {
|
||||
if (request.getTags() != null) {
|
||||
if (request.isAppend()) {
|
||||
Assertions.assertTrue(JSON.parseArray(item.getTags(), String.class).containsAll(request.getTags()));
|
||||
} else {
|
||||
|
@ -530,7 +547,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
// @数据验证
|
||||
List<ApiFileResource> sourceFiles = apiFileResourceService.getByResourceId(apiDefinition.getId());
|
||||
List<ApiFileResource> copyFiles = apiFileResourceService.getByResourceId(resultData.getId());
|
||||
if(!sourceFiles.isEmpty() && !copyFiles.isEmpty()){
|
||||
if (!sourceFiles.isEmpty() && !copyFiles.isEmpty()) {
|
||||
Assertions.assertEquals(sourceFiles.size(), copyFiles.size());
|
||||
}
|
||||
Assertions.assertTrue(resultData.getName().contains("copy_"));
|
||||
|
@ -558,7 +575,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
|
||||
// 移动选中
|
||||
request.setSelectIds(List.of("1001","1002","1005"));
|
||||
request.setSelectIds(List.of("1001", "1002", "1005"));
|
||||
request.setExcludeIds(List.of("1005"));
|
||||
request.setDeleteAll(false);
|
||||
request.setSelectAll(false);
|
||||
|
@ -655,7 +672,8 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
case "FILTER" -> configureFilterSearch(request);
|
||||
case "COMBINE" -> configureCombineSearch(request);
|
||||
case "DELETED" -> configureDeleteSearch(request);
|
||||
default -> {}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(url, request);
|
||||
|
@ -759,7 +777,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
ApiDefinitionDocDTO copyApiDefinitionDocDTO = new ApiDefinitionDocDTO();
|
||||
ApiDefinitionDTO copyApiDefinitionDTO = BeanUtils.copyBean(new ApiDefinitionDTO(), apiDefinition);
|
||||
ApiDefinitionBlob apiDefinitionBlob = apiDefinitionBlobMapper.selectByPrimaryKey(apiDefinition.getId());
|
||||
if(apiDefinitionBlob != null){
|
||||
if (apiDefinitionBlob != null) {
|
||||
copyApiDefinitionDTO.setRequest(ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), AbstractMsTestElement.class));
|
||||
copyApiDefinitionDTO.setResponse(ApiDataUtils.parseArray(new String(apiDefinitionBlob.getResponse()), HttpResponse.class));
|
||||
}
|
||||
|
@ -784,10 +802,10 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
// 校验数据是否正确
|
||||
ApiDefinitionDocDTO copyModuleApiDefinitionDocDTO = new ApiDefinitionDocDTO();
|
||||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.listDoc(request);
|
||||
if(null != list){
|
||||
if (null != list) {
|
||||
ApiDefinitionDTO first = list.stream().findFirst().orElseThrow(() -> new MSException(ApiResultCode.API_DEFINITION_NOT_EXIST));
|
||||
ApiDefinitionBlob moduleApiDefinitionBlob = apiDefinitionBlobMapper.selectByPrimaryKey(first.getId());
|
||||
if(moduleApiDefinitionBlob != null){
|
||||
if (moduleApiDefinitionBlob != null) {
|
||||
first.setRequest(ApiDataUtils.parseObject(new String(moduleApiDefinitionBlob.getRequest()), AbstractMsTestElement.class));
|
||||
first.setResponse(ApiDataUtils.parseArray(new String(moduleApiDefinitionBlob.getResponse()), HttpResponse.class));
|
||||
}
|
||||
|
@ -816,14 +834,14 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
// 校验数据是否正确
|
||||
ApiDefinitionDocDTO copyAllApiDefinitionDocDTO = new ApiDefinitionDocDTO();
|
||||
List<ApiDefinitionDTO> allList = extApiDefinitionMapper.listDoc(request);
|
||||
if(null != allList){
|
||||
if (null != allList) {
|
||||
ApiDefinitionDTO info = allList.stream().findFirst().orElseThrow(() -> new MSException(ApiResultCode.API_DEFINITION_NOT_EXIST));
|
||||
ApiDefinitionBlob allApiDefinitionBlob = apiDefinitionBlobMapper.selectByPrimaryKey(info.getId());
|
||||
if(allApiDefinitionBlob != null){
|
||||
if (allApiDefinitionBlob != null) {
|
||||
info.setRequest(ApiDataUtils.parseObject(new String(allApiDefinitionBlob.getRequest()), AbstractMsTestElement.class));
|
||||
info.setResponse(ApiDataUtils.parseArray(new String(allApiDefinitionBlob.getResponse()), HttpResponse.class));
|
||||
}
|
||||
if(StringUtils.isBlank(copyAllApiDefinitionDocDTO.getDocTitle())){
|
||||
if (StringUtils.isBlank(copyAllApiDefinitionDocDTO.getDocTitle())) {
|
||||
copyAllApiDefinitionDocDTO.setDocTitle(Translator.get(ALL_API));
|
||||
}
|
||||
copyAllApiDefinitionDocDTO.setType(ApiDefinitionDocType.ALL.name());
|
||||
|
@ -853,10 +871,10 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
// 校验数据是否正确
|
||||
ApiDefinitionDocDTO copyModuleApiDefinitionDocDTO = new ApiDefinitionDocDTO();
|
||||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.listDoc(request);
|
||||
if(null != list){
|
||||
if (null != list) {
|
||||
ApiDefinitionDTO first = list.stream().findFirst().orElseThrow(() -> new MSException(ApiResultCode.API_DEFINITION_NOT_EXIST));
|
||||
ApiDefinitionBlob moduleApiDefinitionBlob = apiDefinitionBlobMapper.selectByPrimaryKey(first.getId());
|
||||
if(moduleApiDefinitionBlob != null){
|
||||
if (moduleApiDefinitionBlob != null) {
|
||||
first.setRequest(ApiDataUtils.parseObject(new String(moduleApiDefinitionBlob.getRequest()), AbstractMsTestElement.class));
|
||||
first.setResponse(ApiDataUtils.parseArray(new String(moduleApiDefinitionBlob.getResponse()), HttpResponse.class));
|
||||
}
|
||||
|
@ -901,22 +919,22 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
MvcResult mvcResult = this.requestGetWithOk(VERSION + apiDefinitionDeleteRequest.getId()).andReturn();
|
||||
ApiDataUtils.setResolver(MsHTTPElement.class);
|
||||
List<ApiDefinitionVersionDTO> apiDefinitionVersionDTO = getResultDataArray(mvcResult, ApiDefinitionVersionDTO.class);
|
||||
if(!apiDefinitionVersionDTO.isEmpty()){
|
||||
if (!apiDefinitionVersionDTO.isEmpty()) {
|
||||
this.requestPostWithOkAndReturn(DELETE, apiDefinitionDeleteRequest);
|
||||
// 效验数据
|
||||
// 删除的数据为最新版本需要更新最近一条数据为最新数据
|
||||
if(delApiDefinition.getLatest()){
|
||||
if (delApiDefinition.getLatest()) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andRefIdEqualTo(delApiDefinition.getRefId()).andDeletedEqualTo(false).andProjectIdEqualTo(delApiDefinition.getProjectId());
|
||||
example.setOrderByClause("update_time DESC");
|
||||
ApiDefinition updateApiDefinition = apiDefinitionMapper.selectByExample(example).stream().findFirst().orElse(null);
|
||||
if(updateApiDefinition != null) {
|
||||
if (updateApiDefinition != null) {
|
||||
Assertions.assertTrue(updateApiDefinition.getLatest());
|
||||
Assertions.assertFalse(updateApiDefinition.getDeleted());
|
||||
}
|
||||
}
|
||||
ApiDefinition delApiDefinitionInfo = apiDefinitionMapper.selectByPrimaryKey(apiDefinitionDeleteRequest.getId());
|
||||
if(delApiDefinitionInfo != null){
|
||||
if (delApiDefinitionInfo != null) {
|
||||
Assertions.assertTrue(delApiDefinitionInfo.getDeleted());
|
||||
Assertions.assertEquals("admin", delApiDefinitionInfo.getDeleteUser());
|
||||
Assertions.assertNotNull(delApiDefinitionInfo.getDeleteTime());
|
||||
|
@ -933,7 +951,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
||||
apiDefinitionExample.createCriteria().andIdIn(ids);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(apiDefinitionExample);
|
||||
if(CollectionUtils.isNotEmpty(apiDefinitions)){
|
||||
if (CollectionUtils.isNotEmpty(apiDefinitions)) {
|
||||
apiDefinitions.forEach(item -> {
|
||||
Assertions.assertTrue(item.getDeleted());
|
||||
Assertions.assertEquals("admin", item.getDeleteUser());
|
||||
|
@ -1002,16 +1020,16 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
|
||||
// @查询恢复的数据版本是否为默认版本
|
||||
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(apiDefinition.getProjectId());
|
||||
if(defaultVersion.equals(apiDefinition.getVersionId())){
|
||||
if (defaultVersion.equals(apiDefinition.getVersionId())) {
|
||||
// 需要处理此数据为最新标识
|
||||
// 此数据不为最新版本,验证是否更新为最新版本
|
||||
if(!apiDefinition.getLatest()){
|
||||
if (!apiDefinition.getLatest()) {
|
||||
Assertions.assertTrue(apiDefinitionInfo.getLatest());
|
||||
}
|
||||
}
|
||||
// 效验 关联数据
|
||||
List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(Collections.singletonList(apiDefinition.getId()), false);
|
||||
if(!caseLists.isEmpty()) {
|
||||
if (!caseLists.isEmpty()) {
|
||||
caseLists.forEach(item -> {
|
||||
Assertions.assertNull(item.getDeleteUser());
|
||||
Assertions.assertNull(item.getDeleteTime());
|
||||
|
@ -1035,7 +1053,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
ApiDefinitionBatchRequest request = new ApiDefinitionBatchRequest();
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
// 恢复选中
|
||||
request.setSelectIds(List.of("1002","1004","1005"));
|
||||
request.setSelectIds(List.of("1002", "1004", "1005"));
|
||||
request.setExcludeIds(List.of("1005"));
|
||||
request.setSelectAll(false);
|
||||
this.requestPostWithOk(BATCH_RESTORE, request);
|
||||
|
@ -1044,14 +1062,14 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
||||
apiDefinitionExample.createCriteria().andIdIn(request.getSelectIds());
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(apiDefinitionExample);
|
||||
if(!apiDefinitions.isEmpty()){
|
||||
if (!apiDefinitions.isEmpty()) {
|
||||
apiDefinitions.forEach(item -> {
|
||||
Assertions.assertFalse(item.getDeleted());
|
||||
Assertions.assertNull(item.getDeleteUser());
|
||||
Assertions.assertNull(item.getDeleteTime());
|
||||
// 效验 关联数据
|
||||
List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(Collections.singletonList(item.getId()), false);
|
||||
if(!caseLists.isEmpty()) {
|
||||
if (!caseLists.isEmpty()) {
|
||||
caseLists.forEach(test -> {
|
||||
Assertions.assertNull(test.getDeleteUser());
|
||||
Assertions.assertNull(test.getDeleteTime());
|
||||
|
@ -1081,7 +1099,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
public void testTrashDel() throws Exception {
|
||||
LogUtils.info("trashDel api test");
|
||||
apiDefinition = apiDefinitionMapper.selectByPrimaryKey("1001");
|
||||
if(!apiDefinition.getDeleted()){
|
||||
if (!apiDefinition.getDeleted()) {
|
||||
ApiDefinitionDeleteRequest apiDefinitionDeleteRequest = new ApiDefinitionDeleteRequest();
|
||||
apiDefinitionDeleteRequest.setId(apiDefinition.getId());
|
||||
apiDefinitionDeleteRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
|
@ -1146,7 +1164,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
|
||||
// @@校验日志
|
||||
apiDefinition = apiDefinitionMapper.selectByPrimaryKey("1006");
|
||||
if(!apiDefinition.getDeleted()){
|
||||
if (!apiDefinition.getDeleted()) {
|
||||
ApiDefinitionDeleteRequest apiDefinitionDeleteRequest = new ApiDefinitionDeleteRequest();
|
||||
apiDefinitionDeleteRequest.setId(apiDefinition.getId());
|
||||
apiDefinitionDeleteRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
|
@ -1188,5 +1206,123 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(102)
|
||||
public void testImport() throws Exception {
|
||||
LogUtils.info("import api test");
|
||||
ApiDefinitionModule apiDefinitionModule = new ApiDefinitionModule();
|
||||
apiDefinitionModule.setId("test-import");
|
||||
apiDefinitionModule.setName("test-import");
|
||||
apiDefinitionModule.setProjectId(DEFAULT_PROJECT_ID);
|
||||
apiDefinitionModule.setCreateUser("admin");
|
||||
apiDefinitionModule.setUpdateUser("admin");
|
||||
apiDefinitionModule.setPos(1L);
|
||||
apiDefinitionModule.setCreateTime(System.currentTimeMillis());
|
||||
apiDefinitionModule.setUpdateTime(System.currentTimeMillis());
|
||||
apiDefinitionModuleMapper.insertSelective(apiDefinitionModule);
|
||||
ImportRequest request = new ImportRequest();
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setPlatform("Swagger3");
|
||||
request.setCoverData(true);
|
||||
request.setCoverModule(true);
|
||||
request.setModuleId(apiDefinitionModule.getId());
|
||||
request.setProtocol("HTTP");
|
||||
request.setUserId("admin");
|
||||
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
paramMap.add("request", JSON.toJSONString(request));
|
||||
FileInputStream inputStream = new FileInputStream(new File(
|
||||
this.getClass().getClassLoader().getResource("file/openapi.json")
|
||||
.getPath()));
|
||||
|
||||
MockMultipartFile file = new MockMultipartFile("file", "openapi.json", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
|
||||
paramMap.add("file", file);
|
||||
this.requestMultipartWithOkAndReturn("/api/definition/import", paramMap);
|
||||
request.setCoverModule(false);
|
||||
request.setCoverData(false);
|
||||
this.requestMultipartWithOkAndReturn("/api/definition/import", paramMap);
|
||||
paramMap.clear();
|
||||
inputStream = new FileInputStream(new File(
|
||||
this.getClass().getClassLoader().getResource("file/openapi1.json")
|
||||
.getPath()));
|
||||
file = new MockMultipartFile("file", "openapi1.json", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
|
||||
paramMap.add("file", file);
|
||||
request.setCoverModule(true);
|
||||
request.setCoverData(true);
|
||||
paramMap.add("request", JSON.toJSONString(request));
|
||||
this.requestMultipartWithOkAndReturn("/api/definition/import", paramMap);
|
||||
paramMap.clear();
|
||||
inputStream = new FileInputStream(new File(
|
||||
this.getClass().getClassLoader().getResource("file/openapi2.json")
|
||||
.getPath()));
|
||||
file = new MockMultipartFile("file", "openapi2.json", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
|
||||
paramMap.add("file", file);
|
||||
request.setCoverModule(false);
|
||||
request.setCoverData(false);
|
||||
paramMap.add("request", JSON.toJSONString(request));
|
||||
this.requestMultipart("/api/definition/import", paramMap, status().is5xxServerError());
|
||||
|
||||
paramMap.clear();
|
||||
inputStream = new FileInputStream(new File(
|
||||
this.getClass().getClassLoader().getResource("file/openapi3.json")
|
||||
.getPath()));
|
||||
file = new MockMultipartFile("file", "openapi3.json", MediaType.APPLICATION_OCTET_STREAM_VALUE, inputStream);
|
||||
paramMap.add("file", file);
|
||||
request.setCoverModule(false);
|
||||
request.setCoverData(false);
|
||||
paramMap.add("request", JSON.toJSONString(request));
|
||||
this.requestMultipartWithOkAndReturn("/api/definition/import", paramMap);
|
||||
paramMap.clear();
|
||||
|
||||
paramMap.add("file", file);
|
||||
request.setCoverModule(false);
|
||||
request.setCoverData(false);
|
||||
request.setSwaggerUrl("http://localhost:8080/v2/api-docs");
|
||||
paramMap.add("request", JSON.toJSONString(request));
|
||||
this.requestMultipart("/api/definition/import", paramMap, status().is5xxServerError());
|
||||
|
||||
}
|
||||
|
||||
protected MvcResult requestMultipart(String url, MultiValueMap<String, Object> paramMap, ResultMatcher resultMatcher) throws Exception {
|
||||
MockMultipartHttpServletRequestBuilder requestBuilder = getMultipartRequestBuilderWithParam(url, paramMap);
|
||||
MockHttpServletRequestBuilder header = requestBuilder
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.header(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN");
|
||||
return mockMvc.perform(header)
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(resultMatcher).andReturn();
|
||||
}
|
||||
|
||||
private MockMultipartHttpServletRequestBuilder getMultipartRequestBuilderWithParam(String url, MultiValueMap<String, Object> paramMap) {
|
||||
MockMultipartHttpServletRequestBuilder requestBuilder =
|
||||
MockMvcRequestBuilders.multipart(getBasePath() + url);
|
||||
paramMap.forEach((key, value) -> {
|
||||
List list = value;
|
||||
for (Object o : list) {
|
||||
if (o instanceof List fileList) {
|
||||
fileList.forEach(o1 -> {
|
||||
if (o1 instanceof MockMultipartFile mockMultipartFile) {
|
||||
try {
|
||||
MockMultipartFile mockMultipartFile1 = null;
|
||||
mockMultipartFile1 = new MockMultipartFile(key, mockMultipartFile.getOriginalFilename(),
|
||||
MediaType.APPLICATION_OCTET_STREAM_VALUE, mockMultipartFile.getBytes());
|
||||
requestBuilder.file(mockMultipartFile1);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
MockMultipartFile multipartFile = null;
|
||||
multipartFile = new MockMultipartFile(key, null,
|
||||
MediaType.APPLICATION_JSON_VALUE, o.toString().getBytes());
|
||||
requestBuilder.file(multipartFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
return requestBuilder;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import io.metersphere.api.dto.request.processors.extract.JSONPathExtract;
|
|||
import io.metersphere.api.dto.request.processors.extract.RegexExtract;
|
||||
import io.metersphere.api.dto.request.processors.extract.ResultMatchingExtract;
|
||||
import io.metersphere.api.dto.request.processors.extract.XPathExtract;
|
||||
import io.metersphere.api.dto.schema.JsonSchemaItem;
|
||||
import io.metersphere.api.parser.TestElementParser;
|
||||
import io.metersphere.api.parser.TestElementParserFactory;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
|
@ -76,7 +77,7 @@ public class MsHTTPElementTest {
|
|||
body.setWwwFormBody(wwwFormBody);
|
||||
|
||||
JsonBody jsonBody = new JsonBody();
|
||||
jsonBody.setJsonSchema("{}");
|
||||
jsonBody.setJsonSchema(new JsonSchemaItem());
|
||||
jsonBody.setEnableJsonSchema(false);
|
||||
body.setJsonBody(jsonBody);
|
||||
|
||||
|
|
|
@ -16,12 +16,6 @@ import java.util.Objects;
|
|||
@AutoConfigureMockMvc
|
||||
public class ParserTests {
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
public void testImportParserSwagger() throws Exception {
|
||||
Objects.requireNonNull(ImportParserFactory.getImportParser(ApiImportPlatform.Swagger3.name())).parse(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void testImportParserPostman() throws Exception {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,772 @@
|
|||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "合规问询",
|
||||
"version": "1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/tasks/start/enquiry": {
|
||||
"post": {
|
||||
"summary": "开始问询",
|
||||
"description": "**Request parameters**\n\n| 参数 | 必须 | 类型 | 说明 |\n|:---|:---|:---|:---|\n|customer_ids|是|list| 问询用户 customer_id 列表|\n|user_ids|是|list| 问询用户 user_ids 列表(会查询用户的Omnibus账户)|\n|name|是|String|问询名称|\n|type|是|String| 问询类型 CDD ST ONGOING TM|\n|reason|是|String| 问询原因(需要把用户勾选的原因拼起来)|\n|remark|是|String| 备注|\n|restrict|是|boolean| 是否清算 true:是|\n|content|是|json| 问询内容|\n|pre\\_answer_id|否|String| 上次问询answer_id|\n|pre_status|否|String| 上次问询结果,UNSUBMIT,SUCCESS,REJECTED|\n\n**Response fields**\n\n\n\n\n\n```json\n\n\n{\n \"status\": \"ok\",\n \"msg\": \"ok\",\n \"timestamp\": 1606477343900\n}\n\n\n\n```\n",
|
||||
"operationId": "post--tasks-start-enquiry",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"customer_ids": {
|
||||
"type": "array",
|
||||
"x-stoplight": {
|
||||
"id": "kbjft55jellci"
|
||||
},
|
||||
"description": "问询客户Id列表,与user_ids二选一",
|
||||
"items": {
|
||||
"x-stoplight": {
|
||||
"id": "48rmyqxcgaenj"
|
||||
},
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"user_ids": {
|
||||
"type": "array",
|
||||
"x-stoplight": {
|
||||
"id": "k2vz6vj9bcb1i"
|
||||
},
|
||||
"description": "问询用户Id列表,与customer_ids二选一",
|
||||
"items": {
|
||||
"x-stoplight": {
|
||||
"id": "sv3rgfiwghwlz"
|
||||
},
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "k0e99u1kks179"
|
||||
},
|
||||
"description": "问询名称"
|
||||
},
|
||||
"pre_answer_id": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "7fg4vu00xa2xa"
|
||||
},
|
||||
"description": "前一个问询id"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "ejbuowi29ntqm"
|
||||
}
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "mykt2dh4d7c78"
|
||||
}
|
||||
},
|
||||
"pre_answer_status": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "nok8zrvkugh85"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"type": "object",
|
||||
"x-stoplight": {
|
||||
"id": "pbk4zgl8aq3vk"
|
||||
},
|
||||
"description": "问询内容",
|
||||
"required": [
|
||||
"questions"
|
||||
],
|
||||
"properties": {
|
||||
"questions": {
|
||||
"type": "array",
|
||||
"x-stoplight": {
|
||||
"id": "5a0g6bpavd3p9"
|
||||
},
|
||||
"items": {
|
||||
"x-stoplight": {
|
||||
"id": "tzanfcdtus3zk"
|
||||
},
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "dadmpn80vj277"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"type": "object",
|
||||
"x-stoplight": {
|
||||
"id": "vxxr5fco5x5qd"
|
||||
},
|
||||
"properties": {
|
||||
"en_US": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "ynddq0wrd59yl"
|
||||
}
|
||||
},
|
||||
"zh_TW": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "gq1soegk1bv1z"
|
||||
}
|
||||
},
|
||||
"zh_CN": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "skxaai7a1tgbn"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"title"
|
||||
]
|
||||
}
|
||||
},
|
||||
"": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "lyxhp63oqftol"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"reason",
|
||||
"content"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
},
|
||||
"responses": {},
|
||||
"security": [],
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tasks/count/enquire": {
|
||||
"get": {
|
||||
"summary": "任务计数",
|
||||
"description": "**权限** \npage:accounts:enquiry\n\n\n**Request parameters**\n\n| 参数 | 必须 | 类型 | 说明 |\n|:---|:---|:---|:---|\n|target|是|String| ACCOUNT|\n\n\n**Response fields**\n\n\n```json\n\n\n{\n \"status\": \"ok\",\n \"msg\": \"ok\",\n \"data\": {\n \"ENQUIRY_CDD\": 10,\n \"ENQUIRY_ECDD\": 140,\n \"ENQUIRY_TM\": 20,\n \"ENQUIRY_ST\": 1,\n \"MINE\": 11\n },\n \"timestamp\": 1620908408415\n}\n\n\n```\n",
|
||||
"operationId": "get--tasks-count-enquire",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "8ef7olao3cjcr"
|
||||
}
|
||||
},
|
||||
"msg": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "cxmgh6dzrif3a"
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"x-stoplight": {
|
||||
"id": "809qtdhwnaaua"
|
||||
},
|
||||
"properties": {
|
||||
"ENQUIRY_CDD": {
|
||||
"type": "integer",
|
||||
"x-stoplight": {
|
||||
"id": "xmsl5222h8sro"
|
||||
}
|
||||
},
|
||||
"ENQUIRY_ECDD": {
|
||||
"type": "integer",
|
||||
"x-stoplight": {
|
||||
"id": "hgibemphi4r8j"
|
||||
}
|
||||
},
|
||||
"ENQUIRY_TM": {
|
||||
"type": "integer",
|
||||
"x-stoplight": {
|
||||
"id": "12ftglelyzcon"
|
||||
}
|
||||
},
|
||||
"ENQUIRY_ST": {
|
||||
"type": "integer",
|
||||
"x-stoplight": {
|
||||
"id": "3la5n5yagh6nq"
|
||||
}
|
||||
},
|
||||
"ENQUIRY_ONGOING": {
|
||||
"type": "integer",
|
||||
"x-stoplight": {
|
||||
"id": "tagt0zejkzmaa"
|
||||
}
|
||||
},
|
||||
"MINE": {
|
||||
"type": "integer",
|
||||
"x-stoplight": {
|
||||
"id": "3p2iub9ajdblw"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "target",
|
||||
"description": "审核目标"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tasks/{answerId}/approve/enquiry/offline": {
|
||||
"post": {
|
||||
"summary": "线下通过问询",
|
||||
"description": "**Request parameters**\n\n| 参数 | 必须 | 类型 | 说明 |\n|:---|:---|:---|:---|\n|answerId|是|String| 问询id|\n|content|是|Object| 问询内容|\n\n\n\n```\n\n{\n \"answerId\": 1,\n \"content\": {\n \"answers\": [\n {\n \"value\": \"第一个问题的回答\"\n },\n {\n \"value\": [\"/file/1.jpg\", \"/file/2.jpg\"]\n }\n ]\n }\n}\n```\n\n**Response fields**\n\n```json\n\n\n{\n \"status\": \"ok\",\n \"msg\": \"ok\",\n \"timestamp\": 1606477343900\n}\n\n\n```\n",
|
||||
"operationId": "post--tasks-{answerId}-approve-enquiry-offline",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"answer_id": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "hdza6stym83jj"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"type": "object",
|
||||
"x-stoplight": {
|
||||
"id": "308kahe1s8nk0"
|
||||
},
|
||||
"properties": {
|
||||
"answers": {
|
||||
"type": "array",
|
||||
"x-stoplight": {
|
||||
"id": "h309c4jqgkduz"
|
||||
},
|
||||
"items": {
|
||||
"x-stoplight": {
|
||||
"id": "h87o04ulbgs3e"
|
||||
},
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"value": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "h0ehc5t1ckc87"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
},
|
||||
"responses": {},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "answerId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "问询ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
"/enquiry/list": {
|
||||
"get": {
|
||||
"summary": "问询历史记录列表",
|
||||
"tags": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itemCount": {
|
||||
"type": "number"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"customerId": {
|
||||
"type": "number"
|
||||
},
|
||||
"userId": {
|
||||
"type": "number"
|
||||
},
|
||||
"realName": {
|
||||
"type": "string"
|
||||
},
|
||||
"accountId": {
|
||||
"type": "string"
|
||||
},
|
||||
"accountType": {
|
||||
"type": "string"
|
||||
},
|
||||
"enquiryType": {
|
||||
"type": "string"
|
||||
},
|
||||
"answerId": {
|
||||
"type": "string"
|
||||
},
|
||||
"preAnswerId": {
|
||||
"type": "string"
|
||||
},
|
||||
"operator": {
|
||||
"type": "string"
|
||||
},
|
||||
"enquiryStartDate": {
|
||||
"type": "number"
|
||||
},
|
||||
"enquiryDeadline": {
|
||||
"type": "number"
|
||||
},
|
||||
"enquiryReplyDate": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"operationId": "get-enquiry-list",
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"UNSUBMIT",
|
||||
"SUCCESS",
|
||||
"REJECTED",
|
||||
"PENDING"
|
||||
]
|
||||
},
|
||||
"in": "query",
|
||||
"name": "enquiryStatus",
|
||||
"description": "问询状态"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"CDD",
|
||||
"ONGOING",
|
||||
"TM",
|
||||
"ST"
|
||||
]
|
||||
},
|
||||
"in": "query",
|
||||
"name": "enquiryType",
|
||||
"description": "问询类型"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "email",
|
||||
"description": "邮箱"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "number"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "userIds",
|
||||
"description": "支持多个userid,逗号隔开"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "phone",
|
||||
"description": "手机号"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "telCode",
|
||||
"description": "区号"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "number"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "customerId"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "accountId",
|
||||
"description": "账号id"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "tag",
|
||||
"description": "用户标签"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"OPENED",
|
||||
"AUDITING"
|
||||
]
|
||||
},
|
||||
"in": "query",
|
||||
"name": "accountStatus",
|
||||
"description": "开户状态"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ENQUIRY_DATE",
|
||||
"OPEN_DATE",
|
||||
"APPLICATION_DATE",
|
||||
"ENQUIRE_DEADLINE_DATE"
|
||||
]
|
||||
},
|
||||
"in": "query",
|
||||
"name": "dateRangeType",
|
||||
"description": "时间范围类型"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "dateStart",
|
||||
"description": "开始时间"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "dateEnd",
|
||||
"description": "结束时间"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "offset",
|
||||
"description": "数据偏移量"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "limit",
|
||||
"description": "每页数量"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ASCENDING",
|
||||
"DESCENDING"
|
||||
]
|
||||
},
|
||||
"in": "query",
|
||||
"name": "order",
|
||||
"description": "排序类型"
|
||||
},
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": "query",
|
||||
"name": "realName",
|
||||
"description": "姓名"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/tasks/{taskId}/enquiry": {
|
||||
"get": {
|
||||
"summary": "问询详情",
|
||||
"description": "**Request parameters**\n\n| 参数 | 必须 | 类型 | 说明 |\n|:---|:---|:---|:---|\n|taskId|是|int| 任务ID|\n\n**Response fields**\n\n| 字段 | 类型 | 说明 |\n|:------|:-----|:------|\n| answerId | string | 答案ID |\n| realName | string | 姓名 |\n\n\n```json\n\n\n{\n \"data\": {\n \"accountInfo\": {\n \"userInfo\": {\n \"realName\": \"张三\"\n }\n },\n \"enquiryInfo\": {\n \"answerId\": \"123123\"\n }\n }\n}\n\n```\n",
|
||||
"operationId": "get--tasks-{taskId}-enquiry",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": "taskId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "任务ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
"/tasks/{taskId}/claim/enquiry": {
|
||||
"post": {
|
||||
"summary": "认领任务",
|
||||
"description": "**权限** \naccounts:enquiry:cdd \naccounts:enquiry:st \naccounts:enquiry:ecdd \naccounts:enquiry:tm \n\n\n**Response fields**\n\n\n```json\n\n\n{\n \"status\": \"ok\",\n \"msg\": \"ok\",\n \"timestamp\": 1606477343900\n}\n\n\n```\n",
|
||||
"operationId": "post--tasks-{taskId}-claim-enquiry",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "taskId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "任务ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
"/tasks/{taskId}/abort": {
|
||||
"post": {
|
||||
"summary": "放回任务",
|
||||
"description": "**权限** \naccounts:enquiry:cdd \naccounts:enquiry:st \naccounts:enquiry:ecdd \naccounts:enquiry:tm \n\n**Request parameters**\n\n| 参数 | 必须 | 类型 | 说明 |\n|:---|:---|:---|:---|\n|taskId|是|int| 任务ID|\n\n**Response fields**\n\n\n```json\n\n\n{\n \"status\": \"ok\",\n \"msg\": \"ok\",\n \"timestamp\": 1606477343900\n}\n\n\n```",
|
||||
"operationId": "post--tasks-{taskId}-abort",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {},
|
||||
"responses": {},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "taskId",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"/tasks/{taskId}/approve/enquiry": {
|
||||
"post": {
|
||||
"summary": "问询通过",
|
||||
"description": "**权限** \naccounts:enquiry:cdd \naccounts:enquiry:st \naccounts:enquiry:ecdd \naccounts:enquiry:tm \n\n**Request parameters**\n\n| 参数 | 必须 | 类型 | 说明 |\n|:---|:---|:---|:---|\n|taskId|是|int| 任务ID|\n\n**Response fields**\n\n\n```json\n\n\n{\n \"status\": \"ok\",\n \"msg\": \"ok\",\n \"timestamp\": 1606477343900\n}\n\n\n```",
|
||||
"operationId": "post--tasks-{taskId}-approve-enquiry",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {},
|
||||
"responses": {},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "taskId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "任务Id"
|
||||
}
|
||||
]
|
||||
},
|
||||
"/tasks/{taskId}/reject/enquiry": {
|
||||
"post": {
|
||||
"summary": "问询打回",
|
||||
"description": "**权限** \naccounts:enquiry:cdd \naccounts:enquiry:st \naccounts:enquiry:ecdd \naccounts:enquiry:tm \n\n\n**Request parameters**\n\n| 参数 | 必须 | 类型 | 说明 |\n|:---|:---|:---|:---|\n|taskId|是|int| ID|\n|rejectReasons|是|String| 打回理由|\n|comments|否|String| 备注|\n\n**打回原因对应操作**\n\n| 原因短语 | 操作 | \n|:------|:-----|\n| REJECT\\_CUSTOMER | 再次询问/打回用户申请 |\n| REJECT\\_FIRST\\_REVIEW | 打回初审(限制用户未开户) |\n| REJECT\\_OPEN | 拒绝开户 |\n\n\n**Response fields**\n\n```json\n\n\n{\n \"status\": \"ok\",\n \"msg\": \"ok\",\n \"timestamp\": 1606477343900\n}\n\n\n```\n",
|
||||
"operationId": "post--tasks-{taskId}-reject-enquiry",
|
||||
"tags": [
|
||||
"合规问询"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"rejectReasons": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "uqsyov82j5jks"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"type": "string",
|
||||
"x-stoplight": {
|
||||
"id": "rv9d5xuujthmm"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/Authorization"
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "taskId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"description": "任务ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"securitySchemes": {},
|
||||
"parameters": {
|
||||
"Authorization": {
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"openapi":"3.0.1","info":{"title":"个人项目","description":"","version":"1.0.0"},"tags":[],"paths":{"/ad/config_v2":{"post":{"summary":"config_v2","x-apifox-folder":"","x-apifox-status":"developing","deprecated":false,"description":"","tags":[],"parameters":[{"name":"Content-Type","in":"header","description":"","required":true,"example":"application/json; charset=UTF-8","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"disable_personal_recommend":{"type":"integer"},"appid":{"type":"string"},"h_dt":{"type":"integer"},"sdk_ver":{"type":"string"},"h_mac":{"type":"string"},"third_sdk_ver":{"type":"object","properties":{"tencent_sdk":{"type":"string"},"zgtech_sdk":{"type":"string"},"baidu_sdk":{"type":"string"},"tanx_sdk":{"type":"string"},"qumeng_sdk":{"type":"string"},"homemade_sdk":{"type":"string"},"kuaishou_sdk":{"type":"string"},"jd_sdk":{"type":"string"},"xingu_sdk":{"type":"string"},"toutiao_sdk":{"type":"string"},"mimo_sdk":{"type":"string"}},"required":["tencent_sdk","zgtech_sdk","baidu_sdk","tanx_sdk","qumeng_sdk","homemade_sdk","kuaishou_sdk","jd_sdk","xingu_sdk","toutiao_sdk","mimo_sdk"],"x-apifox-orders":["tencent_sdk","zgtech_sdk","baidu_sdk","tanx_sdk","qumeng_sdk","homemade_sdk","kuaishou_sdk","jd_sdk","xingu_sdk","toutiao_sdk","mimo_sdk"],"x-apifox-ignore-properties":[]}},"required":["disable_personal_recommend","appid","h_dt","sdk_ver","h_mac","third_sdk_ver"],"x-apifox-orders":["disable_personal_recommend","appid","h_dt","sdk_ver","h_mac","third_sdk_ver"],"x-apifox-ignore-properties":[]},"example":{"disable_personal_recommend":0,"ext":{"mid":"7466112968446","did":"9e17fa1e40b52024","app_ver":"2.89.10"},"h_carrier":"","h_ids":{"android_id":"9e17fa1e40b52024","oaid":"dfb91568eb92cf4e"},"h_model":"MI 8 Lite","h_os_ver":"10","h_os":"29","resolution":"1080x2154","h_nt":1,"h_did":"9e17fa1e40b52024","manufacturer":"Xiaomi","appid":"100028","h_dt":0,"sdk_ver":"4.0.07.19","h_mac":"70:BB:E9:9C:49:19","third_sdk_ver":{"tencent_sdk":"4.542.1412","zgtech_sdk":"2.2.5-1-20231122","baidu_sdk":"9.324","tanx_sdk":"2.9.3","qumeng_sdk":"3.457.13.422x","homemade_sdk":"1.0.68.6","kuaishou_sdk":"3.3.55","jd_sdk":"2.2.16_20230515","xingu_sdk":"12103_202309211453","toutiao_sdk":"5.6.1.5","mimo_sdk":"5.2.7"}}}}},"responses":{"200":{"description":"成功","content":{"application/json":{"schema":{"type":"object","properties":{},"x-apifox-orders":[],"x-apifox-ignore-properties":[]}}}}},"x-run-in-apifox":"https://www.apifox.cn/web/project/2037509/apis/api-135591150-run","security":[]}}},"components":{"schemas":{},"securitySchemes":{}},"servers":[]}
|
|
@ -120,7 +120,7 @@ public class BaseUserRoleService {
|
|||
put("READ+RECOVER", "permission.recover");
|
||||
put("READ+EXPORT", "permission.export");
|
||||
put("READ+EXECUTE", "permission.execute");
|
||||
put("READ+DEBUG", "permission.download");
|
||||
put("READ+DEBUG", "permission.debug");
|
||||
}};
|
||||
return Translator.get(translationMap.get(permissionKey));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue