diff --git a/backend/src/main/java/io/metersphere/api/controller/APIReportController.java b/backend/src/main/java/io/metersphere/api/controller/APIReportController.java index caa7374ebf..fd6db503ca 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APIReportController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APIReportController.java @@ -11,6 +11,7 @@ import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.dto.DashboardTestDTO; +import io.metersphere.service.CheckOwnerService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; @@ -25,6 +26,8 @@ public class APIReportController { @Resource private APIReportService apiReportService; + @Resource + private CheckOwnerService checkOwnerService; @GetMapping("recent/{count}") public List recentTest(@PathVariable int count) { @@ -37,6 +40,7 @@ public class APIReportController { @GetMapping("/list/{testId}") public List listByTestId(@PathVariable String testId) { + checkOwnerService.checkApiTestOwner(testId); return apiReportService.listByTestId(testId); } diff --git a/backend/src/main/java/io/metersphere/api/controller/APITestController.java b/backend/src/main/java/io/metersphere/api/controller/APITestController.java index ad3940ac7a..3eb82dddba 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APITestController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APITestController.java @@ -13,6 +13,7 @@ import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.controller.request.QueryScheduleRequest; import io.metersphere.dto.ScheduleDao; +import io.metersphere.service.CheckOwnerService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; @@ -27,6 +28,8 @@ import java.util.List; public class APITestController { @Resource private APITestService apiTestService; + @Resource + private CheckOwnerService checkownerService; @GetMapping("recent/{count}") public List recentTest(@PathVariable int count) { @@ -51,6 +54,7 @@ public class APITestController { @GetMapping("/list/{projectId}") public List list(@PathVariable String projectId) { + checkownerService.checkProjectOwner(projectId); return apiTestService.getApiTestByProjectId(projectId); } @@ -71,6 +75,7 @@ public class APITestController { @PostMapping(value = "/update", consumes = {"multipart/form-data"}) public void update(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "file") MultipartFile file, @RequestPart(value = "files") List bodyFiles) { + checkownerService.checkApiTestOwner(request.getId()); apiTestService.update(request, file, bodyFiles); } @@ -81,13 +86,16 @@ public class APITestController { @GetMapping("/get/{testId}") public APITestResult get(@PathVariable String testId) { + checkownerService.checkApiTestOwner(testId); return apiTestService.get(testId); } @PostMapping("/delete") public void delete(@RequestBody DeleteAPITestRequest request) { - apiTestService.delete(request.getId()); + String testId = request.getId(); + checkownerService.checkApiTestOwner(testId); + apiTestService.delete(testId); } @PostMapping(value = "/run") diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiTestEnvironmentController.java b/backend/src/main/java/io/metersphere/api/controller/ApiTestEnvironmentController.java index 9cee0a427b..ae274c383e 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiTestEnvironmentController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiTestEnvironmentController.java @@ -3,6 +3,7 @@ package io.metersphere.api.controller; import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.commons.constants.RoleConstants; +import io.metersphere.service.CheckOwnerService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; @@ -17,9 +18,12 @@ public class ApiTestEnvironmentController { @Resource ApiTestEnvironmentService apiTestEnvironmentService; + @Resource + private CheckOwnerService checkOwnerService; @GetMapping("/list/{projectId}") public List list(@PathVariable String projectId) { + checkOwnerService.checkProjectOwner(projectId); return apiTestEnvironmentService.list(projectId); } diff --git a/backend/src/main/java/io/metersphere/controller/ProjectController.java b/backend/src/main/java/io/metersphere/controller/ProjectController.java index d2d302ea71..9b3940b79e 100644 --- a/backend/src/main/java/io/metersphere/controller/ProjectController.java +++ b/backend/src/main/java/io/metersphere/controller/ProjectController.java @@ -9,6 +9,7 @@ import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.controller.request.ProjectRequest; import io.metersphere.dto.ProjectDTO; +import io.metersphere.service.CheckOwnerService; import io.metersphere.service.ProjectService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; @@ -22,6 +23,8 @@ import java.util.List; public class ProjectController { @Resource private ProjectService projectService; + @Resource + private CheckOwnerService checkOwnerService; @GetMapping("/listAll") public List listAll() { @@ -71,6 +74,7 @@ public class ProjectController { @GetMapping("/delete/{projectId}") @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER,}, logical = Logical.OR) public void deleteProject(@PathVariable(value = "projectId") String projectId) { + checkOwnerService.checkProjectOwner(projectId); projectService.deleteProject(projectId); } diff --git a/backend/src/main/java/io/metersphere/controller/handler/RestControllerExceptionHandler.java b/backend/src/main/java/io/metersphere/controller/handler/RestControllerExceptionHandler.java index 352a56b338..411ccc6c42 100644 --- a/backend/src/main/java/io/metersphere/controller/handler/RestControllerExceptionHandler.java +++ b/backend/src/main/java/io/metersphere/controller/handler/RestControllerExceptionHandler.java @@ -4,6 +4,7 @@ package io.metersphere.controller.handler; import io.metersphere.commons.exception.MSException; import io.metersphere.controller.ResultHolder; import org.apache.shiro.ShiroException; +import org.apache.shiro.authz.UnauthorizedException; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -21,6 +22,13 @@ public class RestControllerExceptionHandler { return ResultHolder.error(exception.getMessage()); } + /*=========== Shiro 异常拦截==============*/ + @ExceptionHandler(UnauthorizedException.class) + public ResultHolder unauthorizedExceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception exception) { + response.setStatus(HttpStatus.FORBIDDEN.value()); + return ResultHolder.error(exception.getMessage()); + } + @ExceptionHandler(MSException.class) public ResultHolder msExceptionHandler(HttpServletRequest request, HttpServletResponse response, MSException e) { diff --git a/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java b/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java index fbc5086d11..9580e6f9a1 100644 --- a/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java +++ b/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java @@ -14,6 +14,7 @@ import io.metersphere.dto.DashboardTestDTO; import io.metersphere.dto.LoadTestDTO; import io.metersphere.dto.ScheduleDao; import io.metersphere.performance.service.PerformanceTestService; +import io.metersphere.service.CheckOwnerService; import io.metersphere.service.FileService; import io.metersphere.track.request.testplan.*; import org.apache.shiro.authz.annotation.Logical; @@ -35,6 +36,8 @@ public class PerformanceTestController { private PerformanceTestService performanceTestService; @Resource private FileService fileService; + @Resource + private CheckOwnerService checkOwnerService; @GetMapping("recent/{count}") public List recentTestPlans(@PathVariable int count) { @@ -54,12 +57,14 @@ public class PerformanceTestController { @GetMapping("/list/{projectId}") public List list(@PathVariable String projectId) { + checkOwnerService.checkProjectOwner(projectId); return performanceTestService.getLoadTestByProjectId(projectId); } @GetMapping("/state/get/{testId}") public LoadTest listByTestId(@PathVariable String testId) { + checkOwnerService.checkPerformanceTestOwner(testId); return performanceTestService.getLoadTestBytestId(testId); } @@ -76,26 +81,31 @@ public class PerformanceTestController { @RequestPart("request") EditTestPlanRequest request, @RequestPart(value = "file", required = false) List files ) { + checkOwnerService.checkPerformanceTestOwner(request.getId()); return performanceTestService.edit(request, files); } @GetMapping("/get/{testId}") public LoadTestDTO get(@PathVariable String testId) { + checkOwnerService.checkPerformanceTestOwner(testId); return performanceTestService.get(testId); } @GetMapping("/get-advanced-config/{testId}") public String getAdvancedConfiguration(@PathVariable String testId) { + checkOwnerService.checkPerformanceTestOwner(testId); return performanceTestService.getAdvancedConfiguration(testId); } @GetMapping("/get-load-config/{testId}") public String getLoadConfiguration(@PathVariable String testId) { + checkOwnerService.checkPerformanceTestOwner(testId); return performanceTestService.getLoadConfiguration(testId); } @PostMapping("/delete") public void delete(@RequestBody DeleteTestPlanRequest request) { + checkOwnerService.checkPerformanceTestOwner(request.getId()); performanceTestService.delete(request); } @@ -111,6 +121,7 @@ public class PerformanceTestController { @GetMapping("/file/metadata/{testId}") public List getFileMetadata(@PathVariable String testId) { + checkOwnerService.checkPerformanceTestOwner(testId); return fileService.getFileMetadataByTestId(testId); } diff --git a/backend/src/main/java/io/metersphere/service/CheckOwnerService.java b/backend/src/main/java/io/metersphere/service/CheckOwnerService.java new file mode 100644 index 0000000000..2a0ef39497 --- /dev/null +++ b/backend/src/main/java/io/metersphere/service/CheckOwnerService.java @@ -0,0 +1,64 @@ +package io.metersphere.service; + +import io.metersphere.api.dto.APITestResult; +import io.metersphere.api.dto.QueryAPITestRequest; +import io.metersphere.base.domain.Project; +import io.metersphere.base.mapper.ProjectMapper; +import io.metersphere.base.mapper.ext.ExtApiTestMapper; +import io.metersphere.base.mapper.ext.ExtLoadTestMapper; +import io.metersphere.commons.utils.SessionUtils; +import io.metersphere.dto.LoadTestDTO; +import io.metersphere.i18n.Translator; +import io.metersphere.track.request.testplan.QueryTestPlanRequest; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.UnauthorizedException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +@Service +public class CheckOwnerService { + @Resource + private ProjectMapper projectMapper; + @Resource + private ExtApiTestMapper extApiTestMapper; + @Resource + private ExtLoadTestMapper extLoadTestMapper; + + public void checkProjectOwner(String projectId) { + String workspaceId = SessionUtils.getCurrentWorkspaceId(); + Project project = projectMapper.selectByPrimaryKey(projectId); + if (project == null) { + return; + } + if (!StringUtils.equals(workspaceId, project.getWorkspaceId())) { + throw new UnauthorizedException(Translator.get("check_owner_project")); + } + } + + public void checkApiTestOwner(String testId) { + String workspaceId = SessionUtils.getCurrentWorkspaceId(); + QueryAPITestRequest request = new QueryAPITestRequest(); + request.setWorkspaceId(workspaceId); + request.setId(testId); + List apiTestResults = extApiTestMapper.list(request); + + if (CollectionUtils.size(apiTestResults) != 1) { + throw new UnauthorizedException(Translator.get("check_owner_test")); + } + } + + public void checkPerformanceTestOwner(String testId) { + String workspaceId = SessionUtils.getCurrentWorkspaceId(); + QueryTestPlanRequest request = new QueryTestPlanRequest(); + request.setWorkspaceId(workspaceId); + request.setId(testId); + List loadTestDTOS = extLoadTestMapper.list(request); + + if (CollectionUtils.size(loadTestDTOS) != 1) { + throw new UnauthorizedException(Translator.get("check_owner_test")); + } + } +} diff --git a/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java b/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java index fac2c1cb7c..d1def98d05 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java @@ -10,6 +10,7 @@ import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.excel.domain.ExcelResponse; +import io.metersphere.service.CheckOwnerService; import io.metersphere.track.dto.TestCaseDTO; import io.metersphere.track.request.testcase.QueryTestCaseRequest; import io.metersphere.track.request.testcase.TestCaseBatchRequest; @@ -30,6 +31,8 @@ public class TestCaseController { @Resource TestCaseService testCaseService; + @Resource + private CheckOwnerService checkOwnerService; @PostMapping("/list/{goPage}/{pageSize}") public Pager> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) { @@ -39,6 +42,7 @@ public class TestCaseController { @GetMapping("/list/{projectId}") public List list(@PathVariable String projectId) { + checkOwnerService.checkProjectOwner(projectId); QueryTestCaseRequest request = new QueryTestCaseRequest(); request.setProjectId(projectId); return testCaseService.listTestCase(request); @@ -47,6 +51,7 @@ public class TestCaseController { @GetMapping("/list/method/{projectId}") public List listByMethod(@PathVariable String projectId) { + checkOwnerService.checkProjectOwner(projectId); QueryTestCaseRequest request = new QueryTestCaseRequest(); request.setProjectId(projectId); return testCaseService.listTestCaseMthod(request); @@ -106,8 +111,9 @@ public class TestCaseController { @PostMapping("/import/{projectId}/{userId}") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) - public ExcelResponse testCaseImport(MultipartFile file, @PathVariable String projectId,@PathVariable String userId) throws NoSuchFieldException { - return testCaseService.testCaseImport(file, projectId,userId); + public ExcelResponse testCaseImport(MultipartFile file, @PathVariable String projectId, @PathVariable String userId) { + checkOwnerService.checkProjectOwner(projectId); + return testCaseService.testCaseImport(file, projectId, userId); } @GetMapping("/export/template") @@ -115,6 +121,7 @@ public class TestCaseController { public void testCaseTemplateExport(HttpServletResponse response) { testCaseService.testCaseTemplateExport(response); } + @GetMapping("/export/xmindTemplate") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) public void xmindTemplate(HttpServletResponse response) { diff --git a/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java b/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java index d1062619fd..83328ec917 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java @@ -2,6 +2,7 @@ package io.metersphere.track.controller; import io.metersphere.base.domain.TestCaseNode; import io.metersphere.commons.constants.RoleConstants; +import io.metersphere.service.CheckOwnerService; import io.metersphere.track.dto.TestCaseNodeDTO; import io.metersphere.track.request.testcase.DragNodeRequest; import io.metersphere.track.request.testcase.QueryNodeRequest; @@ -20,9 +21,12 @@ public class TestCaseNodeController { @Resource TestCaseNodeService testCaseNodeService; + @Resource + private CheckOwnerService checkOwnerService; @GetMapping("/list/{projectId}") public List getNodeByProjectId(@PathVariable String projectId) { + checkOwnerService.checkProjectOwner(projectId); return testCaseNodeService.getNodeTreeByProjectId(projectId); } diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index 4004f8fac2..abd1d31f1f 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -158,3 +158,6 @@ license_valid_license_error=Authorization authentication failed timing_task_result_notification=Timing task result notification test_review_task_notice=Test review task notice test_track.length_less_than=The title is too long, the length must be less than +# check owner +check_owner_project=The current user does not have permission to operate this project +check_owner_test=The current user does not have permission to operate this test \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index d4596937ce..d4aebdce4d 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -158,4 +158,6 @@ import_xmind_not_found=未找到测试用例 timing_task_result_notification=定时任务结果通知 test_review_task_notice=测试评审任务通知 test_track.length_less_than=标题过长,字数必须小于 - +# check owner +check_owner_project=当前用户没有操作此项目的权限 +check_owner_test=当前用户没有操作此测试的权限 \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index 05655a009f..21433d9522 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -158,4 +158,7 @@ import_xmind_count_error=思維導圖導入用例數量不能超過 500 條 import_xmind_not_found=未找到测试用例 timing_task_result_notification=定時任務結果通知 test_review_task_notice=測試評審任務通知 -test_track.length_less_than=標題過長,字數必須小於 \ No newline at end of file +test_track.length_less_than=標題過長,字數必須小於 +# check owner +check_owner_project=當前用戶沒有操作此項目的權限 +check_owner_test=當前用戶沒有操作此測試的權限 \ No newline at end of file