refactor(接口测试): 接口定义接口优化

This commit is contained in:
AgAngle 2024-03-07 13:40:26 +08:00 committed by Craftsman
parent 7384228187
commit cafcfe198b
10 changed files with 261 additions and 186 deletions

View File

@ -82,24 +82,6 @@ public class ApiDefinitionController {
apiDefinitionService.batchUpdate(request, SessionUtils.getUserId());
}
@GetMapping("/delete-to-gc/{id}")
@Operation(summary = "接口测试-接口管理-删除接口定义到回收站")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
@Log(type = OperationLogType.DELETE, expression = "#msClass.moveToGcLog(#id)", msClass = ApiDefinitionLogService.class)
@CheckOwner(resourceId = "#id", resourceType = "api_definition")
public void deleteToGc(@PathVariable String id, @RequestParam(required = false) boolean deleteAllVersion) {
apiDefinitionService.deleteToGc(id, deleteAllVersion, SessionUtils.getUserId());
}
@PostMapping(value = "/batch/delete-to-gc")
@Operation(summary = "接口测试-接口管理-批量删除接口定义到回收站")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
@CheckOwner(resourceId = "#request.getSelectIds()", resourceType = "api_definition")
@SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getBatchEditApiDTO(#request)", targetClass = ApiDefinitionNoticeService.class)
public void batchDeleteToGc(@Validated @RequestBody ApiDefinitionBatchRequest request) {
apiDefinitionService.batchDeleteToGc(request, SessionUtils.getUserId());
}
@PostMapping(value = "/copy")
@Operation(summary = "接口测试-接口管理-复制接口定义")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_UPDATE)
@ -152,13 +134,22 @@ public class ApiDefinitionController {
return PageUtils.setPageInfo(page, apiDefinitionService.getApiDefinitionPage(request, SessionUtils.getUserId()));
}
@PostMapping(value = "/recover")
@Operation(summary = "接口测试-接口管理-恢复回收站接口定义")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_RECOVER)
@Log(type = OperationLogType.RECOVER, expression = "#msClass.recoverLog(#request)", msClass = ApiDefinitionLogService.class)
@CheckOwner(resourceId = "#request.getId()", resourceType = "api_definition")
public void recover(@Validated @RequestBody ApiDefinitionDeleteRequest request) {
apiDefinitionService.recover(request, SessionUtils.getUserId());
@GetMapping("/delete-to-gc/{id}")
@Operation(summary = "接口测试-接口管理-删除接口定义到回收站")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
@Log(type = OperationLogType.DELETE, expression = "#msClass.moveToGcLog(#id)", msClass = ApiDefinitionLogService.class)
@CheckOwner(resourceId = "#id", resourceType = "api_definition")
public void deleteToGc(@PathVariable String id, @RequestParam(required = false) boolean deleteAllVersion) {
apiDefinitionService.deleteToGc(id, deleteAllVersion, SessionUtils.getUserId());
}
@PostMapping(value = "/batch/delete-to-gc")
@Operation(summary = "接口测试-接口管理-批量删除接口定义到回收站")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
@CheckOwner(resourceId = "#request.getSelectIds()", resourceType = "api_definition")
@SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getBatchEditApiDTO(#request)", targetClass = ApiDefinitionNoticeService.class)
public void batchDeleteToGc(@Validated @RequestBody ApiDefinitionBatchDeleteRequest request) {
apiDefinitionService.batchDeleteToGc(request, SessionUtils.getUserId());
}
@GetMapping("/delete/{id}")
@ -178,6 +169,15 @@ public class ApiDefinitionController {
apiDefinitionService.batchDelete(request, SessionUtils.getUserId());
}
@PostMapping(value = "/recover")
@Operation(summary = "接口测试-接口管理-恢复回收站接口定义")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_RECOVER)
@Log(type = OperationLogType.RECOVER, expression = "#msClass.recoverLog(#request)", msClass = ApiDefinitionLogService.class)
@CheckOwner(resourceId = "#request.getId()", resourceType = "api_definition")
public void recover(@Validated @RequestBody ApiDefinitionDeleteRequest request) {
apiDefinitionService.recover(request, SessionUtils.getUserId());
}
@PostMapping(value = "/batch-recover")
@Operation(summary = "接口测试-接口管理-批量从回收站恢复接口定义")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_RECOVER)

View File

@ -30,6 +30,7 @@ public class ApiDefinitionAddRequest implements Serializable {
@Schema(description = "接口名称", requiredMode = Schema.RequiredMode.REQUIRED)
@Size(min = 1, max = 255, message = "{api_definition.name.length_range}")
@NotBlank
private String name;
@Schema(description = "接口协议", requiredMode = Schema.RequiredMode.REQUIRED)

View File

@ -0,0 +1,22 @@
package io.metersphere.api.dto.definition;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lan
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ApiDefinitionBatchDeleteRequest extends ApiDefinitionBatchRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "删除列表版本/删除全部版本")
private Boolean deleteAllVersion = false;
}

View File

@ -34,7 +34,4 @@ public class ApiDefinitionBatchRequest extends TableBatchProcessDTO implements S
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<@NotBlank String> moduleIds;
@Schema(description = "删除列表版本/删除全部版本")
private Boolean deleteAll = false;
}

View File

@ -1,12 +1,19 @@
package io.metersphere.api.dto.definition;
import io.metersphere.api.constants.ApiDefinitionStatus;
import io.metersphere.api.domain.ApiDefinitionCustomField;
import io.metersphere.system.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import java.io.Serial;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
/**
@ -14,7 +21,7 @@ import java.util.List;
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ApiDefinitionUpdateRequest extends ApiDefinitionAddRequest {
public class ApiDefinitionUpdateRequest {
@Serial
private static final long serialVersionUID = 1L;
@ -24,6 +31,60 @@ public class ApiDefinitionUpdateRequest extends ApiDefinitionAddRequest {
@Size(min = 1, max = 50, message = "{api_definition.id.length_range}")
private String id;
@Schema(description = "接口名称", requiredMode = Schema.RequiredMode.REQUIRED)
@Size(min = 1, max = 255, message = "{api_definition.name.length_range}")
private String name;
@Schema(description = "http协议类型post/get/其它协议则是协议名(mqtt)")
@Size(max = 20, message = "{api_debug.method.length_range}")
private String method;
@Schema(description = "http协议路径/其它协议则为空")
@Size(max = 500, message = "{api_debug.path.length_range}")
private String path;
@Schema(description = "接口状态/进行中/已完成", requiredMode = Schema.RequiredMode.REQUIRED)
@Size(min = 1, max = 50, message = "{api_definition.status.length_range}")
@EnumValue(enumClass = ApiDefinitionStatus.class)
private String status;
@Schema(description = "模块fk", requiredMode = Schema.RequiredMode.REQUIRED)
@Size(min = 1, max = 50, message = "{api_definition.module_id.length_range}")
private String moduleId;
@Schema(description = "描述")
@Size(max = 1000, message = "{api_definition.description.length_range}")
private String description;
@Schema(description = "标签")
private LinkedHashSet<
@NotBlank
@Size(min = 1, max = 64, message = "{api_test_case.tag.length_range}")
String> tags;
@Schema(description = "请求内容")
private Object request;
@Schema(description = "响应内容")
@Valid
private List<HttpResponse> response;
/**
* 新上传的文件ID
* 创建时先按ID创建目录再把文件放入目录
*/
@Schema(description = "新上传的文件ID")
private List<String> uploadFileIds;
/**
* 新关联的文件ID
*/
@Schema(description = "关联文件ID")
private List<String> linkFileIds;
@Schema(description = "自定义字段集合")
private List<ApiDefinitionCustomField> customFields;
/**
* 删除本地上传的文件ID
*/
@ -35,4 +96,16 @@ public class ApiDefinitionUpdateRequest extends ApiDefinitionAddRequest {
*/
@Schema(description = "取消关联文件ID")
private List<String> unLinkFileIds;
public void setPath(String path) {
this.path = StringUtils.trim(path);
}
public List<String> getTags() {
if (tags == null) {
return new ArrayList<>(0);
} else {
return new ArrayList<>(tags);
}
}
}

View File

@ -34,40 +34,38 @@
</select>
<select id="listByRequest" resultMap="ApiTestCaseDTO">
SELECT
t1.id,
t1.project_id,
t1.name,
t1.status,
t1.api_definition_id,
t1.priority,
t1.create_user,
t1.update_user,
t1.create_time,
t1.update_time,
t1.delete_user,
t1.delete_time,
t1.num,
t1.last_report_status,
t1.last_report_id,
t1.environment_id,
t1.tags,
atc.id,
atc.project_id,
atc.name,
atc.status,
atc.api_definition_id,
atc.priority,
atc.create_user,
atc.update_user,
atc.create_time,
atc.update_time,
atc.delete_user,
atc.delete_time,
atc.num,
atc.last_report_status,
atc.last_report_id,
atc.environment_id,
atc.tags,
a.module_id,
t1.pos
atc.pos
FROM
api_test_case t1
LEFT JOIN api_report t3 ON t1.last_report_id = t3.id
INNER JOIN api_definition a ON t1.api_definition_id = a.id
WHERE t1.deleted =#{deleted}
api_test_case atc
INNER JOIN api_definition a ON atc.api_definition_id = a.id
WHERE atc.deleted =#{deleted}
<include refid="queryWhereCondition"/>
</select>
<select id="getIds" resultType="java.lang.String">
SELECT
t1.id
atc.id
FROM
api_test_case t1
LEFT JOIN api_report t3 ON t1.last_report_id = t3.id
INNER JOIN api_definition a ON t1.api_definition_id = a.id
WHERE t1.deleted =#{deleted}
api_test_case atc
INNER JOIN api_definition a ON atc.api_definition_id = a.id
WHERE atc.deleted =#{deleted}
<include refid="queryWhereConditionByBatch"/>
</select>
<select id="getCaseInfoByApiIds" resultType="io.metersphere.api.domain.ApiTestCase">
@ -110,58 +108,58 @@
<select id="findPassRateByIds" resultType="io.metersphere.api.dto.definition.CasePassDTO">
SELECT
t1.api_scenario_id as id,
atc.api_scenario_id as id,
CONCAT(
FORMAT(
SUM(
IF
( t2.`status` = 'success', 1, 0 ))/ COUNT( t2.id )* 100,
( ar.`status` = 'success', 1, 0 ))/ COUNT( ar.id )* 100,
2
),
'%'
) value
FROM
api_report t2
left join api_scenario_record t1 on t1.api_scenario_report_id = t2.id
api_report ar
left join api_scenario_record atc on atc.api_scenario_report_id = ar.id
WHERE
t1.api_scenario_id IN
atc.api_scenario_id IN
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
GROUP BY
t1.api_scenario_id
atc.api_scenario_id
</select>
<select id="selectIdsByCaseIds" resultType="java.lang.String">
SELECT
t1.api_definition_id
atc.api_definition_id
FROM
api_test_case t1
api_test_case atc
WHERE
t1.deleted = 1
AND t1.id IN
atc.deleted = 1
AND atc.id IN
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
<select id="getCaseIds" resultType="java.lang.String">
SELECT
t1.id
atc.id
FROM
api_test_case t1
api_test_case atc
WHERE
t1.deleted = #{deleted}
AND t1.api_definition_id IN
atc.deleted = #{deleted}
AND atc.api_definition_id IN
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
<select id="getIdsByApiIds" resultType="java.lang.String">
SELECT
t1.id
atc.id
FROM
api_test_case t1
api_test_case atc
WHERE
t1.api_definition_id IN
atc.api_definition_id IN
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
@ -169,18 +167,18 @@
<select id="listByProviderRequest" resultMap="TestCaseProviderDTO">
SELECT
t1.id,
t1.project_id,
t1.name,
t1.priority,
t1.tags,
atc.id,
atc.project_id,
atc.name,
atc.priority,
atc.tags,
v.name as versionName
FROM
api_test_case t1
LEFT JOIN project_version v ON t1.version_id = v.id
INNER JOIN api_definition a ON t1.api_definition_id = a.id
WHERE t1.deleted =#{deleted}
and t1.id not in
api_test_case atc
LEFT JOIN project_version v ON atc.version_id = v.id
INNER JOIN api_definition a ON atc.api_definition_id = a.id
WHERE atc.deleted =#{deleted}
and atc.id not in
(
select associate.${apiCaseColumnName} from ${table} associate where associate.${sourceName} = #{request.sourceId}
)
@ -188,10 +186,10 @@
</select>
<select id="countModuleIdByProviderRequest" resultType="io.metersphere.project.dto.ModuleCountDTO">
SELECT a.module_id AS moduleId, count(t1.id) AS dataCount
FROM api_test_case t1 inner join api_definition a on t1.api_definition_id = a.id
WHERE t1.deleted =#{deleted}
and t1.id not in
SELECT a.module_id AS moduleId, count(atc.id) AS dataCount
FROM api_test_case atc inner join api_definition a on atc.api_definition_id = a.id
WHERE atc.deleted =#{deleted}
and atc.id not in
(
select associate.${apiCaseColumnName} from ${table} associate where associate.${sourceName} = #{request.sourceId}
)
@ -209,22 +207,21 @@
<select id="getTestCaseByProvider" resultType="io.metersphere.api.domain.ApiTestCase">
SELECT
t1.id, t1.version_id
atc.id, atc.version_id
FROM
api_test_case t1
LEFT JOIN api_report t3 ON t1.last_report_id = t3.id
INNER JOIN api_definition a ON t1.api_definition_id = a.id
WHERE t1.deleted =#{deleted}
api_test_case atc
INNER JOIN api_definition a ON atc.api_definition_id = a.id
WHERE atc.deleted =#{deleted}
<include refid="queryWhereConditionByBatch"/>
</select>
<select id="getTagsByIds" resultMap="BaseResultMap">
SELECT
t1.id,
t1.tags
atc.id,
atc.tags
FROM
api_test_case t1
WHERE t1.deleted =#{deleted}
and t1.id in
api_test_case atc
WHERE atc.deleted =#{deleted}
and atc.id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
@ -239,10 +236,10 @@
api_report.trigger_mode,
api_report.test_plan_id
from api_report
left join api_test_case_record t1 on t1.api_report_id = api_report.id
left join api_test_case_record atc on atc.api_report_id = api_report.id
where
<if test="request.id != null and request.id != ''">
t1.api_test_case_id = #{request.id}
atc.api_test_case_id = #{request.id}
</if>
<include refid="report_filters">
<property name="filter" value="request.filter"/>
@ -313,16 +310,16 @@
and a.protocol = #{request.protocol}
</if>
<if test="request.apiDefinitionId != null and request.apiDefinitionId!=''">
and t1.api_definition_id = #{request.apiDefinitionId}
and atc.api_definition_id = #{request.apiDefinitionId}
</if>
<if test="request.projectId != null and request.projectId!=''">
and t1.project_id = #{request.projectId}
and atc.project_id = #{request.projectId}
</if>
<if test="request.condition.keyword != null">
and (
t1.name like concat('%', #{request.condition.keyword},'%')
or t1.num like concat('%', #{request.condition.keyword},'%')
or t1.tags like JSON_CONTAINS(t1.tags, concat('["',#{request.condition.keyword},'"]'))
atc.name like concat('%', #{request.condition.keyword},'%')
or atc.num like concat('%', #{request.condition.keyword},'%')
or atc.tags like JSON_CONTAINS(atc.tags, concat('["',#{request.condition.keyword},'"]'))
)
</if>
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
@ -335,7 +332,7 @@
<property name="filter" value="request.condition.filter"/>
</include>
<include refid="queryVersionCondition">
<property name="versionTable" value="t1"/>
<property name="versionTable" value="atc"/>
</include>
</sql>
@ -344,17 +341,17 @@
and a.protocol = #{request.protocol}
</if>
<if test="request.apiDefinitionId != null and request.apiDefinitionId!=''">
and t1.api_definition_id = #{request.apiDefinitionId}
and atc.api_definition_id = #{request.apiDefinitionId}
</if>
<if test="request.projectId != null and request.projectId!=''">
and t1.project_id = #{request.projectId}
and atc.project_id = #{request.projectId}
</if>
<if test="request.keyword != null">
and (
t1.name like concat('%', #{request.keyword},'%')
or t1.num like concat('%', #{request.keyword},'%')
atc.name like concat('%', #{request.keyword},'%')
or atc.num like concat('%', #{request.keyword},'%')
or a.path like concat('%', #{request.keyword},'%')
or t1.tags like JSON_CONTAINS(t1.tags, concat('["',#{request.keyword},'"]'))
or atc.tags like JSON_CONTAINS(atc.tags, concat('["',#{request.keyword},'"]'))
)
</if>
<if test="request.moduleIds != null and request.moduleIds.size() > 0">
@ -367,7 +364,7 @@
<property name="filter" value="request.filter"/>
</include>
<include refid="queryVersionCondition">
<property name="versionTable" value="t1"/>
<property name="versionTable" value="atc"/>
</include>
</sql>
@ -377,37 +374,37 @@
<if test="values != null and values.size() > 0">
<choose>
<when test="key == 'priority'">
and t1.priority in
and atc.priority in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
<when test="key=='status'">
and t1.status in
and atc.status in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
<when test="key=='caseStatus' or key=='case_status'">
and t1.case_status in
and atc.case_status in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
<when test="key=='last_execute_result'">
and t1.last_execute_result in
and atc.last_execute_result in
<foreach collection="values" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</when>
<when test="key=='create_user' or key=='createUser'">
and t1.create_user in
and atc.create_user in
<foreach collection="values" item="value" separator="," open="(" close=")">
(#{value})
</foreach>
</when>
<when test="key=='update_user' or key=='updateUser'">
and t1.update_user in
and atc.update_user in
<foreach collection="values" item="value" separator="," open="(" close=")">
(#{value})
</foreach>

View File

@ -326,13 +326,13 @@ public class ApiFileResourceService {
boolean isTemp = false;
ApiResourceType apiResourceType = ApiResourceType.valueOf(type);
String apiFolder = switch (apiResourceType) {
case ApiResourceType.API_DEBUG ->
case API_DEBUG ->
DefaultRepositoryDir.getApiDebugDir(request.getProjectId(), request.getSourceId()) + "/" + request.getFileId();
case ApiResourceType.API ->
case API ->
DefaultRepositoryDir.getApiDefinitionDir(request.getProjectId(), request.getSourceId()) + "/" + request.getFileId();
case ApiResourceType.API_CASE ->
case API_CASE ->
DefaultRepositoryDir.getApiCaseDir(request.getProjectId(), request.getSourceId()) + "/" + request.getFileId();
case ApiResourceType.API_SCENARIO ->
case API_SCENARIO ->
DefaultRepositoryDir.getApiScenarioDir(request.getProjectId(), request.getSourceId()) + "/" + request.getFileId();
default -> throw new MSException("file type error!");
};

View File

@ -70,7 +70,7 @@ public class ApiDefinitionLogService {
ApiDefinitionDTO apiDefinition = getOriginalValue(request.getId());
if (apiDefinition.getId() != null) {
LogDTO dto = new LogDTO(
request.getProjectId(),
apiDefinition.getProjectId(),
null,
request.getId(),
null,

View File

@ -252,44 +252,37 @@ public class ApiDefinitionService {
}
public ApiDefinition update(ApiDefinitionUpdateRequest request, String userId) {
ProjectService.checkResourceExist(request.getProjectId());
ApiDefinition originApiDefinition = checkApiDefinition(request.getId());
ApiDefinition apiDefinition = new ApiDefinition();
BeanUtils.copyBean(apiDefinition, request);
checkResponseNameCode(request.getResponse());
apiDefinition.setVersionId(originApiDefinition.getVersionId());
apiDefinition.setRefId(originApiDefinition.getRefId());
apiDefinition.setProjectId(originApiDefinition.getProjectId());
if (request.getProtocol().equals(ModuleConstants.NODE_PROTOCOL_HTTP)) {
checkUpdateExist(apiDefinition);
if (originApiDefinition.getProtocol().equals(ModuleConstants.NODE_PROTOCOL_HTTP)) {
checkUpdateExist(apiDefinition, originApiDefinition);
//http协议的接口如果修改了path和method需要同步把case的path和method修改
if (!originApiDefinition.getPath().equals(apiDefinition.getPath()) || !originApiDefinition.getMethod().equals(apiDefinition.getMethod())) {
List<String> ids = new ArrayList<>();
ids.add(request.getId());
apiTestCaseService.updateByApiDefinitionId(ids, apiDefinition);
apiTestCaseService.updateByApiDefinitionId(List.of(request.getId()), apiDefinition);
}
}
apiDefinition.setStatus(request.getStatus());
apiDefinition.setUpdateUser(userId);
apiDefinition.setUpdateTime(System.currentTimeMillis());
if (CollectionUtils.isNotEmpty(request.getTags())) {
apiDefinition.setTags(request.getTags());
}
apiDefinitionMapper.updateByPrimaryKeySelective(apiDefinition);
ApiDefinitionBlob apiDefinitionBlob = new ApiDefinitionBlob();
apiDefinitionBlob.setId(apiDefinition.getId());
if (request.getRequest() != null) {
apiDefinitionBlob.setRequest(getMsTestElementStr(request.getRequest()).getBytes());
}
if (request.getResponse() != null) {
apiDefinitionBlob.setResponse(JSON.toJSONString(request.getResponse()).getBytes());
if (request.getResponse() != null || request.getRequest() != null) {
// 更新请求和响应
ApiDefinitionBlob apiDefinitionBlob = new ApiDefinitionBlob();
apiDefinitionBlob.setId(apiDefinition.getId());
Optional.ofNullable(request.getRequest())
.ifPresent(req -> apiDefinitionBlob.setRequest(getMsTestElementStr(req).getBytes()));
Optional.ofNullable(request.getResponse())
.ifPresent(responses -> apiDefinitionBlob.setResponse(JSON.toJSONString(responses).getBytes()));
apiDefinitionBlobMapper.updateByPrimaryKeySelective(apiDefinitionBlob);
}
apiDefinitionBlobMapper.updateByPrimaryKeySelective(apiDefinitionBlob);
// 自定义字段
handleUpdateCustomFields(request);
handleUpdateCustomFields(request, originApiDefinition.getProjectId());
// 处理文件
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(originApiDefinition.getId(), originApiDefinition.getProjectId(), userId);
@ -323,7 +316,7 @@ public class ApiDefinitionService {
apiDefinitionUpdateRequest.setCustomFields(list);
ids.forEach(id -> {
apiDefinitionUpdateRequest.setId(id);
handleUpdateCustomFields(apiDefinitionUpdateRequest);
handleUpdateCustomFields(apiDefinitionUpdateRequest, request.getProjectId());
});
} else {
ApiDefinition apiDefinition = new ApiDefinition();
@ -338,13 +331,13 @@ public class ApiDefinitionService {
}
private void handleUpdateCustomFields(ApiDefinitionUpdateRequest request) {
private void handleUpdateCustomFields(ApiDefinitionUpdateRequest request, String projectId) {
List<ApiDefinitionCustomField> customFields = request.getCustomFields();
//更新自定义字段
if (CollectionUtils.isNotEmpty(customFields)) {
List<ApiDefinitionCustomField> addFields = new ArrayList<>();
List<ApiDefinitionCustomField> updateFields = new ArrayList<>();
List<ApiDefinitionCustomFieldDTO> originalFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(List.of(request.getId()), request.getProjectId());
List<ApiDefinitionCustomFieldDTO> originalFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(List.of(request.getId()), projectId);
Map<String, ApiDefinitionCustomFieldDTO> originalFieldMap = originalFields.stream().collect(Collectors.toMap(ApiDefinitionCustomFieldDTO::getId, Function.identity()));
customFields.forEach(customField -> {
@ -427,10 +420,10 @@ public class ApiDefinitionService {
handleDeleteApiDefinition(Collections.singletonList(id), deleteAllVersion, apiDefinition.getProjectId(), userId, false);
}
public void batchDeleteToGc(ApiDefinitionBatchRequest request, String userId) {
public void batchDeleteToGc(ApiDefinitionBatchDeleteRequest request, String userId) {
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false, userId);
if (CollectionUtils.isNotEmpty(ids)) {
handleDeleteApiDefinition(ids, request.getDeleteAll(), request.getProjectId(), userId, true);
handleDeleteApiDefinition(ids, request.getDeleteAllVersion(), request.getProjectId(), userId, true);
}
}
@ -533,19 +526,21 @@ public class ApiDefinitionService {
}
}
private void checkUpdateExist(ApiDefinition apiDefinition) {
if (!StringUtils.equals(apiDefinition.getProtocol(), ApiConstants.HTTP_PROTOCOL)) {
private void checkUpdateExist(ApiDefinition apiDefinition, ApiDefinition originApiDefinition) {
if (!StringUtils.equals(originApiDefinition.getProtocol(), ApiConstants.HTTP_PROTOCOL)) {
return;
}
if (StringUtils.isNotEmpty(apiDefinition.getPath()) && StringUtils.isNotEmpty(apiDefinition.getMethod())) {
if (StringUtils.isNotEmpty(apiDefinition.getPath()) || StringUtils.isNotEmpty(apiDefinition.getMethod())) {
ApiDefinitionExample example = new ApiDefinitionExample();
String method = StringUtils.isBlank(apiDefinition.getMethod()) ? originApiDefinition.getMethod() : apiDefinition.getMethod();
String path = StringUtils.isBlank(apiDefinition.getPath()) ? originApiDefinition.getPath() : apiDefinition.getPath();
example.createCriteria()
.andIdNotEqualTo(apiDefinition.getId())
.andProtocolEqualTo(apiDefinition.getProtocol())
.andPathEqualTo(apiDefinition.getPath())
.andMethodEqualTo(apiDefinition.getMethod())
.andProjectIdEqualTo(apiDefinition.getProjectId())
.andRefIdNotEqualTo(apiDefinition.getRefId());
.andPathEqualTo(path)
.andMethodEqualTo(method)
.andIdNotEqualTo(originApiDefinition.getId())
.andProtocolEqualTo(originApiDefinition.getProtocol())
.andProjectIdEqualTo(originApiDefinition.getProjectId())
.andRefIdNotEqualTo(originApiDefinition.getRefId());
if (apiDefinitionMapper.countByExample(example) > 0) {
throw new MSException(ApiResultCode.API_DEFINITION_EXIST);
}
@ -628,8 +623,8 @@ public class ApiDefinitionService {
return copyName;
}
private void handleDeleteApiDefinition(List<String> ids, boolean deleteAll, String projectId, String userId, boolean isBatch) {
if (deleteAll) {
private void handleDeleteApiDefinition(List<String> ids, boolean deleteAllVersion, String projectId, String userId, boolean isBatch) {
if (deleteAllVersion) {
//全部删除 进入回收站
List<String> refIds = extApiDefinitionMapper.getRefIds(ids, false);
if (CollectionUtils.isNotEmpty(refIds)) {
@ -1065,9 +1060,6 @@ public class ApiDefinitionService {
ApiDefinition apiDefinition = checkApiDefinition(request.getTargetId());
if (!StringUtils.equals(request.getModuleId(), apiDefinition.getModuleId())) {
checkModuleExist(request.getModuleId());
apiDefinition.setModuleId(request.getModuleId());
apiDefinition.setProjectId(request.getProjectId());
checkUpdateExist(apiDefinition);
apiDefinition.setUpdateTime(System.currentTimeMillis());
apiDefinition.setUpdateUser(userId);
apiDefinitionMapper.updateByPrimaryKeySelective(apiDefinition);
@ -1084,7 +1076,7 @@ public class ApiDefinitionService {
}
private void checkResponseNameCode(Object response) {
if (!response.toString().isEmpty() && !response.toString().equals("{}")) {
if (response != null && !response.toString().isEmpty() && !response.toString().equals("{}")) {
List<HttpResponse> httpResponses = ApiDataUtils.parseArray(JSON.toJSONString(response), HttpResponse.class);
boolean isUnique = httpResponses.stream()
.map(httpResponse -> httpResponse.getName() + httpResponse.getStatusCode())

View File

@ -446,11 +446,8 @@ public class ApiDefinitionControllerTests extends BaseTest {
request.setLinkFileIds(List.of(fileMetadataId));
request.setDeleteFileIds(null);
request.setUnLinkFileIds(null);
String versionId = request.getVersionId();
request.setVersionId(null);
this.requestPostWithOk(UPDATE, request);
// 校验请求成功数据
request.setVersionId(versionId);
apiDefinition = assertAddApiDefinition(request, msHttpElement, request.getId());
assertUploadFile(apiDefinition.getId(), List.of(fileId));
assertLinkFile(apiDefinition.getId());
@ -477,15 +474,20 @@ public class ApiDefinitionControllerTests extends BaseTest {
assertUploadFile(apiDefinition.getId(), List.of(newFileId1, newFileId2));
assertLinkFile(apiDefinition.getId());
// 单独更新状态
ApiDefinitionUpdateRequest updateStatusRequest = new ApiDefinitionUpdateRequest();
updateStatusRequest.setId(apiDefinition.getId());
updateStatusRequest.setStatus(ApiDefinitionStatus.DONE.name());
this.requestPostWithOk(UPDATE, updateStatusRequest);
apiDefinition = apiDefinitionMapper.selectByPrimaryKey(updateStatusRequest.getId());
Assertions.assertEquals(apiDefinition.getStatus(), ApiDefinitionStatus.DONE.name());
// @@重名校验异常
request.setModuleId("default");
request.setPath("/api/admin/posts");
request.setMethod("GET");
request.setUploadFileIds(null);
request.setLinkFileIds(null);
request.setDeleteFileIds(null);
request.setUnLinkFileIds(null);
assertErrorCode(this.requestPost(UPDATE, request), ApiResultCode.API_DEFINITION_EXIST);
ApiDefinitionUpdateRequest repeatRequest = new ApiDefinitionUpdateRequest();
repeatRequest.setId(apiDefinition.getId());
repeatRequest.setPath("/api/admin/posts");
repeatRequest.setMethod("GET");
assertErrorCode(this.requestPost(UPDATE, repeatRequest), ApiResultCode.API_DEFINITION_EXIST);
// @@响应名+响应码唯一校验异常
request.setName("test123-response");
@ -503,11 +505,6 @@ public class ApiDefinitionControllerTests extends BaseTest {
request.setName("test123");
assertErrorCode(this.requestPost(UPDATE, request), ApiResultCode.API_DEFINITION_NOT_EXIST);
// 校验项目是否存在
request.setProjectId("111");
request.setName("test123");
assertErrorCode(this.requestPost(UPDATE, request), MsHttpResultCode.NOT_FOUND);
// @@校验日志
checkLogModelList.add(new CheckLogModel(apiDefinition.getId(), OperationLogType.UPDATE, UPDATE));
@ -565,11 +562,8 @@ public class ApiDefinitionControllerTests extends BaseTest {
Assertions.assertEquals(updateRequest.getPath(), caseElement.getPath());
Assertions.assertEquals(updateRequest.getMethod(), caseElement.getMethod());
});
// @@异常参数校验
createdGroupParamValidateTest(ApiDefinitionUpdateRequest.class, UPDATE);
// @@校验权限
request.setId(apiDefinition.getId());
request.setProjectId(DEFAULT_PROJECT_ID);
request.setName("permission-st-6");
request.setModuleId("module-st-6");
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_UPDATE, UPDATE, request);
@ -788,7 +782,6 @@ public class ApiDefinitionControllerTests extends BaseTest {
// 移动选中
request.setSelectIds(List.of("1001", "1002", "1005"));
request.setExcludeIds(List.of("1005"));
request.setDeleteAll(false);
request.setSelectAll(false);
this.requestPostWithOkAndReturn(BATCH_MOVE, request);
// @@校验日志
@ -1273,23 +1266,23 @@ public class ApiDefinitionControllerTests extends BaseTest {
@Order(15)
public void testBatchDel() throws Exception {
LogUtils.info("batch delete api test");
ApiDefinitionBatchRequest request = new ApiDefinitionBatchRequest();
ApiDefinitionBatchDeleteRequest request = new ApiDefinitionBatchDeleteRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
// 删除选中
request.setSelectIds(List.of("1004"));
request.setDeleteAll(false);
request.setDeleteAllVersion(false);
request.setSelectAll(false);
this.requestPostWithOkAndReturn(BATCH_DELETE_TO_GC, request);
// @@校验日志
checkLogModelList.add(new CheckLogModel("1004", OperationLogType.DELETE, BATCH_DELETE_TO_GC));
request.setSelectIds(List.of("1002"));
request.setDeleteAll(false);
request.setDeleteAllVersion(false);
request.setSelectAll(false);
assertErrorCode(this.requestPost(BATCH_DELETE_TO_GC, request), ApiResultCode.API_DEFINITION_NOT_EXIST);
// 删除全部 条件为关键字为st-6的数据
request.setDeleteAll(true);
request.setDeleteAllVersion(true);
request.setExcludeIds(List.of("1005"));
request.setSelectAll(true);
BaseCondition baseCondition = new BaseCondition();