diff --git a/backend/framework/sdk/src/main/resources/i18n/api.properties b/backend/framework/sdk/src/main/resources/i18n/api.properties index 2ced8703be..b5ae1773f4 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api.properties @@ -369,7 +369,7 @@ api_definition_custom_field.field_id.not_blank=自定义字段ID不能为空 api_module.not.exist=模块不存在 permission.api.name=接口测试 permission.api_mock.name=接口 MOCK -api_debug_exist=接口已存在 +api_debug_exist=请求已存在 follow=关注 unfollow=取消关注 api_definition_exist=接口已存在 diff --git a/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties index ae63c6b401..3bad851314 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api_en_US.properties @@ -381,7 +381,7 @@ api_definition_custom_field.field_id.not_blank=Field ID cannot be empty api_module.not.exist=The module does not exist permission.api.name=API Test permission.api_mock.name=API MOCK -api_debug_exist=The API already exists +api_debug_exist=The Request already exists follow=Follow unfollow=Unfollow api_definition_exist=The API already exists diff --git a/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties index 407c5889bb..f6d90e631f 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api_zh_CN.properties @@ -349,7 +349,7 @@ api_definition_custom_field.field_id.not_blank=自定义字段ID不能为空 api_module.not.exist=模块不存在 permission.api.name=接口测试 permission.api_mock.name=接口 MOCK -api_debug_exist=接口已存在 +api_debug_exist=请求已存在 follow=关注 unfollow=取消关注 api_definition_exist=接口已存在 diff --git a/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties index 226088e7e5..19ec0eb19e 100644 --- a/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/api_zh_TW.properties @@ -350,7 +350,7 @@ api_definition_custom_field.field_id.not_blank=自定義字段ID不能爲空 api_module.not.exist=模塊不存在 permission.api.name=接口測試 permission.api_mock.name=接口 MOCK -api_debug_exist=接口已存在 +api_debug_exist=请求已存在 follow=关注 unfollow=取消关注 api_definition_exist=接口已存在 diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/debug/ApiDebugController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/debug/ApiDebugController.java index 877d11d9bb..ac0b11ba3f 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/debug/ApiDebugController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/debug/ApiDebugController.java @@ -2,11 +2,13 @@ package io.metersphere.api.controller.debug; import io.metersphere.api.domain.ApiDebug; import io.metersphere.api.dto.debug.*; +import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.service.debug.ApiDebugLogService; import io.metersphere.api.service.debug.ApiDebugService; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.security.CheckOwner; import io.metersphere.system.utils.SessionUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -82,4 +84,13 @@ public class ApiDebugController { public String debug(@Validated @RequestBody ApiDebugRunRequest request) { return apiDebugService.debug(request); } + + @PostMapping("/edit/pos") + @Operation(summary = "接口调试-拖拽排序") + @RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_UPDATE) + @Log(type = OperationLogType.UPDATE, expression = "#msClass.moveLog(#request.getTargetId())", msClass = ApiDebugLogService.class) + @CheckOwner(resourceId = "#request.getTargetId()", resourceType = "api_debug") + public void editPos(@Validated @RequestBody ApiEditPosRequest request) { + apiDebugService.editPos(request, SessionUtils.getUserId()); + } } \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java index 6865b59717..bf4507bf18 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java @@ -4,6 +4,7 @@ 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.request.ApiEditPosRequest; import io.metersphere.api.dto.request.ImportRequest; import io.metersphere.api.service.definition.ApiDefinitionLogService; import io.metersphere.api.service.definition.ApiDefinitionNoticeService; @@ -12,7 +13,6 @@ import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.dto.OperationHistoryDTO; import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.dto.request.OperationHistoryVersionRequest; -import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.notice.annotation.SendNotice; @@ -239,9 +239,9 @@ public class ApiDefinitionController { @PostMapping("/edit/pos") @Operation(summary = "接口测试-接口管理-接口-拖拽排序") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_UPDATE) - public void editPos(@Validated @RequestBody PosRequest request) { - apiDefinitionService.editPos(request); + @Log(type = OperationLogType.UPDATE, expression = "#msClass.moveLog(#request.getTargetId())", msClass = ApiDefinitionLogService.class) + @CheckOwner(resourceId = "#request.getTargetId()", resourceType = "api_definition") + public void editPos(@Validated @RequestBody ApiEditPosRequest request) { + apiDefinitionService.editPos(request, SessionUtils.getUserId()); } - - } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/ApiEditPosRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/ApiEditPosRequest.java new file mode 100644 index 0000000000..664fcf712e --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/request/ApiEditPosRequest.java @@ -0,0 +1,19 @@ +package io.metersphere.api.dto.request; + +import io.metersphere.system.dto.sdk.request.PosRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class ApiEditPosRequest extends PosRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "模块id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{api_definition.module_id.not_blank}") + private String moduleId; + +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.java b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.java index 830672d84a..2ac1b5e71f 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.java @@ -17,4 +17,8 @@ public interface ExtApiDebugMapper { Long getPos(@Param("userId") String userId); + Long getPrePos(@Param("projectId") String projectId, @Param("basePos") Long basePos); + + Long getLastPos(@Param("projectId") String projectId, @Param("basePos") Long basePos); + } \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.xml index cdf387d902..714cda7003 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiDebugMapper.xml @@ -17,4 +17,20 @@ ORDER BY pos DESC LIMIT 1; + + + + \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugLogService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugLogService.java index cd802924cc..a00b36b6ea 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugLogService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugLogService.java @@ -11,6 +11,7 @@ import io.metersphere.system.log.dto.LogDTO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + /** * @author jianxing * @date : 2023-11-6 @@ -65,4 +66,18 @@ public class ApiDebugLogService { dto.setOriginalValue(JSON.toJSONBytes(apiDebug)); return dto; } + + public LogDTO moveLog(String id) { + ApiDebug apiDebug = apiDebugService.get(id); + LogDTO dto = new LogDTO( + OperationLogConstants.SYSTEM, + OperationLogConstants.SYSTEM, + apiDebug.getId(), + null, + OperationLogType.UPDATE.name(), + OperationLogModule.API_DEBUG, + apiDebug.getName()); + dto.setOriginalValue(JSON.toJSONBytes(apiDebug)); + return dto; + } } \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java index 529e8bc12c..3e2ce4ef14 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java @@ -4,10 +4,13 @@ import io.metersphere.api.constants.ApiResourceType; import io.metersphere.api.domain.ApiDebug; import io.metersphere.api.domain.ApiDebugBlob; import io.metersphere.api.domain.ApiDebugExample; +import io.metersphere.api.domain.ApiDebugModule; import io.metersphere.api.dto.ApiParamConfig; import io.metersphere.api.dto.debug.*; +import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.mapper.ApiDebugBlobMapper; import io.metersphere.api.mapper.ApiDebugMapper; +import io.metersphere.api.mapper.ApiDebugModuleMapper; import io.metersphere.api.mapper.ExtApiDebugMapper; import io.metersphere.api.service.ApiExecuteService; import io.metersphere.api.service.ApiFileResourceService; @@ -53,6 +56,8 @@ public class ApiDebugService { private ApiExecuteService apiExecuteService; @Resource private ApiPluginService apiPluginService; + @Resource + private ApiDebugModuleMapper apiDebugModuleMapper; public static final Long ORDER_STEP = 5000L; @@ -209,4 +214,32 @@ public class ApiDebugService { return runRequest.getReportId(); } + public void checkModuleExist(String moduleId) { + if (StringUtils.equals(moduleId, "root")) { + return; + } + ApiDebugModule apiDebugModule = apiDebugModuleMapper.selectByPrimaryKey(moduleId); + if (apiDebugModule == null) { + throw new MSException("module.not.exist"); + } + } + + public void editPos(ApiEditPosRequest request, String userId) { + ApiDebug apiDebug = checkResourceExist(request.getTargetId()); + checkModuleExist(request.getModuleId()); + apiDebug.setModuleId(request.getModuleId()); + checkUpdateExist(apiDebug, apiDebug); + apiDebug.setUpdateUser(userId); + apiDebug.setUpdateTime(System.currentTimeMillis()); + apiDebugMapper.updateByPrimaryKeySelective(apiDebug); + if (StringUtils.equals(request.getTargetId(), request.getMoveId())) { + return; + } + ServiceUtils.updatePosField(request, + ApiDebug.class, + apiDebugMapper::selectByPrimaryKey, + extApiDebugMapper::getPrePos, + extApiDebugMapper::getLastPos, + apiDebugMapper::updateByPrimaryKeySelective); + } } \ No newline at end of file diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java index 76757b2e60..40477c19da 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java @@ -339,5 +339,20 @@ public class ApiDefinitionLogService { return dto.getId(); } + public LogDTO moveLog(String id) { + ApiDefinitionDTO apiDefinitionDTO = getOriginalValue(id); + Project project = projectMapper.selectByPrimaryKey(apiDefinitionDTO.getProjectId()); + LogDTO dto = new LogDTO( + apiDefinitionDTO.getProjectId(), + project.getOrganizationId(), + apiDefinitionDTO.getId(), + null, + OperationLogType.UPDATE.name(), + OperationLogModule.API_DEFINITION, + apiDefinitionDTO.getName()); + dto.setOriginalValue(JSON.toJSONBytes(apiDefinitionDTO)); + return dto; + } + } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java index dcd4cc97e3..937fc30047 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java @@ -8,6 +8,7 @@ import io.metersphere.api.dto.ApiResourceModuleInfo; import io.metersphere.api.dto.converter.ApiDefinitionImport; import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest; import io.metersphere.api.dto.definition.*; +import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.dto.request.ImportRequest; import io.metersphere.api.mapper.*; import io.metersphere.api.parser.ImportParser; @@ -29,7 +30,6 @@ import io.metersphere.system.dto.OperationHistoryDTO; import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.dto.request.OperationHistoryVersionRequest; import io.metersphere.system.dto.sdk.SessionUser; -import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.dto.table.TableBatchProcessDTO; import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.service.OperationHistoryService; @@ -1004,12 +1004,22 @@ public class ApiDefinitionService { return apiDefinitionBlobMapper.selectByExampleWithBLOBs(apiDefinitionBlobExample); } - public void editPos(PosRequest request) { + public void editPos(ApiEditPosRequest request, String userId) { + ApiDefinition apiDefinition = checkApiDefinition(request.getTargetId()); + checkModuleExist(request.getModuleId()); + apiDefinition.setModuleId(request.getModuleId()); + checkUpdateExist(apiDefinition); + apiDefinition.setUpdateTime(System.currentTimeMillis()); + apiDefinition.setUpdateUser(userId); + apiDefinitionMapper.updateByPrimaryKeySelective(apiDefinition); + if (StringUtils.equals(request.getTargetId(), request.getMoveId())) { + return; + } ServiceUtils.updatePosField(request, ApiDefinition.class, apiDefinitionMapper::selectByPrimaryKey, extApiDefinitionMapper::getPrePos, - extApiTestCaseMapper::getLastPos, + extApiDefinitionMapper::getLastPos, apiDefinitionMapper::updateByPrimaryKeySelective); } @@ -1029,4 +1039,14 @@ public class ApiDefinitionService { public List getModuleInfoByIds(List apiIds) { return extApiDefinitionMapper.getModuleInfoByIds(apiIds); } + + public void checkModuleExist(String moduleId) { + if (StringUtils.equals(moduleId, "root")) { + return; + } + ApiDefinitionModule apiDefinitionModule = apiDefinitionModuleMapper.selectByPrimaryKey(moduleId); + if (apiDefinitionModule == null) { + throw new MSException("module.not.exist"); + } + } } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java index 8b096a8e89..2cd50b4d15 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDebugControllerTests.java @@ -7,6 +7,7 @@ import io.metersphere.api.domain.ApiDebugBlob; import io.metersphere.api.domain.ApiFileResource; import io.metersphere.api.dto.assertion.MsAssertionConfig; import io.metersphere.api.dto.debug.*; +import io.metersphere.api.dto.request.ApiEditPosRequest; import io.metersphere.api.dto.request.MsCommonElement; import io.metersphere.api.dto.request.http.MsHTTPElement; import io.metersphere.api.dto.request.http.RestParam; @@ -53,6 +54,7 @@ import java.util.List; import static io.metersphere.api.controller.result.ApiResultCode.API_DEBUG_EXIST; import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** * @author jianxing @@ -359,6 +361,29 @@ public class ApiDebugControllerTests extends BaseTest { @Test @Order(6) + public void move() throws Exception { + ApiEditPosRequest request = new ApiEditPosRequest(); + request.setTargetId(addApiDebug.getId()); + request.setMoveId(addApiDebug.getId()); + request.setProjectId(DEFAULT_PROJECT_ID); + request.setModuleId("root"); + request.setMoveMode("AFTER"); + requestPost("edit/pos", request).andExpect(status().isOk()); + // @@请求成功 + request.setMoveId(anotherAddApiDebug.getId()); + this.requestPostWithOk("edit/pos", request); + // 校验请求成功数据 + ApiDebug apiDebug = apiDebugMapper.selectByPrimaryKey(addApiDebug.getId()); + Assertions.assertEquals(apiDebug.getModuleId(), "root"); + request.setModuleId("def"); + requestPost("edit/pos", request).andExpect(status().is5xxServerError()); + request.setModuleId("root"); + // @@校验权限 + requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_UPDATE, "edit/pos", request); + } + + @Test + @Order(7) public void debug() throws Exception { ApiDebugRunRequest request = new ApiDebugRunRequest(); request.setId(addApiDebug.getId()); @@ -506,7 +531,7 @@ public class ApiDebugControllerTests extends BaseTest { } @Test - @Order(7) + @Order(8) public void delete() throws Exception { // @@请求成功 this.requestGetWithOk(DEFAULT_DELETE, addApiDebug.getId()); diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java index 7fa67033d8..674aac2bca 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java @@ -6,6 +6,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.ApiEditPosRequest; import io.metersphere.api.dto.request.ImportRequest; import io.metersphere.api.dto.request.http.MsHTTPElement; import io.metersphere.api.mapper.*; @@ -33,7 +34,6 @@ import io.metersphere.system.domain.OperationHistoryExample; import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.dto.request.OperationHistoryVersionRequest; import io.metersphere.system.dto.sdk.BaseCondition; -import io.metersphere.system.dto.sdk.request.PosRequest; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.mapper.OperationHistoryMapper; import io.metersphere.system.utils.Pager; @@ -1065,17 +1065,22 @@ public class ApiDefinitionControllerTests extends BaseTest { @Order(9) public void testPos() throws Exception { - apiDefinition = apiDefinitionMapper.selectByPrimaryKey("1001"); - ApiDefinition apiDefinition1 = apiDefinitionMapper.selectByPrimaryKey("1002"); - PosRequest posRequest = new PosRequest(); - posRequest.setProjectId(DEFAULT_PROJECT_ID); - posRequest.setTargetId(apiDefinition.getId()); - posRequest.setMoveId(apiDefinition1.getId()); - posRequest.setMoveMode("AFTER"); - this.requestPostWithOkAndReturn(BASE_PATH + "edit/pos", posRequest); + ApiEditPosRequest request = new ApiEditPosRequest(); + apiDefinition = apiDefinitionMapper.selectByPrimaryKey("1005"); + ApiDefinition apiDefinition1 = apiDefinitionMapper.selectByPrimaryKey("1004"); + request.setProjectId(DEFAULT_PROJECT_ID); + request.setTargetId(apiDefinition.getId()); + request.setMoveId(apiDefinition.getId()); + request.setModuleId("root"); + request.setMoveMode("AFTER"); + this.requestPostWithOkAndReturn(BASE_PATH + "edit/pos", request); + request.setMoveId(apiDefinition1.getId()); + this.requestPostWithOkAndReturn(BASE_PATH + "edit/pos", request); + request.setMoveMode("BEFORE"); + this.requestPostWithOkAndReturn(BASE_PATH + "edit/pos", request); - posRequest.setMoveMode("BEFORE"); - this.requestPostWithOkAndReturn(BASE_PATH + "edit/pos", posRequest); + request.setModuleId("module-st-6"); + requestPost(BASE_PATH + "edit/pos", request).andExpect(status().is5xxServerError()); }