From e112391c2a4905fd977c4f0ad52cddd29309cbc4 Mon Sep 17 00:00:00 2001 From: song-tianyang Date: Tue, 23 Jan 2024 16:25:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92):=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E8=AE=A1=E5=88=92=E8=B5=84=E6=BA=90=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=8A=9F=E8=83=BD=E5=A2=9E=E5=8A=A0=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migration/3.0.0/dml/V3.0.0_11_1__data.sql | 6 +- .../sdk/constants/PermissionConstants.java | 4 +- .../src/main/resources/i18n/plan.properties | 3 + .../main/resources/i18n/plan_en_US.properties | 3 + .../main/resources/i18n/plan_zh_CN.properties | 3 + .../main/resources/i18n/plan_zh_TW.properties | 3 + .../main/resources/i18n/project.properties | 1 + .../resources/i18n/project_en_US.properties | 1 + .../resources/i18n/project_zh_CN.properties | 1 + .../resources/i18n/project_zh_TW.properties | 1 + .../project/dto/ModuleCountDTO.java | 4 + .../project/service/ModuleTreeService.java | 6 +- .../src/main/resources/permission.json | 9 - .../FileManagementControllerTests.java | 8 + .../controller/PersonalCenterController.java | 5 - .../system/controller/UserController.java | 2 +- .../src/main/resources/permission.json | 15 +- .../user/PersonalControllerTests.java | 5 - .../user/UserControllerPermissionTests.java | 6 +- .../constants/TestPlanResourceConfig.java | 12 + .../controller/TestPlanApiCaseController.java | 10 +- .../TestPlanApiScenarioController.java | 10 +- .../plan/controller/TestPlanController.java | 23 +- .../TestPlanFunctionalCaseController.java | 10 +- .../controller/TestPlanModuleController.java | 10 + .../dto/request/TestPlanTableRequest.java | 9 + .../plan/mapper/ExtTestPlanApiCaseMapper.java | 4 +- .../plan/mapper/ExtTestPlanApiCaseMapper.xml | 38 +-- .../mapper/ExtTestPlanApiScenarioMapper.java | 4 +- .../mapper/ExtTestPlanApiScenarioMapper.xml | 32 +- .../ExtTestPlanFunctionalCaseMapper.java | 4 +- .../ExtTestPlanFunctionalCaseMapper.xml | 32 +- .../plan/mapper/ExtTestPlanMapper.java | 2 + .../plan/mapper/ExtTestPlanMapper.xml | 5 + .../plan/mapper/ExtTestPlanModuleMapper.java | 2 + .../plan/mapper/ExtTestPlanModuleMapper.xml | 5 + .../plan/service/TestPlanApiCaseService.java | 29 +- .../service/TestPlanApiScenarioService.java | 34 +-- .../TestPlanFunctionalCaseService.java | 11 +- .../service/TestPlanManagementService.java | 36 +++ .../plan/service/TestPlanResourceService.java | 25 +- .../plan/service/TestPlanService.java | 5 +- .../src/main/resources/permission.json | 3 + .../plan/controller/TestPlanTests.java | 280 ++++++++++++++++-- .../plan/service/TestPlanTestService.java | 41 +++ 45 files changed, 535 insertions(+), 227 deletions(-) create mode 100644 backend/services/test-plan/src/main/java/io/metersphere/plan/constants/TestPlanResourceConfig.java diff --git a/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql b/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql index a3a7ec3d84..306d1f18b3 100644 --- a/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql +++ b/backend/framework/domain/src/main/resources/migration/3.0.0/dml/V3.0.0_11_1__data.sql @@ -39,8 +39,6 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL_API_KEY:READ+UPDATE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL_API_KEY:READ+DELETE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL_API_KEY:READ'); -INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL:READ'); -INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'SYSTEM_PERSONAL:READ+UPDATE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'PROJECT_TEST_PLAN_MODULE:READ'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'member', 'PROJECT_TEST_PLAN:READ'); @@ -96,7 +94,6 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_ENVIRONMENT:READ+DELETE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_ENVIRONMENT:READ+IMPORT'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_ENVIRONMENT:READ+EXPORT'); -INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE:READ'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ+ADD'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ+UPDATE'); @@ -198,6 +195,7 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+UPDATE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+DELETE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+EXECUTE'); +INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEST_PLAN:READ+ASSOCIATION'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_CUSTOM_FUNCTION:READ'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_CUSTOM_FUNCTION:READ+ADD'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_CUSTOM_FUNCTION:READ+UPDATE'); @@ -217,7 +215,6 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_ENVIRONMENT:READ+DELETE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_ENVIRONMENT:READ+IMPORT'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_ENVIRONMENT:READ+EXPORT'); -INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_FILE:READ'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_FILE_MANAGEMENT:READ'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_FILE_MANAGEMENT:READ+ADD'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_FILE_MANAGEMENT:READ+UPDATE'); @@ -318,6 +315,7 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+UPDATE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+DELETE'); INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+EXECUTE'); +INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_member', 'PROJECT_TEST_PLAN:READ+ASSOCIATION'); -- 初始化当前站点配置 INSERT into system_parameter values('base.url', 'http://127.0.0.1:8081', 'text'); -- 初始化prometheus站点配置 diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/PermissionConstants.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/PermissionConstants.java index a1f204ea21..bac7d80541 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/PermissionConstants.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/PermissionConstants.java @@ -66,6 +66,7 @@ public class PermissionConstants { public static final String SYSTEM_USER_ADD = "SYSTEM_USER:READ+ADD"; public static final String SYSTEM_USER_IMPORT = "SYSTEM_USER:READ+IMPORT"; public static final String SYSTEM_USER_UPDATE = "SYSTEM_USER:READ+UPDATE"; + public static final String SYSTEM_USER_INVITE = "SYSTEM_USER:READ+INVITE"; public static final String SYSTEM_USER_DELETE = "SYSTEM_USER:READ+DELETE"; /*------ end: SYSTEM_SERVICE_INTEGRATION ------*/ @@ -298,8 +299,6 @@ public class PermissionConstants { 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"; - public static final String SYSTEM_PERSONAL_READ = "SYSTEM_PERSONAL:READ"; - public static final String SYSTEM_PERSONAL_READ_UPDATE = "SYSTEM_PERSONAL:READ+UPDATE"; /*------ end: PERSONAL_CENTER ------*/ //测试计划 @@ -314,5 +313,6 @@ public class PermissionConstants { public static final String TEST_PLAN_READ_UPDATE = "PROJECT_TEST_PLAN:READ+UPDATE"; public static final String TEST_PLAN_READ_DELETE = "PROJECT_TEST_PLAN:READ+DELETE"; public static final String TEST_PLAN_READ_EXECUTE = "PROJECT_TEST_PLAN:READ+EXECUTE"; + public static final String TEST_PLAN_READ_ASSOCIATION = "PROJECT_TEST_PLAN:READ+ASSOCIATION"; /*------ end: TEST_PLAN ------*/ } diff --git a/backend/framework/sdk/src/main/resources/i18n/plan.properties b/backend/framework/sdk/src/main/resources/i18n/plan.properties index e70c17ac3a..6f87e15951 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan.properties @@ -10,6 +10,9 @@ test_plan.name.length_range=测试计划名称长度过长 test_plan.name.not_blank=测试计划名称不能为空 test_plan.name.exist=测试计划名称已存在 test_plan.too_many=测试计划数量不能超过{0}个 +test_plan.not.exist=测试计划不存在 +test_plan.drag.node.error=测试计划拖拽节点错误 +test_plan.drag.position.error=测试计划拖拽操作错误 test_plan.pass_threshold.max=测试计划通过阈值不得超过100 test_plan.status.length_range=测试计划状态长度过长 test_plan.status.not_blank=测试计划状态不能为空 diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties index afb1076fe5..8ee0cbedc8 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_en_US.properties @@ -10,6 +10,9 @@ test_plan.name.length_range=Test plan name length too long test_plan.name.not_blank=Test plan name cannot be empty test_plan.name.exist=Test plan name exist test_plan.too_many=Test plan cannot larger than {0} +test_plan.not.exist=Test plan not exist +test_plan.drag.node.error=Test plan drag node error +test_plan.drag.position.error=Test plan drag position error test_plan.pass_threshold.max=Test plan threshold max is 100 test_plan.status.length_range=Test plan status length too long test_plan.status.not_blank=Test plan status cannot be empty diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties index e70c17ac3a..6f87e15951 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_zh_CN.properties @@ -10,6 +10,9 @@ test_plan.name.length_range=测试计划名称长度过长 test_plan.name.not_blank=测试计划名称不能为空 test_plan.name.exist=测试计划名称已存在 test_plan.too_many=测试计划数量不能超过{0}个 +test_plan.not.exist=测试计划不存在 +test_plan.drag.node.error=测试计划拖拽节点错误 +test_plan.drag.position.error=测试计划拖拽操作错误 test_plan.pass_threshold.max=测试计划通过阈值不得超过100 test_plan.status.length_range=测试计划状态长度过长 test_plan.status.not_blank=测试计划状态不能为空 diff --git a/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties index 1751fcf346..491377a700 100644 --- a/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/plan_zh_TW.properties @@ -9,6 +9,9 @@ test_plan.parent_id.not_blank=測試計劃父id不能為空 test_plan.name.length_range=測試計劃名稱長度過長 test_plan.name.not_blank=測試計劃名稱不能為空 test_plan.name.exist=測試計劃名稱已存在 +test_plan.not.exist=測試計劃不存在 +test_plan.drag.node.error=測試計劃拖拽節點錯誤 +test_plan.drag.position.error=測試計劃拖拽操作錯誤 test_plan.too_many=測試計劃數量不能超過{0}個 test_plan.pass_threshold.max=測試計劃通過閾值不得超過100 test_plan.status.length_range=測試計劃狀態長度過長 diff --git a/backend/framework/sdk/src/main/resources/i18n/project.properties b/backend/framework/sdk/src/main/resources/i18n/project.properties index 3cc53b7792..24809f7011 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project.properties @@ -65,6 +65,7 @@ project_extend.project_id.not_blank=项目ID不能为空 project_extend.platform.length_range=平台长度必须在{min}-{max}之间 project_extend.platform.not_blank=平台不能为空 project.id.not_blank=ID不能为空 +project.module_menu.check.error=该项目的模块菜单检查失败 project.organization_id.length_range=组织ID长度必须在{min}-{max}之间 project.organization_id.not_blank=组织ID不能为空 project.name.length_range=名称长度必须在{min}-{max}之间 diff --git a/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties index 8b72aa960a..850793ceee 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project_en_US.properties @@ -77,6 +77,7 @@ project_extend.project_id.not_blank=Project ID is required project_extend.platform.length_range=Platform length must be between {min} and {max} project_extend.platform.not_blank=Platform is required project.id.not_blank=ID is required +project.module_menu.check.error=Project module menu check error project.organization_id.length_range=Organization ID length must be between {min} and {max} project.organization_id.not_blank=Organization ID is required project.name.length_range=Name length must be between {min} and {max} diff --git a/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties index 3bdeaf66e9..a14dc9d2a8 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project_zh_CN.properties @@ -77,6 +77,7 @@ project_extend.project_id.not_blank=项目ID不能为空 project_extend.platform.length_range=平台长度必须在{min}-{max}之间 project_extend.platform.not_blank=平台不能为空 project.id.not_blank=ID不能为空 +project.module_menu.check.error=该项目的模块菜单检查失败 project.organization_id.length_range=组织ID长度必须在{min}-{max}之间 project.organization_id.not_blank=组织ID不能为空 project.name.length_range=名称长度必须在{min}-{max}之间 diff --git a/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties index 1ef5acac2e..150ba9ccc6 100644 --- a/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/project_zh_TW.properties @@ -77,6 +77,7 @@ project_extend.project_id.not_blank=項目ID不能為空 project_extend.platform.length_range=平台長度必須在{min}-{max}之間 project_extend.platform.not_blank=平台不能為空 project.id.not_blank=ID不能為空 +project.module_menu.check.error=該項目的模塊菜單檢查失敗 project.organization_id.length_range=工作空間ID長度必須在{min}-{max}之間 project.organization_id.not_blank=工作空間ID不能為空 project.name.length_range=名稱長度必須在{min}-{max}之間 diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/dto/ModuleCountDTO.java b/backend/services/project-management/src/main/java/io/metersphere/project/dto/ModuleCountDTO.java index 999b010104..a266d37999 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/dto/ModuleCountDTO.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/dto/ModuleCountDTO.java @@ -1,8 +1,12 @@ package io.metersphere.project.dto; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; @Data +@NoArgsConstructor +@AllArgsConstructor public class ModuleCountDTO { private String moduleId; private int dataCount; diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java index 4a4b2e06e7..12122687a4 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/ModuleTreeService.java @@ -111,7 +111,7 @@ public abstract class ModuleTreeService { public NodeSortDTO getNodeSortDTO(NodeMoveRequest request, Function selectIdNodeFunc, Function selectPosNodeFunc) { if (StringUtils.equals(request.getDragNodeId(), request.getDropNodeId())) { //两种节点不能一样 - throw new MSException(Translator.get("invalid_parameter")); + throw new MSException(Translator.get("invalid_parameter") + ": drag node and drop node"); } BaseModule dragNode = selectIdNodeFunc.apply(request.getDragNodeId()); @@ -125,7 +125,7 @@ public abstract class ModuleTreeService { } BaseModule parentModule; - BaseModule previousNode = null; + BaseModule previousNode; BaseModule nextNode = null; if (request.getDropPosition() == 0) { //dropPosition=0: 放到dropNode节点内,最后一个节点之后 @@ -160,7 +160,7 @@ public abstract class ModuleTreeService { sortParam.setOperator(MOVE_POS_OPERATOR_LESS); previousNode = selectPosNodeFunc.apply(sortParam); } else { - throw new MSException(Translator.get("invalid_parameter")); + throw new MSException(Translator.get("invalid_parameter") + ": dropPosition"); } } diff --git a/backend/services/project-management/src/main/resources/permission.json b/backend/services/project-management/src/main/resources/permission.json index 1396f484f7..8caabfe62c 100644 --- a/backend/services/project-management/src/main/resources/permission.json +++ b/backend/services/project-management/src/main/resources/permission.json @@ -76,15 +76,6 @@ } ] }, - { - "id": "PROJECT_FILE", - "name": "permission.project_file.name", - "permissions": [ - { - "id": "PROJECT_FILE:READ" - } - ] - }, { "id": "PROJECT_TEMPLATE", "name": "permission.project_template.name", diff --git a/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java b/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java index 1b4e70ed4d..cd1e0e93fe 100644 --- a/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java +++ b/backend/services/project-management/src/test/java/io/metersphere/project/controller/filemanagement/FileManagementControllerTests.java @@ -1,6 +1,7 @@ package io.metersphere.project.controller.filemanagement; import io.metersphere.project.domain.*; +import io.metersphere.project.dto.ModuleCountDTO; import io.metersphere.project.dto.filemanagement.FileAssociationDTO; import io.metersphere.project.dto.filemanagement.FileLogRecord; import io.metersphere.project.dto.filemanagement.request.*; @@ -2463,6 +2464,13 @@ public class FileManagementControllerTests extends BaseTest { error = true; } Assertions.assertTrue(error); + + List treeNodeList = new ArrayList<>() {{ + this.add(new ModuleCountDTO(IDGenerator.nextStr(), 1)); + this.add(new ModuleCountDTO(IDGenerator.nextStr(), 2)); + this.add(new ModuleCountDTO(IDGenerator.nextStr(), 3)); + }}; + fileModuleService.getAllCount(treeNodeList); } @Test diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PersonalCenterController.java b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PersonalCenterController.java index c1002b53a0..c394474701 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PersonalCenterController.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/PersonalCenterController.java @@ -1,6 +1,5 @@ package io.metersphere.system.controller; -import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.exception.MSException; import io.metersphere.system.dto.request.user.PersonalUpdatePasswordRequest; import io.metersphere.system.dto.request.user.PersonalUpdateRequest; @@ -14,7 +13,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; -import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -28,7 +26,6 @@ public class PersonalCenterController { @GetMapping("/get/{id}") @Operation(summary = "个人中心-获取信息") - @RequiresPermissions(PermissionConstants.SYSTEM_PERSONAL_READ) public PersonalDTO getInformation(@PathVariable String id) { this.checkPermission(id); return userService.getPersonalById(id); @@ -36,7 +33,6 @@ public class PersonalCenterController { @PostMapping("/update-info") @Operation(summary = "个人中心-修改信息") - @RequiresPermissions(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE) @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateAccountLog(#request)", msClass = UserLogService.class) public boolean updateUser(@Validated @RequestBody PersonalUpdateRequest request) { this.checkPermission(request.getId()); @@ -45,7 +41,6 @@ public class PersonalCenterController { @PostMapping("/update-password") @Operation(summary = "个人中心-修改密码") - @RequiresPermissions(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE) @Log(type = OperationLogType.UPDATE, expression = "#msClass.updatePasswordLog(#request)", msClass = UserLogService.class) public boolean updateUser(@Validated @RequestBody PersonalUpdatePasswordRequest request) { this.checkPermission(request.getId()); diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/UserController.java b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/UserController.java index 47b12f4086..db23cd7430 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/UserController.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/UserController.java @@ -187,7 +187,7 @@ public class UserController { @PostMapping("/invite") @Operation(summary = "系统设置-系统-用户-邀请用户注册") - @RequiresPermissions(PermissionConstants.SYSTEM_USER_ADD) + @RequiresPermissions(PermissionConstants.SYSTEM_USER_INVITE) public UserInviteResponse invite(@Validated @RequestBody UserInviteRequest request) { return userService.saveInviteRecord(request, SessionUtils.getUser()); } diff --git a/backend/services/system-setting/src/main/resources/permission.json b/backend/services/system-setting/src/main/resources/permission.json index eeb57e807e..837bfc472e 100644 --- a/backend/services/system-setting/src/main/resources/permission.json +++ b/backend/services/system-setting/src/main/resources/permission.json @@ -20,6 +20,9 @@ { "id": "SYSTEM_USER:READ+UPDATE" }, + { + "id": "SYSTEM_USER:READ+INVITE" + }, { "id": "SYSTEM_USER:READ+DELETE" } @@ -296,18 +299,6 @@ "name": "permission.my_settings", "type": "SYSTEM", "children": [ - { - "id": "PERSONAL_INFO", - "name": "permission.my_settings_personal_info", - "permissions": [ - { - "id": "SYSTEM_PERSONAL:READ" - }, - { - "id": "SYSTEM_PERSONAL:READ+UPDATE" - } - ] - }, { "id": "API_KEYS", "name": "permission.api_keys", diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/PersonalControllerTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/PersonalControllerTests.java index a730c7d7f8..bdbba8edc9 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/PersonalControllerTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/PersonalControllerTests.java @@ -1,6 +1,5 @@ package io.metersphere.system.controller.user; -import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.util.CodingUtils; import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.RsaKey; @@ -49,8 +48,6 @@ public class PersonalControllerTests extends BaseTest { //查询非登录人 this.requestGet(String.format(PersonalRequestUtils.URL_PERSONAL_GET, IDGenerator.nextStr())).andExpect(status().is5xxServerError()); - //权限校验 - this.requestGetPermissionTest(PermissionConstants.SYSTEM_PERSONAL_READ, String.format(PersonalRequestUtils.URL_PERSONAL_GET, loginUser)); } private UserDTO selectUserDTO(String id) throws Exception { @@ -150,7 +147,6 @@ public class PersonalControllerTests extends BaseTest { request.setEmail("admin@metersphere.io"); request.setUsername("'Administrator'"); request.setPhone("12345678901"); - this.requestPostPermissionTest(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE, PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO, request); this.checkLog(loginUser, OperationLogType.UPDATE, PersonalRequestUtils.URL_PERSONAL_UPDATE_INFO); } @@ -229,7 +225,6 @@ public class PersonalControllerTests extends BaseTest { request.setId(loginUser); request.setOldPassword(RsaUtils.publicEncrypt("metersphere222", rsaKey.getPublicKey())); request.setNewPassword(RsaUtils.publicEncrypt("metersphere", rsaKey.getPublicKey())); - this.requestPostPermissionTest(PermissionConstants.SYSTEM_PERSONAL_READ_UPDATE, PersonalRequestUtils.URL_PERSONAL_UPDATE_PASSWORD, request); //最后检查密码是否回归原密码 example.clear(); diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/UserControllerPermissionTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/UserControllerPermissionTests.java index da2da4ce0d..87207ee630 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/UserControllerPermissionTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/user/UserControllerPermissionTests.java @@ -1,13 +1,13 @@ package io.metersphere.system.controller.user; -import io.metersphere.system.base.BaseTest; import io.metersphere.sdk.constants.PermissionConstants; -import io.metersphere.system.dto.table.TableBatchProcessDTO; +import io.metersphere.system.base.BaseTest; import io.metersphere.system.dto.UserCreateInfo; import io.metersphere.system.dto.request.UserInviteRequest; import io.metersphere.system.dto.request.user.UserChangeEnableRequest; import io.metersphere.system.dto.request.user.UserRoleBatchRelationRequest; import io.metersphere.system.dto.response.UserSelectOption; +import io.metersphere.system.dto.table.TableBatchProcessDTO; import io.metersphere.system.utils.user.UserParamUtils; import io.metersphere.system.utils.user.UserRequestUtils; import org.junit.jupiter.api.MethodOrderer; @@ -117,7 +117,7 @@ public class UserControllerPermissionTests extends BaseTest { UserInviteRequest userInviteRequest = new UserInviteRequest(); userInviteRequest.setUserRoleIds(Collections.singletonList("member")); userInviteRequest.setInviteEmails(Collections.singletonList("tianyang.song.invite.permission.1@test.email")); - this.requestPostPermissionTest(PermissionConstants.SYSTEM_USER_ADD, UserRequestUtils.URL_INVITE, userInviteRequest); + this.requestPostPermissionTest(PermissionConstants.SYSTEM_USER_INVITE, UserRequestUtils.URL_INVITE, userInviteRequest); } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/TestPlanResourceConfig.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/TestPlanResourceConfig.java new file mode 100644 index 0000000000..374d2b3c71 --- /dev/null +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/constants/TestPlanResourceConfig.java @@ -0,0 +1,12 @@ +package io.metersphere.plan.constants; + +public class TestPlanResourceConfig { + public static final String CHECK_TYPE_PROJECT = "project"; + public static final String CHECK_TYPE_TEST_PLAN = "testPlan"; + public static final String CHECK_TYPE_TEST_PLAN_MODULE = "testPlanModule"; + + public static final String CONFIG_TEST_PLAN = "testPlan"; + public static final String CONFIG_TEST_PLAN_FUNCTIONAL_CASE = "caseManagement"; + public static final String CONFIG_TEST_PLAN_API_CASE = "apiTest"; + public static final String CONFIG_TEST_PLAN_API_SCENARIO = "apiTest"; +} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java index c6a119ee17..2c8ae01bac 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java @@ -1,11 +1,13 @@ package io.metersphere.plan.controller; +import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.dto.LogInsertModule; import io.metersphere.plan.dto.request.ResourceSortRequest; import io.metersphere.plan.dto.request.TestPlanAssociationRequest; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; import io.metersphere.plan.service.TestPlanApiCaseService; +import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.security.CheckOwner; @@ -20,19 +22,24 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Collections; + @Tag(name = "测试计划接口用例") @RestController @RequestMapping("/test-plan/api/case") public class TestPlanApiCaseController { + @Resource + private TestPlanManagementService testPlanManagementService; @Resource private TestPlanApiCaseService testPlanApiCaseService; @PostMapping(value = "/association") @Operation(summary = "测试计划接口用例-关联接口用例") - @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ASSOCIATION) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") public TestPlanAssociationResponse association(@Validated @RequestBody TestPlanAssociationRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_API_CASE)); return testPlanApiCaseService.association(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/case/association", HttpMethodConstants.POST.name())); } @@ -41,6 +48,7 @@ public class TestPlanApiCaseController { @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") public TestPlanResourceSortResponse sortNode(@Validated @RequestBody ResourceSortRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_API_CASE)); return testPlanApiCaseService.sortNode(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/case/sort", HttpMethodConstants.POST.name())); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java index b0af924b23..11fba1c26a 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java @@ -1,11 +1,13 @@ package io.metersphere.plan.controller; +import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.dto.LogInsertModule; import io.metersphere.plan.dto.request.ResourceSortRequest; import io.metersphere.plan.dto.request.TestPlanAssociationRequest; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; import io.metersphere.plan.service.TestPlanApiScenarioService; +import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.security.CheckOwner; @@ -20,19 +22,24 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Collections; + @Tag(name = "测试计划场景用例") @RestController @RequestMapping("/test-plan/api/scenario") public class TestPlanApiScenarioController { + @Resource + private TestPlanManagementService testPlanManagementService; @Resource private TestPlanApiScenarioService testPlanApiScenarioService; @PostMapping(value = "/association") @Operation(summary = "测试计划场景用例-关联接口用例") - @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ASSOCIATION) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") public TestPlanAssociationResponse association(@Validated @RequestBody TestPlanAssociationRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_API_SCENARIO)); return testPlanApiScenarioService.association(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/scenario/association", HttpMethodConstants.POST.name())); } @@ -41,6 +48,7 @@ public class TestPlanApiScenarioController { @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") public TestPlanResourceSortResponse sortNode(@Validated @RequestBody ResourceSortRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_API_SCENARIO)); return testPlanApiScenarioService.sortNode(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/api/scenario/sort", HttpMethodConstants.POST.name())); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java index baf9abd6d3..af54f62229 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanController.java @@ -1,5 +1,6 @@ package io.metersphere.plan.controller; +import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest; import io.metersphere.plan.dto.request.TestPlanCreateRequest; import io.metersphere.plan.dto.request.TestPlanTableRequest; @@ -21,6 +22,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -33,11 +35,13 @@ public class TestPlanController { @Resource private TestPlanManagementService testPlanManagementService; + @PostMapping("/page") @Operation(summary = "测试计划-表格分页查询") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") public Pager> page(@Validated @RequestBody TestPlanTableRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); return testPlanManagementService.page(request); } @@ -46,6 +50,7 @@ public class TestPlanController { @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @CheckOwner(resourceId = "#id", resourceType = "test_plan") public TestPlanCountResponse getCount(@PathVariable String id) { + testPlanManagementService.checkModuleIsOpen(id, TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); return testPlanService.getCount(id); } @@ -54,8 +59,8 @@ public class TestPlanController { @Operation(summary = "测试计划-模块统计") @RequiresPermissions(PermissionConstants.TEST_PLAN_READ) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") - public Map moduleCount(@Validated @RequestBody TestPlanTableRequest - request) { + public Map moduleCount(@Validated @RequestBody TestPlanTableRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); return testPlanManagementService.moduleCount(request); } @@ -65,6 +70,7 @@ public class TestPlanController { @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ADD) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") public String add(@Validated @RequestBody TestPlanCreateRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); return testPlanService.add(request, SessionUtils.getUserId(), "/test-plan/add", HttpMethodConstants.POST.name()); } @@ -73,6 +79,7 @@ public class TestPlanController { @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) @CheckOwner(resourceId = "#request.getId()", resourceType = "test_plan") public String add(@Validated @RequestBody TestPlanUpdateRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); return testPlanService.update(request, SessionUtils.getUserId(), "/test-plan/update", HttpMethodConstants.POST.name()); } @@ -82,6 +89,7 @@ public class TestPlanController { @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_DELETE) @CheckOwner(resourceId = "#id", resourceType = "test_plan") public void delete(@NotBlank @PathVariable String id) { + testPlanManagementService.checkModuleIsOpen(id, TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); testPlanService.delete(id, SessionUtils.getUserId(), "/test-plan/delete", HttpMethodConstants.GET.name()); } @@ -91,19 +99,10 @@ public class TestPlanController { @RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DELETE) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") public void delete(@Validated @RequestBody TestPlanBatchProcessRequest request) throws Exception { + testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN)); testPlanService.batchDelete(request, SessionUtils.getUserId(), "/test-plan/batch-delete", HttpMethodConstants.POST.name()); } - /* - todo 更新接口(具体字段未确定) - @PostMapping(value = "/update") - @Operation(summary = "项目管理-文件管理-修改文件") - @RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE) - @CheckOwner(resourceId = "#request.getId()", resourceType = "file_metadata") - public void update(@Validated @RequestBody FileUpdateRequest request) throws Exception { - } - */ - //todo 关注测试计划接口 diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java index d35468cc19..488a8e3ba9 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanFunctionalCaseController.java @@ -1,11 +1,13 @@ package io.metersphere.plan.controller; +import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.dto.LogInsertModule; import io.metersphere.plan.dto.request.ResourceSortRequest; import io.metersphere.plan.dto.request.TestPlanAssociationRequest; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; import io.metersphere.plan.service.TestPlanFunctionalCaseService; +import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.security.CheckOwner; @@ -20,19 +22,24 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Collections; + @RestController @Tag(name = "测试计划功能用例") @RequestMapping("/test-plan/functional/case") public class TestPlanFunctionalCaseController { + @Resource + private TestPlanManagementService testPlanManagementService; @Resource private TestPlanFunctionalCaseService testPlanFunctionalCaseService; @PostMapping(value = "/association") @Operation(summary = "测试计划功能用例-关联功能用例") - @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_ASSOCIATION) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") public TestPlanAssociationResponse association(@Validated @RequestBody TestPlanAssociationRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE)); return testPlanFunctionalCaseService.association(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/association", HttpMethodConstants.POST.name())); } @@ -41,6 +48,7 @@ public class TestPlanFunctionalCaseController { @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE) @CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan") public TestPlanResourceSortResponse sortNode(@Validated @RequestBody ResourceSortRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getTestPlanId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN_FUNCTIONAL_CASE)); return testPlanFunctionalCaseService.sortNode(request, new LogInsertModule(SessionUtils.getUserId(), "/test-plan/functional/case/sort", HttpMethodConstants.POST.name())); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanModuleController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanModuleController.java index d2bf8eeea4..8bb28c7465 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanModuleController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanModuleController.java @@ -1,7 +1,9 @@ package io.metersphere.plan.controller; +import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.dto.request.TestPlanModuleCreateRequest; import io.metersphere.plan.dto.request.TestPlanModuleUpdateRequest; +import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanModuleService; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.PermissionConstants; @@ -16,6 +18,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.Collections; import java.util.List; @Tag(name = "测试计划管理-模块树") @@ -25,12 +28,15 @@ public class TestPlanModuleController { @Resource private TestPlanModuleService testPlanModuleService; + @Resource + private TestPlanManagementService testPlanManagementService; @GetMapping("/tree/{projectId}") @Operation(summary = "测试计划管理-模块树-查找模块") @RequiresPermissions(PermissionConstants.TEST_PLAN_MODULE_READ) @CheckOwner(resourceId = "#projectId", resourceType = "project") public List getTree(@PathVariable String projectId) { + testPlanManagementService.checkModuleIsOpen(projectId, TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN)); return testPlanModuleService.getTree(projectId); } @@ -39,6 +45,7 @@ public class TestPlanModuleController { @RequiresPermissions(PermissionConstants.TEST_PLAN_MODULE_READ_ADD) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") public String add(@RequestBody @Validated TestPlanModuleCreateRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN)); return testPlanModuleService.add(request, SessionUtils.getUserId(),"/test-plan/module/add", HttpMethodConstants.POST.name()); } @@ -47,6 +54,7 @@ public class TestPlanModuleController { @RequiresPermissions(PermissionConstants.TEST_PLAN_MODULE_READ_UPDATE) @CheckOwner(resourceId = "#request.getId()", resourceType = "file_module") public boolean list(@RequestBody @Validated TestPlanModuleUpdateRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN_MODULE, Collections.singletonList(TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN)); testPlanModuleService.update(request, SessionUtils.getUserId(),"/test-plan/module/update", HttpMethodConstants.POST.name()); return true; } @@ -56,6 +64,7 @@ public class TestPlanModuleController { @RequiresPermissions(PermissionConstants.TEST_PLAN_MODULE_READ_DELETE) @CheckOwner(resourceId = "#deleteId", resourceType = "file_module") public void deleteNode(@PathVariable String deleteId) { + testPlanManagementService.checkModuleIsOpen(deleteId, TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN_MODULE, Collections.singletonList(TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN)); testPlanModuleService.deleteModule(deleteId, SessionUtils.getUserId(),"/test-plan/module/delete",HttpMethodConstants.GET.name()); } @@ -64,6 +73,7 @@ public class TestPlanModuleController { @RequiresPermissions(PermissionConstants.TEST_PLAN_MODULE_READ_UPDATE) @CheckOwner(resourceId = "#request.getDragNodeId()", resourceType = "test_plan_module") public void moveNode(@Validated @RequestBody NodeMoveRequest request) { + testPlanManagementService.checkModuleIsOpen(request.getDragNodeId(), TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN_MODULE, Collections.singletonList(TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN)); testPlanModuleService.moveNode(request, SessionUtils.getUserId(),"/test-plan/module/move",HttpMethodConstants.POST.name()); } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java index 8b73de685a..34782b0dd4 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/dto/request/TestPlanTableRequest.java @@ -29,4 +29,13 @@ public class TestPlanTableRequest extends BasePageRequest { public boolean conditionIsEmpty() { return StringUtils.isEmpty(this.getKeyword()) && MapUtils.isEmpty(this.getFilter()) && MapUtils.isEmpty(this.getCombine()); } + + public String getSortString() { + if (StringUtils.isEmpty(super.getSortString())) { + return "t.update_time desc"; + } else { + return "t." + super.getSortString(); + } + + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java index 2065fade1e..40d5c5d3b4 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.java @@ -15,9 +15,7 @@ public interface ExtTestPlanApiCaseMapper { Long getMaxPosByTestPlanId(String testPlanId); - List getIdByIds(ResourceSelectParam resourceSelectParam); - - List getIdByModuleIds(ResourceSelectParam resourceSelectParam); + List getIdByParam(ResourceSelectParam resourceSelectParam); AssociationNode selectDragInfoById(String id); diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml index 627b7728a6..062a9129df 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanApiCaseMapper.xml @@ -18,34 +18,25 @@ FROM test_plan_api_case WHERE test_plan_id = #{0} - - + - - - - + WHERE t.project_id = #{projectId} diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java index 37986b66da..19d2f75f12 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.java @@ -27,4 +27,6 @@ public interface ExtTestPlanModuleMapper { List selectChildrenIdsSortByPos(String parentId); String selectNameById(String id); + + String selectProjectIdByModuleId(String id); } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml index e4c7d716f8..a2ac1d14e6 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/mapper/ExtTestPlanModuleMapper.xml @@ -68,4 +68,9 @@ FROM test_plan_module WHERE id = #{0} + \ No newline at end of file diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java index 78149f7020..8169b63af2 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java @@ -13,7 +13,6 @@ import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; import io.metersphere.plan.mapper.ExtTestPlanApiCaseMapper; import io.metersphere.plan.mapper.TestPlanApiCaseMapper; -import io.metersphere.plan.mapper.TestPlanConfigMapper; import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.TestPlanResourceConstants; @@ -42,8 +41,6 @@ public class TestPlanApiCaseService extends TestPlanResourceService { @Resource private ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper; @Resource - private TestPlanConfigMapper testPlanConfigMapper; - @Resource private TestPlanResourceLogService testPlanResourceLogService; @Resource private TestPlanMapper testPlanMapper; @@ -87,8 +84,7 @@ public class TestPlanApiCaseService extends TestPlanResourceService { TestPlanResourceConstants.RESOURCE_API_CASE, request, logInsertModule, - extTestPlanApiCaseMapper::getIdByIds, - extTestPlanApiCaseMapper::getIdByModuleIds, + extTestPlanApiCaseMapper::getIdByParam, this::saveTestPlanResource); } @@ -116,21 +112,18 @@ public class TestPlanApiCaseService extends TestPlanResourceService { TestPlanResourceSortResponse response = new TestPlanResourceSortResponse(); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId()); TestPlanApiCase dragNode = testPlanApiCaseMapper.selectByPrimaryKey(request.getDragNodeId()); - if (dragNode == null && testPlan == null) { + if (dragNode == null) { throw new MSException("test_plan.drag.node.error"); } - if (request.getDropPosition() == -1 || request.getDropPosition() == 1) { - AssociationNodeSortDTO sortDTO = super.getNodeSortDTO( - request, - extTestPlanApiCaseMapper::selectDragInfoById, - extTestPlanApiCaseMapper::selectNodeByPosOperator - ); - this.sort(sortDTO); - response.setSortNodeNum(1); - testPlanResourceLogService.saveSortLog(testPlan, request.getDragNodeId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule)); - } else { - throw new MSException("test_plan.drag.position.error"); - } + AssociationNodeSortDTO sortDTO = super.getNodeSortDTO( + request, + extTestPlanApiCaseMapper::selectDragInfoById, + extTestPlanApiCaseMapper::selectNodeByPosOperator + ); + this.sort(sortDTO); + response.setSortNodeNum(1); + testPlanResourceLogService.saveSortLog(testPlan, request.getDragNodeId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule)); return response; + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java index a3926b8802..65dc376e8a 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java @@ -11,7 +11,10 @@ import io.metersphere.plan.dto.request.ResourceSortRequest; import io.metersphere.plan.dto.request.TestPlanAssociationRequest; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; -import io.metersphere.plan.mapper.*; +import io.metersphere.plan.mapper.ExtTestPlanApiCaseMapper; +import io.metersphere.plan.mapper.ExtTestPlanApiScenarioMapper; +import io.metersphere.plan.mapper.TestPlanApiScenarioMapper; +import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.TestPlanResourceConstants; import io.metersphere.sdk.exception.MSException; @@ -39,8 +42,6 @@ public class TestPlanApiScenarioService extends TestPlanResourceService { @Resource private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper; @Resource - private TestPlanConfigMapper testPlanConfigMapper; - @Resource private TestPlanResourceLogService testPlanResourceLogService; @Resource private TestPlanMapper testPlanMapper; @@ -84,8 +85,7 @@ public class TestPlanApiScenarioService extends TestPlanResourceService { TestPlanResourceConstants.RESOURCE_API_CASE, request, logInsertModule, - extTestPlanApiScenarioMapper::getIdByIds, - extTestPlanApiScenarioMapper::getIdByModuleIds, + extTestPlanApiScenarioMapper::getIdByParam, this::saveTestPlanResource); } @@ -110,24 +110,20 @@ public class TestPlanApiScenarioService extends TestPlanResourceService { } public TestPlanResourceSortResponse sortNode(ResourceSortRequest request, LogInsertModule logInsertModule) { - TestPlanResourceSortResponse response = new TestPlanResourceSortResponse(); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId()); TestPlanApiScenario dragNode = testPlanApiScenarioMapper.selectByPrimaryKey(request.getDragNodeId()); - if (dragNode == null && testPlan == null) { + if (dragNode == null) { throw new MSException("test_plan.drag.node.error"); } - if (request.getDropPosition() == -1 || request.getDropPosition() == 1) { - AssociationNodeSortDTO sortDTO = super.getNodeSortDTO( - request, - extTestPlanApiScenarioMapper::selectDragInfoById, - extTestPlanApiScenarioMapper::selectNodeByPosOperator - ); - this.sort(sortDTO); - response.setSortNodeNum(1); - testPlanResourceLogService.saveSortLog(testPlan, request.getDragNodeId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule)); - } else { - throw new MSException("test_plan.drag.position.error"); - } + TestPlanResourceSortResponse response = new TestPlanResourceSortResponse(); + AssociationNodeSortDTO sortDTO = super.getNodeSortDTO( + request, + extTestPlanApiScenarioMapper::selectDragInfoById, + extTestPlanApiScenarioMapper::selectNodeByPosOperator + ); + this.sort(sortDTO); + response.setSortNodeNum(1); + testPlanResourceLogService.saveSortLog(testPlan, request.getDragNodeId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule)); return response; } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java index dc20c68410..d037449601 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanFunctionalCaseService.java @@ -12,12 +12,12 @@ import io.metersphere.plan.dto.request.TestPlanAssociationRequest; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper; -import io.metersphere.plan.mapper.TestPlanConfigMapper; import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper; import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.TestPlanResourceConstants; import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.util.Translator; import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.NumGenerator; import jakarta.annotation.Resource; @@ -40,8 +40,6 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService { @Resource private ExtTestPlanFunctionalCaseMapper extTestPlanFunctionalCaseMapper; @Resource - private TestPlanConfigMapper testPlanConfigMapper; - @Resource private SqlSessionFactory sqlSessionFactory; @Resource private TestPlanResourceLogService testPlanResourceLogService; @@ -87,8 +85,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService { TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE, request, logInsertModule, - extTestPlanFunctionalCaseMapper::getIdByIds, - extTestPlanFunctionalCaseMapper::getIdByModuleIds, + extTestPlanFunctionalCaseMapper::getIdByParam, this::saveTestPlanResource); } @@ -115,8 +112,8 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService { public TestPlanResourceSortResponse sortNode(ResourceSortRequest request, LogInsertModule logInsertModule) { TestPlanFunctionalCase dragNode = testPlanFunctionalCaseMapper.selectByPrimaryKey(request.getDragNodeId()); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId()); - if (dragNode == null && testPlan == null) { - throw new MSException("test_plan.drag.node.error"); + if (dragNode == null) { + throw new MSException(Translator.get("test_plan.drag.node.error")); } TestPlanResourceSortResponse response = new TestPlanResourceSortResponse(); AssociationNodeSortDTO sortDTO = super.getNodeSortDTO( diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java index 4d83d52412..71b45c336c 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanManagementService.java @@ -2,11 +2,19 @@ package io.metersphere.plan.service; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; +import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.dto.TestPlanQueryConditions; import io.metersphere.plan.dto.request.TestPlanTableRequest; import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.mapper.ExtTestPlanMapper; +import io.metersphere.plan.mapper.ExtTestPlanModuleMapper; +import io.metersphere.project.domain.Project; import io.metersphere.project.dto.ModuleCountDTO; +import io.metersphere.project.mapper.ProjectMapper; +import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.util.JSON; +import io.metersphere.sdk.util.Translator; +import io.metersphere.system.service.CommonProjectService; import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.Pager; import jakarta.annotation.Resource; @@ -23,6 +31,12 @@ public class TestPlanManagementService { @Resource private ExtTestPlanMapper extTestPlanMapper; @Resource + private ProjectMapper projectMapper; + @Resource + private ExtTestPlanModuleMapper extTestPlanModuleMapper; + @Resource + private CommonProjectService commonProjectService; + @Resource private TestPlanModuleService testPlanModuleService; public Map moduleCount(TestPlanTableRequest request) { @@ -65,4 +79,26 @@ public class TestPlanManagementService { }); return testPlanResponses; } + + public void checkModuleIsOpen(String resourceId, String resourceType, List moduleMenus) { + Project project; + + if (StringUtils.equals(resourceType, TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN)) { + project = projectMapper.selectByPrimaryKey(extTestPlanMapper.selectProjectIdByTestPlanId(resourceId)); + } else if (StringUtils.equals(resourceType, TestPlanResourceConfig.CHECK_TYPE_TEST_PLAN_MODULE)) { + project = projectMapper.selectByPrimaryKey(extTestPlanModuleMapper.selectProjectIdByModuleId(resourceId)); + } else if (StringUtils.equals(resourceType, TestPlanResourceConfig.CHECK_TYPE_PROJECT)) { + project = projectMapper.selectByPrimaryKey(resourceId); + } else { + throw new MSException(Translator.get("project.module_menu.check.error")); + } + + if (project == null || StringUtils.isEmpty(project.getModuleSetting())) { + throw new MSException(Translator.get("project.module_menu.check.error")); + } + List projectModuleMenus = JSON.parseArray(project.getModuleSetting(), String.class); + if (!projectModuleMenus.containsAll(moduleMenus)) { + throw new MSException(Translator.get("project.module_menu.check.error")); + } + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanResourceService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanResourceService.java index e7aa10dc32..980d1bef0e 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanResourceService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanResourceService.java @@ -60,8 +60,7 @@ public abstract class TestPlanResourceService { String resourceType, TestPlanAssociationRequest request, @Validated LogInsertModule logInsertModule, - Function> selectByResourceIdFunc, - Function> selectByModuleIdFunc, + Function> getIdByParam, Consumer saveResourceFunc) { TestPlanAssociationResponse response = new TestPlanAssociationResponse(); if (request.isEmpty()) { @@ -70,19 +69,11 @@ public abstract class TestPlanResourceService { TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestPlanId()); TestPlanConfig testPlanConfig = testPlanConfigMapper.selectByPrimaryKey(request.getTestPlanId()); boolean repeatCase = testPlanConfig.getRepeatCase(); - List associationIdList = new ArrayList<>(); - if (CollectionUtils.isNotEmpty(request.getSelectIds())) { - //获取有效ID - associationIdList.addAll( - selectByResourceIdFunc.apply( - new ResourceSelectParam(request.getTestPlanId(), request.getSelectIds(), null, repeatCase, request.getOrderString()))); - } - if (CollectionUtils.isNotEmpty(request.getSelectModuleIds())) { - //获取有效ID - associationIdList.addAll( - selectByModuleIdFunc.apply( - new ResourceSelectParam(request.getTestPlanId(), null, request.getSelectModuleIds(), repeatCase, request.getOrderString()))); - } + //获取有效ID + List associationIdList = + getIdByParam.apply( + new ResourceSelectParam(request.getTestPlanId(), request.getSelectIds(), request.getSelectModuleIds(), repeatCase, request.getOrderString())); + associationIdList = new ArrayList<>(associationIdList.stream().distinct().toList()); associationIdList.removeAll(request.getExcludeIds()); if (CollectionUtils.isNotEmpty(associationIdList)) { @@ -105,7 +96,7 @@ public abstract class TestPlanResourceService { public AssociationNodeSortDTO getNodeSortDTO(ResourceSortRequest request, Function selectIdNodeFunc, Function selectPosNodeFunc) { if (StringUtils.equals(request.getDragNodeId(), request.getDropNodeId())) { //两种节点不能一样 - throw new MSException(Translator.get("invalid_parameter")); + throw new MSException(Translator.get("invalid_parameter") + ": drag node and drop node"); } AssociationNode dragNode = selectIdNodeFunc.apply(request.getDragNodeId()); @@ -139,7 +130,7 @@ public abstract class TestPlanResourceService { sortParam.setOperator(MOVE_POS_OPERATOR_LESS); previousNode = selectPosNodeFunc.apply(sortParam); } else { - throw new MSException(Translator.get("invalid_parameter")); + throw new MSException(Translator.get("invalid_parameter") + ": dropPosition"); } return new AssociationNodeSortDTO(request.getTestPlanId(), dragNode, previousNode, nextNode); diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java index 33019992c6..41326cb2b1 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanService.java @@ -67,7 +67,7 @@ public class TestPlanService { TestPlanModuleExample example = new TestPlanModuleExample(); example.createCriteria().andIdEqualTo(moduleId); if (testPlanModuleMapper.countByExample(example) == 0) { - throw new MSException("module.not.exist"); + throw new MSException(Translator.get("module.not.exist")); } } } @@ -242,9 +242,6 @@ public class TestPlanService { public String update(TestPlanUpdateRequest request, String userId, String requestUrl, String requestMethod) { TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getId()); - if (testPlan == null) { - throw new MSException("test_plan.not.exist"); - } if (!ObjectUtils.allNull(request.getName(), request.getModuleId(), request.getTags(), request.getPlannedEndTime(), request.getPlannedStartTime(), request.getDescription(), request.getTestPlanGroupId())) { TestPlan updateTestPlan = new TestPlan(); updateTestPlan.setId(request.getId()); diff --git a/backend/services/test-plan/src/main/resources/permission.json b/backend/services/test-plan/src/main/resources/permission.json index 60a2e6254d..842820d9a6 100644 --- a/backend/services/test-plan/src/main/resources/permission.json +++ b/backend/services/test-plan/src/main/resources/permission.json @@ -38,6 +38,9 @@ { "id": "PROJECT_TEST_PLAN:READ+DELETE" }, + { + "id": "PROJECT_TEST_PLAN:READ+ASSOCIATION" + }, { "id": "PROJECT_TEST_PLAN:READ+EXECUTE" } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java index 13b5eb777b..1d49bf9aec 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanTests.java @@ -3,12 +3,14 @@ package io.metersphere.plan.controller; import io.metersphere.api.domain.ApiScenario; import io.metersphere.api.domain.ApiTestCase; import io.metersphere.functional.domain.FunctionalCase; +import io.metersphere.plan.constants.TestPlanResourceConfig; import io.metersphere.plan.domain.*; import io.metersphere.plan.dto.request.*; import io.metersphere.plan.dto.response.TestPlanAssociationResponse; import io.metersphere.plan.dto.response.TestPlanResourceSortResponse; import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.mapper.TestPlanMapper; +import io.metersphere.plan.service.TestPlanManagementService; import io.metersphere.plan.service.TestPlanModuleService; import io.metersphere.plan.service.TestPlanService; import io.metersphere.plan.service.TestPlanTestService; @@ -70,15 +72,12 @@ public class TestPlanTests extends BaseTest { private static List preliminaryTreeNodes = new ArrayList<>(); - @Resource - private CommonProjectService commonProjectService; @Resource private TestPlanModuleMapper testPlanModuleMapper; @Resource - private TestPlanMapper testPlanMapper; - @Resource private TestPlanModuleService testPlanModuleService; - + @Resource + private CommonProjectService commonProjectService; @Resource private TestPlanTestService testPlanTestService; @@ -125,6 +124,8 @@ public class TestPlanTests extends BaseTest { private static TestPlan simpleTestPlan; //允许重复添加用例的测试计划 private static TestPlan repeatCaseTestPlan; + + private static final String[] PROJECT_MODULE = new String[]{"workstation", "testPlan", "bugManagement", "caseManagement", "apiTest", "uiTest", "loadTest"}; @BeforeEach public void initTestData() { //文件管理专用项目 @@ -135,9 +136,22 @@ public class TestPlanTests extends BaseTest { initProject.setDescription("建国创建的文件管理专用项目"); initProject.setEnable(true); project = commonProjectService.add(initProject, "admin", "/organization-project/add", OperationLogModule.SETTING_ORGANIZATION_PROJECT); + + + //测试没指定module的项目检查模块菜单是否会报错 + boolean methodHasError = false; + try { + testPlanManagementService.checkModuleIsOpen(project.getId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, new ArrayList<>()); + } catch (Exception e) { + methodHasError = true; + } + Assertions.assertTrue(methodHasError); + //测试完之后,赋值module + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); } } + private static long a1NodeCount = 0; private static long a2NodeCount = 0; private static long a3NodeCount = 0; @@ -162,6 +176,14 @@ public class TestPlanTests extends BaseTest { //查询测试计划列表 TestPlanTableRequest testPlanTableRequest = new TestPlanTableRequest(); testPlanTableRequest.setProjectId(project.getId()); + + //先测试一下没有开启模块时接口能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestPost(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest).andExpect(status().is5xxServerError()); + this.requestGet(String.format(URL_GET_MODULE_TREE, project.getId())).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + MvcResult pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest); String returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8); ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); @@ -184,6 +206,13 @@ public class TestPlanTests extends BaseTest { FileModuleCreateRequest request = new FileModuleCreateRequest(); request.setProjectId(project.getId()); request.setName("a1"); + + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestPost(URL_POST_MODULE_ADD, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_MODULE_ADD, request); String returnId = mvcResult.getResponse().getContentAsString(); Assertions.assertNotNull(returnId); @@ -425,6 +454,13 @@ public class TestPlanTests extends BaseTest { FileModuleUpdateRequest updateRequest = new FileModuleUpdateRequest(); updateRequest.setId(a1Node.getId()); updateRequest.setName("a1-a1"); + + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestPost(URL_POST_MODULE_UPDATE, updateRequest).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + this.requestPostWithOkAndReturn(URL_POST_MODULE_UPDATE, updateRequest); preliminaryTreeNodes = this.getFileModuleTreeNode(); @@ -499,8 +535,13 @@ public class TestPlanTests extends BaseTest { a1b1NodeCount++; } + if (i == 201) { + //第201时,先测试能否添加重复用例 + request.setName("testPlan_200"); + request.setModuleId(moduleId); + this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().is5xxServerError()); + } //添加测试计划 - request.setName("testPlan_" + i); request.setModuleId(moduleId); MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_ADD, request); @@ -530,12 +571,7 @@ public class TestPlanTests extends BaseTest { request.setType(TestPlanConstants.TEST_PLAN_TYPE_PLAN); } - TestPlan updateTestPlan = new TestPlan(); - updateTestPlan.setId(groupTestPlanId7); - updateTestPlan.setType(TestPlanConstants.TEST_PLAN_TYPE_GROUP); - testPlanMapper.updateByPrimaryKeySelective(updateTestPlan); - updateTestPlan.setId(groupTestPlanId15); - testPlanMapper.updateByPrimaryKeySelective(updateTestPlan); + /* 抽查: testPlan_13没有设置计划开始时间、没有设置重复添加用例和自动更新状态、阈值为100、描述为空; @@ -559,6 +595,13 @@ public class TestPlanTests extends BaseTest { itemRequest.setModuleId(a1Node.getId()); itemRequest.setGroupId(groupTestPlanId7); itemRequest.setName("testPlan_group7_" + i); + if (i == 0) { + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestPost(URL_POST_TEST_PLAN_ADD, itemRequest).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + } MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_ADD, itemRequest); String returnStr = mvcResult.getResponse().getContentAsString(); ResultHolder holder = JSON.parseObject(returnStr, ResultHolder.class); @@ -580,6 +623,7 @@ public class TestPlanTests extends BaseTest { 3.1 group_id不存在 3.2 group_id对应的测试计划type不是group 4.参数校验:passThreshold大于100 + 5.重名校验 */ request.setName(null); this.requestPost(URL_POST_TEST_PLAN_ADD, request).andExpect(status().isBadRequest()); @@ -605,6 +649,14 @@ public class TestPlanTests extends BaseTest { public void testPlanPageCountTest() throws Exception { TestPlanTableRequest testPlanTableRequest = new TestPlanTableRequest(); testPlanTableRequest.setProjectId(project.getId()); + + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest).andExpect(status().is5xxServerError()); + this.requestPost(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + MvcResult moduleCountResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_MODULE_COUNT, testPlanTableRequest); String moduleCountReturnData = moduleCountResult.getResponse().getContentAsString(StandardCharsets.UTF_8); Map moduleCountMap = JSON.parseObject(JSON.toJSONString(JSON.parseObject(moduleCountReturnData, ResultHolder.class).getData()), Map.class); @@ -641,6 +693,20 @@ public class TestPlanTests extends BaseTest { Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize()); Assertions.assertEquals(result.getTotal(), 999); + //按照名称倒叙 + testPlanTableRequest.setSort(new HashMap<>() {{ + this.put("name", "desc"); + }}); + pageResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_PAGE, testPlanTableRequest); + returnData = pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8); + resultHolder = JSON.parseObject(returnData, ResultHolder.class); + result = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class); + //返回值的页码和当前页码相同 + Assertions.assertEquals(result.getCurrent(), testPlanTableRequest.getCurrent()); + //返回的数据量不超过规定要返回的数据量相同 + Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize()); + Assertions.assertEquals(result.getTotal(), 999); + //查询详情 List testPlanResponseList = JSON.parseArray(JSON.toJSONString(result.getList()), TestPlanResponse.class); for (TestPlanResponse response : testPlanResponseList) { @@ -709,6 +775,13 @@ public class TestPlanTests extends BaseTest { //修改名称 TestPlanUpdateRequest updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId()); updateRequest.setName(IDGenerator.nextStr()); + + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestPost(URL_POST_TEST_PLAN_UPDATE, updateRequest).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_POST_TEST_PLAN_UPDATE, updateRequest); String returnStr = mvcResult.getResponse().getContentAsString(); ResultHolder holder = JSON.parseObject(returnStr, ResultHolder.class); @@ -832,6 +905,10 @@ public class TestPlanTests extends BaseTest { updateRequest = testPlanTestService.generateUpdateRequest(testPlan.getId()); this.requestPostWithOk(URL_POST_TEST_PLAN_UPDATE, updateRequest); + //反例:名称重复 + updateRequest.setName("testPlan_400"); + this.requestPost(URL_POST_TEST_PLAN_UPDATE, updateRequest).andExpect(status().is5xxServerError()); + //因为有条数据被移动了测试计划组里,所以检查一下moduleCount. TestPlanTableRequest testPlanTableRequest = new TestPlanTableRequest(); testPlanTableRequest.setProjectId(project.getId()); @@ -879,6 +956,12 @@ public class TestPlanTests extends BaseTest { Assertions.assertEquals(response.getAssociationCount(), FUNCTIONAL_CASES.size()); Assertions.assertEquals(testPlanTestService.countResource(request.getTestPlanId(), TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE), FUNCTIONAL_CASES.size()); + //先测试一下没有开启模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "caseManagement"); + this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION, request); resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanAssociationResponse.class); @@ -918,13 +1001,12 @@ public class TestPlanTests extends BaseTest { request.setTestPlanId(null); this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION, request).andExpect(status().isBadRequest()); //反例 测试计划不存在 - //测试权限 request.setTestPlanId(IDGenerator.nextStr()); this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION, request).andExpect(status().is5xxServerError()); //测试权限 request.setTestPlanId(simpleTestPlan.getId()); - this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION, request); + this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_ASSOCIATION, URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION, request); LOG_CHECK_LIST.add( new CheckLogModel(simpleTestPlan.getId(), OperationLogType.ADD, URL_POST_RESOURCE_FUNCTIONAL_CASE_ASSOCIATION) @@ -949,6 +1031,12 @@ public class TestPlanTests extends BaseTest { request.setDropNodeId(funcList.get(0).getId()); request.setDropPosition(-1); + //先测试一下没有开启模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "caseManagement"); + this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + MvcResult result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request); ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); TestPlanResourceSortResponse response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class); @@ -975,6 +1063,23 @@ public class TestPlanTests extends BaseTest { new CheckLogModel(request.getDragNodeId(), OperationLogType.UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT) ); + + //再将这时的第80个放到第一位之后,但是第一个的pos为2,检查能否触发ref操作 + request.setDragNodeId(funcList.get(79).getId()); + request.setDropNodeId(funcList.get(0).getId()); + request.setDropPosition(-1); + testPlanTestService.setResourcePos(funcList.get(0).getId(), TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE, 2); + result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request); + resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); + response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class); + Assertions.assertEquals(response.getSortNodeNum(), 1); + funcList = testPlanTestService.selectTestPlanFunctionalCaseByTestPlanId(repeatCaseTestPlan.getId()); + Assertions.assertEquals(funcList.get(0).getId(), request.getDragNodeId()); + Assertions.assertEquals(funcList.get(1).getId(), request.getDropNodeId()); + LOG_CHECK_LIST.add( + new CheckLogModel(request.getDragNodeId(), OperationLogType.UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT) + ); + //反例:测试计划为空 request.setTestPlanId(null); this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().isBadRequest()); @@ -1021,6 +1126,12 @@ public class TestPlanTests extends BaseTest { Assertions.assertEquals(response.getAssociationCount(), API_TEST_CASES.size()); Assertions.assertEquals(testPlanTestService.countResource(request.getTestPlanId(), TestPlanResourceConstants.RESOURCE_API_CASE), API_TEST_CASES.size()); + //先测试一下没有开启模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "apiTest"); + this.requestPost(URL_POST_RESOURCE_API_CASE_ASSOCIATION, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_API_CASE_ASSOCIATION, request); resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanAssociationResponse.class); @@ -1060,13 +1171,12 @@ public class TestPlanTests extends BaseTest { request.setTestPlanId(null); this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().isBadRequest()); //反例 测试计划不存在 - //测试权限 request.setTestPlanId(IDGenerator.nextStr()); this.requestPost(URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request).andExpect(status().is5xxServerError()); //测试权限 request.setTestPlanId(simpleTestPlan.getId()); - this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_UPDATE, URL_POST_RESOURCE_FUNCTIONAL_CASE_SORT, request); + this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_ASSOCIATION, URL_POST_RESOURCE_API_CASE_ASSOCIATION, request); LOG_CHECK_LIST.add( new CheckLogModel(simpleTestPlan.getId(), OperationLogType.ADD, URL_POST_RESOURCE_API_CASE_ASSOCIATION) @@ -1091,6 +1201,12 @@ public class TestPlanTests extends BaseTest { request.setDropNodeId(funcList.get(0).getId()); request.setDropPosition(-1); + //先测试一下没有开启模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "apiTest"); + this.requestPost(URL_POST_RESOURCE_API_CASE_SORT, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + MvcResult result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_API_CASE_SORT, request); ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); TestPlanResourceSortResponse response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class); @@ -1117,6 +1233,22 @@ public class TestPlanTests extends BaseTest { new CheckLogModel(request.getDragNodeId(), OperationLogType.UPDATE, URL_POST_RESOURCE_API_CASE_SORT) ); + //再将这时的第80个放到第一位之前,但是第一个的pos为2,检查能否触发ref操作 + request.setDragNodeId(funcList.get(79).getId()); + request.setDropNodeId(funcList.get(0).getId()); + request.setDropPosition(-1); + testPlanTestService.setResourcePos(funcList.get(0).getId(), TestPlanResourceConstants.RESOURCE_API_CASE, 2); + result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_API_CASE_SORT, request); + resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); + response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class); + Assertions.assertEquals(response.getSortNodeNum(), 1); + funcList = testPlanTestService.selectTestPlanApiCaseByTestPlanId(repeatCaseTestPlan.getId()); + Assertions.assertEquals(funcList.get(0).getId(), request.getDragNodeId()); + Assertions.assertEquals(funcList.get(1).getId(), request.getDropNodeId()); + LOG_CHECK_LIST.add( + new CheckLogModel(request.getDragNodeId(), OperationLogType.UPDATE, URL_POST_RESOURCE_API_CASE_SORT) + ); + //反例:测试计划为空 request.setTestPlanId(null); this.requestPost(URL_POST_RESOURCE_API_CASE_SORT, request).andExpect(status().isBadRequest()); @@ -1166,6 +1298,12 @@ public class TestPlanTests extends BaseTest { Assertions.assertEquals(response.getAssociationCount(), API_SCENARIOS.size()); Assertions.assertEquals(testPlanTestService.countResource(request.getTestPlanId(), TestPlanResourceConstants.RESOURCE_API_SCENARIO), API_SCENARIOS.size()); + //先测试一下没有开启模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "apiTest"); + this.requestPost(URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION, request); resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanAssociationResponse.class); @@ -1205,13 +1343,12 @@ public class TestPlanTests extends BaseTest { request.setTestPlanId(null); this.requestPost(URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION, request).andExpect(status().isBadRequest()); //反例 测试计划不存在 - //测试权限 request.setTestPlanId(IDGenerator.nextStr()); this.requestPost(URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION, request).andExpect(status().is5xxServerError()); //测试权限 request.setTestPlanId(simpleTestPlan.getId()); - this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_UPDATE, URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION, request); + this.requestPostPermissionTest(PermissionConstants.TEST_PLAN_READ_ASSOCIATION, URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION, request); LOG_CHECK_LIST.add( new CheckLogModel(simpleTestPlan.getId(), OperationLogType.ADD, URL_POST_RESOURCE_API_SCENARIO_ASSOCIATION) @@ -1236,6 +1373,12 @@ public class TestPlanTests extends BaseTest { request.setDropNodeId(funcList.get(0).getId()); request.setDropPosition(-1); + //先测试一下没有开启模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "apiTest"); + this.requestPost(URL_POST_RESOURCE_API_SCENARIO_SORT, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + MvcResult result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_API_SCENARIO_SORT, request); ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); TestPlanResourceSortResponse response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class); @@ -1262,6 +1405,22 @@ public class TestPlanTests extends BaseTest { new CheckLogModel(request.getDragNodeId(), OperationLogType.UPDATE, URL_POST_RESOURCE_API_SCENARIO_SORT) ); + //再将这时的第80个放到第一位之后,但是第一个的pos为2,检查能否触发ref操作 + request.setDragNodeId(funcList.get(79).getId()); + request.setDropNodeId(funcList.get(0).getId()); + request.setDropPosition(-1); + testPlanTestService.setResourcePos(funcList.get(0).getId(), TestPlanResourceConstants.RESOURCE_API_SCENARIO, 2); + result = this.requestPostWithOkAndReturn(URL_POST_RESOURCE_API_SCENARIO_SORT, request); + resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); + response = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), TestPlanResourceSortResponse.class); + Assertions.assertEquals(response.getSortNodeNum(), 1); + funcList = testPlanTestService.selectTestPlanApiScenarioByTestPlanId(repeatCaseTestPlan.getId()); + Assertions.assertEquals(funcList.get(0).getId(), request.getDragNodeId()); + Assertions.assertEquals(funcList.get(1).getId(), request.getDropNodeId()); + LOG_CHECK_LIST.add( + new CheckLogModel(request.getDragNodeId(), OperationLogType.UPDATE, URL_POST_RESOURCE_API_SCENARIO_SORT) + ); + //反例:测试计划为空 request.setTestPlanId(null); this.requestPost(URL_POST_RESOURCE_API_SCENARIO_SORT, request).andExpect(status().isBadRequest()); @@ -1325,6 +1484,14 @@ public class TestPlanTests extends BaseTest { request.setDragNodeId(a1Node.getId()); request.setDropNodeId(a3Node.getId()); request.setDropPosition(1); + + + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestPost(URL_POST_MODULE_MOVE, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + this.requestPostWithOk(URL_POST_MODULE_MOVE, request); this.checkModulePos(a3Node.getId(), a1Node.getId(), null, false); } @@ -1543,6 +1710,7 @@ public class TestPlanTests extends BaseTest { @Test @Order(101) public void deleteTestPlanTest() throws Exception { + int allDataInDB = 999 + 40; if (StringUtils.isEmpty(groupTestPlanId7)) { this.testPlanAddTest(); } @@ -1550,8 +1718,10 @@ public class TestPlanTests extends BaseTest { //根据id删除 (删除 第61这1个) List testPlanList = testPlanTestService.selectByProjectIdAndNames(project.getId(), new String[]{"testPlan_61"}); + this.requestGet(String.format(URL_GET_TEST_PLAN_DELETE, testPlanList.get(0).getId())).andExpect(status().isOk()); - Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - 1)); + allDataInDB--; + Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), allDataInDB)); //根据id删除 (删除 第610-619这11个) testPlanList = testPlanTestService.selectByProjectIdAndNames(project.getId(), @@ -1560,7 +1730,24 @@ public class TestPlanTests extends BaseTest { request.setProjectId(project.getId()); request.setSelectIds(testPlanList.stream().map(TestPlan::getId).collect(Collectors.toList())); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); - Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - 1 - 10)); + allDataInDB = allDataInDB - 10; + Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), allDataInDB)); + + //删除组 + this.requestGetWithOk(String.format(URL_GET_TEST_PLAN_DELETE, groupTestPlanId7)); + allDataInDB--; + Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), allDataInDB)); + TestPlanExample example = new TestPlanExample(); + example.createCriteria().andGroupIdEqualTo(groupTestPlanId7); + Assertions.assertEquals(testPlanMapper.countByExample(example), 0); + + + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestGet(String.format(URL_GET_TEST_PLAN_DELETE, testPlanList.get(0).getId())).andExpect(status().is5xxServerError()); + this.requestPost(URL_POST_TEST_PLAN_BATCH_DELETE, request).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); // 根据查询条件删除( 删除plan_2)这一部分 request = new TestPlanBatchProcessRequest(); @@ -1568,14 +1755,19 @@ public class TestPlanTests extends BaseTest { request.setSelectAll(true); request.getCondition().setKeyword("plan_2"); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); - Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100))); + allDataInDB = allDataInDB - (1 + 10 + 100); + Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), allDataInDB)); - //批量删除的数据中包含group7这个用户组 + //批量删除的数据中包含group15这个用户组 request = new TestPlanBatchProcessRequest(); - request.setSelectIds(Collections.singletonList(groupTestPlanId7)); + request.setSelectIds(Collections.singletonList(groupTestPlanId15)); request.setProjectId(project.getId()); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); - Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100) - 1)); + allDataInDB--; + Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), allDataInDB)); + example.clear(); + example.createCriteria().andGroupIdEqualTo(groupTestPlanId15); + Assertions.assertEquals(testPlanMapper.countByExample(example), 0); //根据a1a1Node模快删除 BaseTreeNode a1a1Node = TestPlanTestUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-a1"); @@ -1584,7 +1776,8 @@ public class TestPlanTests extends BaseTest { request.setModuleIds(Arrays.asList(a1a1Node.getId())); request.setProjectId(project.getId()); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); - Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100) - 1 - 50)); + allDataInDB = allDataInDB - 50; + Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), allDataInDB)); //根据 a1b1Node模块以及planSty这个条件删除(应当删除0条,数据量不会变化) BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-b1"); @@ -1594,7 +1787,7 @@ public class TestPlanTests extends BaseTest { request.getCondition().setKeyword("planSty"); request.setProjectId(project.getId()); this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_DELETE, request); - Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), 999 + 40 - (1 + 10) - (1 + 10 + 100) - 1 - 50)); + Assertions.assertTrue(testPlanTestService.checkDataCount(project.getId(), allDataInDB)); } @Test @@ -1606,6 +1799,12 @@ public class TestPlanTests extends BaseTest { BaseTreeNode a1b1Node = TestPlanTestUtils.getNodeByName(this.getFileModuleTreeNode(), "a1-b1"); assert a1b1Node != null; + //测试项目没有开启测试计划模块时能否使用 + testPlanTestService.removeProjectModule(project, PROJECT_MODULE, "testPlan"); + this.requestGet(String.format(URL_GET_MODULE_DELETE, a1b1Node.getId())).andExpect(status().is5xxServerError()); + //恢复 + testPlanTestService.resetProjectModule(project, PROJECT_MODULE); + this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, a1b1Node.getId())); this.checkModuleIsEmpty(a1b1Node.getId()); LOG_CHECK_LIST.add( @@ -1622,9 +1821,10 @@ public class TestPlanTests extends BaseTest { ); //删除不存在的节点 - this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, IDGenerator.nextNum())); - // 测试删除根节点 - this.requestGetWithOk(String.format(URL_GET_MODULE_DELETE, ModuleConstants.DEFAULT_NODE_ID)); + this.requestGet(String.format(URL_GET_MODULE_DELETE, IDGenerator.nextNum())).andExpect(status().is5xxServerError()); + // 测试删除根节点(根节点无法删除) + this.requestGet(String.format(URL_GET_MODULE_DELETE, ModuleConstants.DEFAULT_NODE_ID)).andExpect(status().is5xxServerError()); + ; //service层判断:测试删除空集合 testPlanModuleService.deleteModule(new ArrayList<>(), project.getId(), null, null, null); @@ -1761,10 +1961,32 @@ public class TestPlanTests extends BaseTest { @Resource private TestPlanService testPlanService; + @Resource + private TestPlanMapper testPlanMapper; + @Resource + private TestPlanManagementService testPlanManagementService; @Test @Order(111) public void serviceCheckTest() throws Exception { testPlanService.checkModule(ModuleConstants.DEFAULT_NODE_ID); + + //不存在的project测试 + boolean methodHasError = false; + try { + testPlanManagementService.checkModuleIsOpen(IDGenerator.nextStr(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, new ArrayList<>()); + } catch (Exception e) { + methodHasError = true; + } + Assertions.assertTrue(methodHasError); + + //不存在的类型 + methodHasError = false; + try { + testPlanManagementService.checkModuleIsOpen(IDGenerator.nextStr(), IDGenerator.nextStr(), new ArrayList<>()); + } catch (Exception e) { + methodHasError = true; + } + Assertions.assertTrue(methodHasError); } } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/service/TestPlanTestService.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/service/TestPlanTestService.java index 620525c3de..973bfd4101 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/service/TestPlanTestService.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/service/TestPlanTestService.java @@ -11,6 +11,8 @@ import io.metersphere.functional.mapper.FunctionalCaseMapper; import io.metersphere.plan.domain.*; import io.metersphere.plan.dto.request.TestPlanUpdateRequest; import io.metersphere.plan.mapper.*; +import io.metersphere.project.domain.Project; +import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.sdk.constants.*; import io.metersphere.sdk.util.JSON; import io.metersphere.system.uid.IDGenerator; @@ -26,6 +28,8 @@ import java.util.List; @Service public class TestPlanTestService { + @Resource + private ProjectMapper projectMapper; @Resource private TestPlanMapper testPlanMapper; @Resource @@ -336,4 +340,41 @@ public class TestPlanTestService { apiTestCaseMapper.batchInsert(returnList); return returnList; } + + public void removeProjectModule(Project project, String[] projectModule, String removeModule) { + ArrayList moduleList = new ArrayList<>(List.of(projectModule)); + moduleList.remove(removeModule); + + Project updateProject = new Project(); + updateProject.setId(project.getId()); + updateProject.setModuleSetting(JSON.toJSONString(moduleList)); + projectMapper.updateByPrimaryKeySelective(updateProject); + } + + public void resetProjectModule(Project project, String[] projectModule) { + ArrayList moduleList = new ArrayList<>(List.of(projectModule)); + Project updateProject = new Project(); + updateProject.setId(project.getId()); + updateProject.setModuleSetting(JSON.toJSONString(moduleList)); + projectMapper.updateByPrimaryKeySelective(updateProject); + } + + public void setResourcePos(String id, String resourceType, long pos) { + if (StringUtils.equals(resourceType, TestPlanResourceConstants.RESOURCE_FUNCTIONAL_CASE)) { + TestPlanFunctionalCase updateCase = new TestPlanFunctionalCase(); + updateCase.setId(id); + updateCase.setPos(pos); + testPlanFunctionalCaseMapper.updateByPrimaryKeySelective(updateCase); + } else if (StringUtils.equals(resourceType, TestPlanResourceConstants.RESOURCE_API_CASE)) { + TestPlanApiCase updateCase = new TestPlanApiCase(); + updateCase.setId(id); + updateCase.setPos(pos); + testPlanApiCaseMapper.updateByPrimaryKeySelective(updateCase); + } else if (StringUtils.equals(resourceType, TestPlanResourceConstants.RESOURCE_API_SCENARIO)) { + TestPlanApiScenario updateCase = new TestPlanApiScenario(); + updateCase.setId(id); + updateCase.setPos(pos); + testPlanApiScenarioMapper.updateByPrimaryKeySelective(updateCase); + } + } }