diff --git a/Jenkinsfile b/Jenkinsfile index 5901853f5d..65ab9ec657 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ pipeline { options { quietPeriod(600) } parameters { string(name: 'IMAGE_NAME', defaultValue: 'metersphere', description: '构建后的 Docker 镜像名称') - string(name: 'IMAGE_FREFIX', defaultValue: 'registry.cn-qingdao.aliyuncs.com/metersphere', description: '构建后的 Docker 镜像带仓库名的前缀') + string(name: 'IMAGE_PREFIX', defaultValue: 'registry.cn-qingdao.aliyuncs.com/metersphere', description: '构建后的 Docker 镜像带仓库名的前缀') } stages { stage('Build/Test') { @@ -19,9 +19,9 @@ pipeline { } stage('Docker build & push') { steps { - sh "docker build --build-arg MS_VERSION=\${TAG_NAME:-\$BRANCH_NAME}-b\${BUILD_NUMBER} -t ${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME} ." - sh "docker tag ${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME} ${IMAGE_FREFIX}/${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME}" - sh "docker push ${IMAGE_FREFIX}/${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME}" + sh "docker build --build-arg MS_VERSION=\${TAG_NAME:-\$BRANCH_NAME}-\${GIT_COMMIT:0:8} -t ${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME} ." + sh "docker tag ${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME} ${IMAGE_PREFIX}/${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME}" + sh "docker push ${IMAGE_PREFIX}/${IMAGE_NAME}:\${TAG_NAME:-\$BRANCH_NAME}" } } } 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 23af0d7f66..5f41294711 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APIReportController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APIReportController.java @@ -11,7 +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 io.metersphere.service.CheckPermissionService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; @@ -27,7 +27,7 @@ public class APIReportController { @Resource private APIReportService apiReportService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @GetMapping("recent/{count}") public List recentTest(@PathVariable int count) { @@ -41,7 +41,7 @@ public class APIReportController { @GetMapping("/list/{testId}/{goPage}/{pageSize}") public Pager> listByTestId(@PathVariable String testId, @PathVariable int goPage, @PathVariable int pageSize) { - checkOwnerService.checkApiTestOwner(testId); + checkPermissionService.checkApiTestOwner(testId); Page page = PageHelper.startPage(goPage, pageSize, true); return PageUtils.setPageInfo(page, apiReportService.listByTestId(testId)); @@ -60,6 +60,7 @@ public class APIReportController { } @PostMapping("/delete") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void delete(@RequestBody DeleteAPIReportRequest request) { apiReportService.delete(request); } @@ -70,6 +71,7 @@ public class APIReportController { } @PostMapping("/batch/delete") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void deleteAPIReportBatch(@RequestBody DeleteAPIReportRequest reportRequest) { apiReportService.deleteAPIReportBatch(reportRequest); } 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 ba511fa454..21150523d3 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APITestController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APITestController.java @@ -15,11 +15,13 @@ import io.metersphere.base.domain.ApiTest; import io.metersphere.base.domain.Schedule; import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.ScheduleGroup; -import io.metersphere.commons.utils.*; +import io.metersphere.commons.utils.CronUtils; +import io.metersphere.commons.utils.PageUtils; +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 io.metersphere.service.CheckPermissionService; import io.metersphere.service.ScheduleService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; @@ -27,7 +29,6 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; - import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Date; @@ -46,7 +47,7 @@ public class APITestController { @Resource private ApiDefinitionService apiDefinitionService; @Resource - private CheckOwnerService checkownerService; + private CheckPermissionService checkownerService; @Resource private ApiTestCaseService apiTestCaseService; @Resource diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java index 6f8fddfb7d..2fe060e97f 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiDefinitionController.java @@ -14,6 +14,7 @@ import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; +import io.metersphere.service.CheckPermissionService; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; @@ -30,6 +31,8 @@ import java.util.List; public class ApiDefinitionController { @Resource private ApiDefinitionService apiDefinitionService; + @Resource + private CheckPermissionService checkPermissionService; @PostMapping("/list/{goPage}/{pageSize}") public Pager> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) { @@ -39,26 +42,34 @@ public class ApiDefinitionController { } @PostMapping(value = "/create", consumes = {"multipart/form-data"}) + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void create(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List bodyFiles) { + checkPermissionService.checkReadOnlyUser(); apiDefinitionService.create(request, bodyFiles); } @PostMapping(value = "/update", consumes = {"multipart/form-data"}) + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List bodyFiles) { + checkPermissionService.checkReadOnlyUser(); apiDefinitionService.update(request, bodyFiles); } @GetMapping("/delete/{id}") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void delete(@PathVariable String id) { + checkPermissionService.checkReadOnlyUser(); apiDefinitionService.delete(id); } @PostMapping("/deleteBatch") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void deleteBatch(@RequestBody List ids) { apiDefinitionService.deleteBatch(ids); } @PostMapping("/removeToGc") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void removeToGc(@RequestBody List ids) { apiDefinitionService.removeToGc(ids); } diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiModuleController.java b/backend/src/main/java/io/metersphere/api/controller/ApiModuleController.java index 9730e9cd86..69742559ef 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiModuleController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiModuleController.java @@ -5,7 +5,7 @@ import io.metersphere.api.dto.definition.DragModuleRequest; import io.metersphere.api.service.ApiModuleService; import io.metersphere.base.domain.ApiModule; import io.metersphere.commons.constants.RoleConstants; -import io.metersphere.service.CheckOwnerService; +import io.metersphere.service.CheckPermissionService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; @@ -21,17 +21,17 @@ public class ApiModuleController { @Resource ApiModuleService apiModuleService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @GetMapping("/list/{projectId}/{protocol}") public List getNodeByProjectId(@PathVariable String projectId,@PathVariable String protocol) { - checkOwnerService.checkProjectOwner(projectId); + checkPermissionService.checkProjectOwner(projectId); return apiModuleService.getNodeTreeByProjectId(projectId,protocol); } @GetMapping("/list/plan/{planId}/{protocol}") public List getNodeByPlanId(@PathVariable String planId, @PathVariable String protocol) { - checkOwnerService.checkTestPlanOwner(planId); + checkPermissionService.checkTestPlanOwner(planId); return apiModuleService.getNodeByPlanId(planId, protocol); } diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiScenarioModuleController.java b/backend/src/main/java/io/metersphere/api/controller/ApiScenarioModuleController.java index b51bc9aa4e..abcd2d86a5 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiScenarioModuleController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiScenarioModuleController.java @@ -5,14 +5,13 @@ import io.metersphere.api.dto.automation.DragApiScenarioModuleRequest; import io.metersphere.api.service.ApiScenarioModuleService; import io.metersphere.base.domain.ApiScenarioModule; import io.metersphere.commons.constants.RoleConstants; -import io.metersphere.service.CheckOwnerService; +import io.metersphere.service.CheckPermissionService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; -import java.util.List; - import javax.annotation.Resource; +import java.util.List; @RequestMapping("/api/automation/module") @RestController @@ -22,11 +21,11 @@ public class ApiScenarioModuleController { @Resource ApiScenarioModuleService apiScenarioModuleService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @GetMapping("/list/{projectId}") public List getNodeByProjectId(@PathVariable String projectId) { - checkOwnerService.checkProjectOwner(projectId); + checkPermissionService.checkProjectOwner(projectId); return apiScenarioModuleService.getNodeTreeByProjectId(projectId); } @@ -44,7 +43,7 @@ public class ApiScenarioModuleController { @GetMapping("/list/plan/{planId}") public List getNodeByPlanId(@PathVariable String planId) { - checkOwnerService.checkTestPlanOwner(planId); + checkPermissionService.checkTestPlanOwner(planId); return apiScenarioModuleService.getNodeByPlanId(planId); } 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 ae274c383e..87d6e618ce 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiTestEnvironmentController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiTestEnvironmentController.java @@ -3,7 +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 io.metersphere.service.CheckPermissionService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; import org.springframework.web.bind.annotation.*; @@ -19,11 +19,11 @@ public class ApiTestEnvironmentController { @Resource ApiTestEnvironmentService apiTestEnvironmentService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @GetMapping("/list/{projectId}") public List list(@PathVariable String projectId) { - checkOwnerService.checkProjectOwner(projectId); + checkPermissionService.checkProjectOwner(projectId); return apiTestEnvironmentService.list(projectId); } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java index 1786eca223..de84c2c899 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsHTTPSamplerProxy.java @@ -119,9 +119,15 @@ public class MsHTTPSamplerProxy extends MsTestElement { sampler.setPort(config.getConfig().getHttpConfig().getPort()); sampler.setProtocol(config.getConfig().getHttpConfig().getProtocol()); url = config.getConfig().getHttpConfig().getProtocol() + "://" + config.getConfig().getHttpConfig().getSocket(); + // 补充如果是完整URL 则用自身URL + boolean isUrl = false; + if (StringUtils.isNotEmpty(this.getUrl()) && isURL(this.getUrl())) { + url = this.getUrl(); + isUrl = true; + } URL urlObject = new URL(url); String envPath = StringUtils.equals(urlObject.getPath(), "/") ? "" : urlObject.getPath(); - if (StringUtils.isNotBlank(this.getPath())) { + if (StringUtils.isNotBlank(this.getPath()) && !isUrl) { envPath += this.getPath(); } if (CollectionUtils.isNotEmpty(this.getRest()) && this.isRest()) { @@ -243,6 +249,15 @@ public class MsHTTPSamplerProxy extends MsTestElement { tree.add(headerManager); } + public boolean isURL(String str) { + //转换为小写 + try { + new URL(str); + return true; + } catch (Exception e) { + return false; + } + } private boolean isRest() { return this.getRest().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).toArray().length > 0; diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java index fc0e0f7fa3..7ba26ee3d1 100644 --- a/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java @@ -98,11 +98,14 @@ public class Body { return StringUtils.equals(type, XML); } - public boolean isWwwFROM() { - return StringUtils.equals(type, WWW_FROM); + public void initKvs() { + this.kvs = new ArrayList<>(); + this.kvs.add(new KeyValue()); } - public boolean isFromData() { - return StringUtils.equals(type, FORM_DATA); + public void initBinary() { + this.binary = new ArrayList<>(); + this.binary.add(new KeyValue()); } + } diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java b/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java index 25a9e982a1..328517e501 100644 --- a/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/KeyValue.java @@ -15,7 +15,7 @@ public class KeyValue { private List files; private String description; private String contentType; - private boolean enable; + private boolean enable = true; private boolean encode = true; private boolean required; diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/controller/IfController.java b/backend/src/main/java/io/metersphere/api/dto/scenario/controller/IfController.java index 0e7a89e69a..93833257fa 100644 --- a/backend/src/main/java/io/metersphere/api/dto/scenario/controller/IfController.java +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/controller/IfController.java @@ -1,7 +1,6 @@ package io.metersphere.api.dto.scenario.controller; import lombok.Data; -import org.apache.commons.lang3.StringUtils; @Data public class IfController { @@ -11,46 +10,4 @@ public class IfController { private String variable; private String operator; private String value; - - public boolean isValid() { - if (StringUtils.contains(operator, "empty")) { - return StringUtils.isNotBlank(variable); - } - return StringUtils.isNotBlank(variable) && StringUtils.isNotBlank(operator) && StringUtils.isNotBlank(value); - } - - public String getLabel() { - if (isValid()) { - String label = variable + " " + operator; - if (StringUtils.isNotBlank(value)) { - label += " " + this.value; - } - return label; - } - return ""; - } - - public String getCondition() { - String variable = "\"" + this.variable + "\""; - String operator = this.operator; - String value = "\"" + this.value + "\""; - - if (StringUtils.contains(operator, "~")) { - value = "\".*" + this.value + ".*\""; - } - - if (StringUtils.equals(operator, "is empty")) { - variable = "empty(" + variable + ")"; - operator = ""; - value = ""; - } - - if (StringUtils.equals(operator, "is not empty")) { - variable = "!empty(" + variable + ")"; - operator = ""; - value = ""; - } - - return "${__jexl3(" + variable + operator + value + ")}"; - } } diff --git a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java index e455e98637..4b80284658 100644 --- a/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java +++ b/backend/src/main/java/io/metersphere/api/parse/ApiImportAbstractParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -72,7 +73,7 @@ public abstract class ApiImportAbstractParser implements ApiImportParser { protected ApiDefinitionResult buildApiDefinition(String id, String name, String path, String method) { ApiDefinitionResult apiDefinition = new ApiDefinitionResult(); apiDefinition.setName(name); - apiDefinition.setPath(path); + apiDefinition.setPath(formatPath(path)); apiDefinition.setProtocol(RequestType.HTTP); apiDefinition.setMethod(method); apiDefinition.setId(id); @@ -81,17 +82,34 @@ public abstract class ApiImportAbstractParser implements ApiImportParser { return apiDefinition; } + private String formatPath(String url) { + try { + URL urlObject = new URL(url); + StringBuffer pathBuffer = new StringBuffer(urlObject.getPath()); + if (StringUtils.isNotEmpty(urlObject.getQuery())) { + pathBuffer.append("?").append(urlObject.getQuery()); + } + return pathBuffer.toString(); + } catch (Exception ex) { + return url; + } + } + protected MsHTTPSamplerProxy buildRequest(String name, String path, String method) { MsHTTPSamplerProxy request = new MsHTTPSamplerProxy(); request.setName(name); - request.setPath(path); + // 路径去掉域名/IP 地址,保留方法名称及参数 + request.setPath(formatPath(path)); request.setMethod(method); request.setProtocol(RequestType.HTTP); request.setId(UUID.randomUUID().toString()); request.setHeaders(new ArrayList<>()); request.setArguments(new ArrayList<>()); request.setRest(new ArrayList<>()); - request.setBody(new Body()); + Body body = new Body(); + body.initKvs(); + body.initBinary(); + request.setBody(body); return request; } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtScheduleMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtScheduleMapper.xml index 5e599d5993..fe30863df5 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtScheduleMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtScheduleMapper.xml @@ -51,5 +51,11 @@ INNER JOIN `schedule` sch ON apiTest.id = sch.resource_id INNER JOIN `user` u ON u.id = sch.user_id WHERE sch.`enable` = true AND sch.workspace_id = #{0,jdbcType=VARCHAR} + UNION + SELECT apiTest.`name` AS scenario,sch.id AS taskID,sch.`value` AS rule,sch.`enable` AS `taskStatus`,u.`name` AS creator,sch.update_time AS updateTime + FROM api_scenario apiTest + INNER JOIN `schedule` sch ON apiTest.id = sch.resource_id + INNER JOIN `user` u ON u.id = sch.user_id + WHERE sch.`enable` = true AND sch.workspace_id = #{0,jdbcType=VARCHAR} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/controller/ProjectController.java b/backend/src/main/java/io/metersphere/controller/ProjectController.java index 2ce466d0d9..edf0d20024 100644 --- a/backend/src/main/java/io/metersphere/controller/ProjectController.java +++ b/backend/src/main/java/io/metersphere/controller/ProjectController.java @@ -9,7 +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.CheckPermissionService; import io.metersphere.service.ProjectService; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; @@ -24,7 +24,7 @@ public class ProjectController { @Resource private ProjectService projectService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @GetMapping("/listAll") public List listAll() { @@ -74,7 +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); + checkPermissionService.checkProjectOwner(projectId); projectService.deleteProject(projectId); } diff --git a/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java b/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java index dd07e05aaa..828cd04e5a 100644 --- a/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java +++ b/backend/src/main/java/io/metersphere/performance/controller/PerformanceReportController.java @@ -53,6 +53,7 @@ public class PerformanceReportController { } @PostMapping("/delete/{reportId}") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void deleteReport(@PathVariable String reportId) { reportService.deleteReport(reportId); } @@ -130,6 +131,7 @@ public class PerformanceReportController { } @PostMapping("/batch/delete") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR) public void deleteReportBatch(@RequestBody DeleteReportRequest reportRequest) { reportService.deleteReportBatch(reportRequest); } 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 9f49ebdacc..893ece5c87 100644 --- a/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java +++ b/backend/src/main/java/io/metersphere/performance/controller/PerformanceTestController.java @@ -14,7 +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.CheckPermissionService; import io.metersphere.service.FileService; import io.metersphere.track.request.testplan.*; import org.apache.shiro.authz.annotation.Logical; @@ -37,7 +37,7 @@ public class PerformanceTestController { @Resource private FileService fileService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @GetMapping("recent/{count}") public List recentTestPlans(@PathVariable int count) { @@ -59,14 +59,14 @@ public class PerformanceTestController { @GetMapping("/list/{projectId}") public List list(@PathVariable String projectId) { - checkOwnerService.checkProjectOwner(projectId); + checkPermissionService.checkProjectOwner(projectId); return performanceTestService.getLoadTestByProjectId(projectId); } @GetMapping("/state/get/{testId}") public LoadTest listByTestId(@PathVariable String testId) { - checkOwnerService.checkPerformanceTestOwner(testId); + checkPermissionService.checkPerformanceTestOwner(testId); return performanceTestService.getLoadTestBytestId(testId); } @@ -75,6 +75,7 @@ public class PerformanceTestController { @RequestPart("request") SaveTestPlanRequest request, @RequestPart(value = "file") List files ) { + checkPermissionService.checkReadOnlyUser(); return performanceTestService.save(request, files); } @@ -83,37 +84,39 @@ public class PerformanceTestController { @RequestPart("request") EditTestPlanRequest request, @RequestPart(value = "file", required = false) List files ) { - checkOwnerService.checkPerformanceTestOwner(request.getId()); + checkPermissionService.checkReadOnlyUser(); + checkPermissionService.checkPerformanceTestOwner(request.getId()); return performanceTestService.edit(request, files); } @GetMapping("/get/{testId}") public LoadTestDTO get(@PathVariable String testId) { - checkOwnerService.checkPerformanceTestOwner(testId); + checkPermissionService.checkPerformanceTestOwner(testId); return performanceTestService.get(testId); } @GetMapping("/get-advanced-config/{testId}") public String getAdvancedConfiguration(@PathVariable String testId) { - checkOwnerService.checkPerformanceTestOwner(testId); + checkPermissionService.checkPerformanceTestOwner(testId); return performanceTestService.getAdvancedConfiguration(testId); } @GetMapping("/get-load-config/{testId}") public String getLoadConfiguration(@PathVariable String testId) { - checkOwnerService.checkPerformanceTestOwner(testId); + checkPermissionService.checkPerformanceTestOwner(testId); return performanceTestService.getLoadConfiguration(testId); } @GetMapping("/get-jmx-content/{testId}") public String getJmxContent(@PathVariable String testId) { - checkOwnerService.checkPerformanceTestOwner(testId); + checkPermissionService.checkPerformanceTestOwner(testId); return performanceTestService.getJmxContent(testId); } @PostMapping("/delete") public void delete(@RequestBody DeleteTestPlanRequest request) { - checkOwnerService.checkPerformanceTestOwner(request.getId()); + checkPermissionService.checkReadOnlyUser(); + checkPermissionService.checkPerformanceTestOwner(request.getId()); performanceTestService.delete(request); } @@ -129,7 +132,7 @@ public class PerformanceTestController { @GetMapping("/file/metadata/{testId}") public List getFileMetadata(@PathVariable String testId) { - checkOwnerService.checkPerformanceTestOwner(testId); + checkPermissionService.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/CheckPermissionService.java similarity index 76% rename from backend/src/main/java/io/metersphere/service/CheckOwnerService.java rename to backend/src/main/java/io/metersphere/service/CheckPermissionService.java index 84a100406a..cf7d210370 100644 --- a/backend/src/main/java/io/metersphere/service/CheckOwnerService.java +++ b/backend/src/main/java/io/metersphere/service/CheckPermissionService.java @@ -9,7 +9,6 @@ import io.metersphere.commons.utils.SessionUtils; import io.metersphere.i18n.Translator; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.shiro.authz.UnauthorizedException; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -18,7 +17,7 @@ import java.util.Set; import java.util.stream.Collectors; @Service -public class CheckOwnerService { +public class CheckPermissionService { @Resource private ProjectMapper projectMapper; @Resource @@ -32,6 +31,20 @@ public class CheckOwnerService { @Resource private ExtTestCaseReviewMapper extTestCaseReviewMapper; + + public void checkReadOnlyUser() { + String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId(); + Set collect = Objects.requireNonNull(SessionUtils.getUser()).getUserRoles().stream() + .filter(ur -> + StringUtils.equals(ur.getRoleId(), RoleConstants.TEST_VIEWER)) + .map(UserRole::getSourceId) + .filter(sourceId -> StringUtils.equals(currentWorkspaceId, sourceId)) + .collect(Collectors.toSet()); + if (CollectionUtils.isNotEmpty(collect)) { + throw new RuntimeException(Translator.get("check_owner_read_only")); + } + } + public void checkProjectOwner(String projectId) { Set workspaceIds = getUserRelatedWorkspaceIds(); Project project = projectMapper.selectByPrimaryKey(projectId); @@ -42,7 +55,7 @@ public class CheckOwnerService { return; } if (!workspaceIds.contains(project.getWorkspaceId())) { - throw new UnauthorizedException(Translator.get("check_owner_project")); + throw new RuntimeException(Translator.get("check_owner_project")); } } @@ -67,7 +80,7 @@ public class CheckOwnerService { int result = extApiTestMapper.checkApiTestOwner(testId, workspaceIds); if (result == 0) { - throw new UnauthorizedException(Translator.get("check_owner_test")); + throw new RuntimeException(Translator.get("check_owner_test")); } } @@ -83,7 +96,7 @@ public class CheckOwnerService { int result = extLoadTestMapper.checkLoadTestOwner(testId, workspaceIds); if (result == 0) { - throw new UnauthorizedException(Translator.get("check_owner_test")); + throw new RuntimeException(Translator.get("check_owner_test")); } } @@ -95,7 +108,7 @@ public class CheckOwnerService { int result = extTestCaseMapper.checkIsHave(caseId, workspaceIds); if (result == 0) { - throw new UnauthorizedException(Translator.get("check_owner_case")); + throw new RuntimeException(Translator.get("check_owner_case")); } } @@ -106,7 +119,7 @@ public class CheckOwnerService { } int result = extTestPlanMapper.checkIsHave(planId, workspaceIds); if (result == 0) { - throw new UnauthorizedException(Translator.get("check_owner_plan")); + throw new RuntimeException(Translator.get("check_owner_plan")); } } @@ -117,7 +130,7 @@ public class CheckOwnerService { } int result = extTestCaseReviewMapper.checkIsHave(reviewId, workspaceIds); if (result == 0) { - throw new UnauthorizedException(Translator.get("check_owner_review")); + throw new RuntimeException(Translator.get("check_owner_review")); } } } 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 5a5643202d..e87d9cd916 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseController.java @@ -11,7 +11,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.service.CheckPermissionService; import io.metersphere.service.FileService; import io.metersphere.track.dto.TestCaseDTO; import io.metersphere.track.request.testcase.EditTestCaseRequest; @@ -39,7 +39,7 @@ public class TestCaseController { @Resource TestCaseService testCaseService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @Resource private FileService fileService; @@ -51,7 +51,7 @@ public class TestCaseController { @GetMapping("/list/{projectId}") public List list(@PathVariable String projectId) { - checkOwnerService.checkProjectOwner(projectId); + checkPermissionService.checkProjectOwner(projectId); QueryTestCaseRequest request = new QueryTestCaseRequest(); request.setProjectId(projectId); return testCaseService.listTestCase(request); @@ -94,13 +94,13 @@ public class TestCaseController { @GetMapping("/get/{testCaseId}") public TestCaseWithBLOBs getTestCase(@PathVariable String testCaseId) { - checkOwnerService.checkTestCaseOwner(testCaseId); + checkPermissionService.checkTestCaseOwner(testCaseId); return testCaseService.getTestCase(testCaseId); } @GetMapping("/project/{testCaseId}") public Project getProjectByTestCaseId(@PathVariable String testCaseId) { - checkOwnerService.checkTestCaseOwner(testCaseId); + checkPermissionService.checkTestCaseOwner(testCaseId); return testCaseService.getProjectByTestCaseId(testCaseId); } @@ -119,14 +119,14 @@ public class TestCaseController { @PostMapping("/delete/{testCaseId}") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) public int deleteTestCase(@PathVariable String testCaseId) { - checkOwnerService.checkTestCaseOwner(testCaseId); + checkPermissionService.checkTestCaseOwner(testCaseId); return testCaseService.deleteTestCase(testCaseId); } @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) { - checkOwnerService.checkProjectOwner(projectId); + checkPermissionService.checkProjectOwner(projectId); return testCaseService.testCaseImport(file, projectId, userId); } 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 0a7f52ee72..e651e58aee 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseNodeController.java @@ -2,7 +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.service.CheckPermissionService; import io.metersphere.track.dto.TestCaseNodeDTO; import io.metersphere.track.request.testcase.DragNodeRequest; import io.metersphere.track.request.testcase.QueryNodeRequest; @@ -22,11 +22,11 @@ public class TestCaseNodeController { @Resource TestCaseNodeService testCaseNodeService; @Resource - private CheckOwnerService checkOwnerService; + private CheckPermissionService checkPermissionService; @GetMapping("/list/{projectId}") public List getNodeByProjectId(@PathVariable String projectId) { - checkOwnerService.checkProjectOwner(projectId); + checkPermissionService.checkProjectOwner(projectId); return testCaseNodeService.getNodeTreeByProjectId(projectId); } @@ -43,13 +43,13 @@ public class TestCaseNodeController { @GetMapping("/list/plan/{planId}") public List getNodeByPlanId(@PathVariable String planId) { - checkOwnerService.checkTestPlanOwner(planId); + checkPermissionService.checkTestPlanOwner(planId); return testCaseNodeService.getNodeByPlanId(planId); } @GetMapping("/list/review/{reviewId}") public List getNodeByReviewId(@PathVariable String reviewId) { - checkOwnerService.checkTestReviewOwner(reviewId); + checkPermissionService.checkTestReviewOwner(reviewId); return testCaseNodeService.getNodeByReviewId(reviewId); } diff --git a/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java b/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java index d9a755d0f9..84d9b809ef 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestCaseReviewController.java @@ -9,7 +9,7 @@ import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; -import io.metersphere.service.CheckOwnerService; +import io.metersphere.service.CheckPermissionService; import io.metersphere.track.dto.TestCaseReviewDTO; import io.metersphere.track.dto.TestReviewDTOWithMetric; import io.metersphere.track.request.testreview.QueryCaseReviewRequest; @@ -35,7 +35,7 @@ public class TestCaseReviewController { @Resource TestReviewProjectService testReviewProjectService; @Resource - CheckOwnerService checkOwnerService; + CheckPermissionService checkPermissionService; @PostMapping("/list/{goPage}/{pageSize}") public Pager> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryCaseReviewRequest request) { @@ -75,7 +75,7 @@ public class TestCaseReviewController { @GetMapping("/delete/{reviewId}") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) public void deleteCaseReview(@PathVariable String reviewId) { - checkOwnerService.checkTestReviewOwner(reviewId); + checkPermissionService.checkTestReviewOwner(reviewId); testCaseReviewService.deleteCaseReview(reviewId); } @@ -107,14 +107,14 @@ public class TestCaseReviewController { @GetMapping("/get/{reviewId}") public TestCaseReview getTestReview(@PathVariable String reviewId) { - checkOwnerService.checkTestReviewOwner(reviewId); + checkPermissionService.checkTestReviewOwner(reviewId); return testCaseReviewService.getTestReview(reviewId); } @PostMapping("/edit/status/{reviewId}") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) public void editTestPlanStatus(@PathVariable String reviewId) { - checkOwnerService.checkTestReviewOwner(reviewId); + checkPermissionService.checkTestReviewOwner(reviewId); testCaseReviewService.editTestReviewStatus(reviewId); } diff --git a/backend/src/main/java/io/metersphere/track/controller/TestPlanController.java b/backend/src/main/java/io/metersphere/track/controller/TestPlanController.java index f6dba70cdd..b5240048a6 100644 --- a/backend/src/main/java/io/metersphere/track/controller/TestPlanController.java +++ b/backend/src/main/java/io/metersphere/track/controller/TestPlanController.java @@ -8,7 +8,7 @@ import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; -import io.metersphere.service.CheckOwnerService; +import io.metersphere.service.CheckPermissionService; import io.metersphere.track.dto.TestCaseReportMetricDTO; import io.metersphere.track.dto.TestPlanDTO; import io.metersphere.track.dto.TestPlanDTOWithMetric; @@ -34,7 +34,7 @@ public class TestPlanController { @Resource TestPlanProjectService testPlanProjectService; @Resource - CheckOwnerService checkOwnerService; + CheckPermissionService checkPermissionService; @PostMapping("/list/{goPage}/{pageSize}") public Pager> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanRequest request) { @@ -73,7 +73,7 @@ public class TestPlanController { @PostMapping("/get/{testPlanId}") public TestPlan getTestPlan(@PathVariable String testPlanId) { - checkOwnerService.checkTestPlanOwner(testPlanId); + checkPermissionService.checkTestPlanOwner(testPlanId); return testPlanService.getTestPlan(testPlanId); } @@ -92,14 +92,14 @@ public class TestPlanController { @PostMapping("/edit/status/{planId}") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) public void editTestPlanStatus(@PathVariable String planId) { - checkOwnerService.checkTestPlanOwner(planId); + checkPermissionService.checkTestPlanOwner(planId); testPlanService.editTestPlanStatus(planId); } @PostMapping("/delete/{testPlanId}") @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) public int deleteTestPlan(@PathVariable String testPlanId) { - checkOwnerService.checkTestPlanOwner(testPlanId); + checkPermissionService.checkTestPlanOwner(testPlanId); return testPlanService.deleteTestPlan(testPlanId); } diff --git a/backend/src/main/java/io/metersphere/xpack b/backend/src/main/java/io/metersphere/xpack index bb494fc68a..9f4a9bbf46 160000 --- a/backend/src/main/java/io/metersphere/xpack +++ b/backend/src/main/java/io/metersphere/xpack @@ -1 +1 @@ -Subproject commit bb494fc68a2367359c9048fa7250c7618de4afb6 +Subproject commit 9f4a9bbf46fc1333dbcccea21f83e27e3ec10b1f diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index b627fe4fb5..5ce5011793 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -164,6 +164,7 @@ check_owner_case=The current user does not have permission to operate this use c check_owner_plan=The current user does not have permission to operate this plan check_owner_review=The current user does not have permission to operate this review check_owner_comment=The current user does not have permission to manipulate this comment +check_owner_read_only=The current user in this workspace is a read-only user upload_content_is_null=Imported content is empty test_plan_notification=Test plan notification task_defect_notification=Task defect notification diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index 89c8359ead..a9824e3984 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -165,6 +165,7 @@ check_owner_case=当前用户没有操作此用例的权限 check_owner_plan=当前用户没有操作此计划的权限 check_owner_review=当前用户没有操作此评审的权限 check_owner_comment=当前用户没有操作此评论的权限 +check_owner_read_only=当前用户在此工作空间为只读用户 upload_content_is_null=导入内容为空 test_plan_notification=测试计划通知 task_defect_notification=缺陷任务通知 diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index ddd705a53e..f6e5762210 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -166,6 +166,7 @@ check_owner_case=當前用戶沒有操作此用例的權限 check_owner_plan=當前用戶沒有操作此計劃的權限 check_owner_review=當前用戶沒有操作此評審的權限 check_owner_comment=當前用戶沒有操作此評論的權限 +check_owner_read_only=當前用戶在此工作空間為只讀用戶 upload_content_is_null=導入內容為空 test_plan_notification=測試計畫通知 task_defect_notification=缺陷任務通知 diff --git a/frontend/src/business/components/api/automation/ApiAutomation.vue b/frontend/src/business/components/api/automation/ApiAutomation.vue index fa812a1468..d1ed00a250 100644 --- a/frontend/src/business/components/api/automation/ApiAutomation.vue +++ b/frontend/src/business/components/api/automation/ApiAutomation.vue @@ -1,14 +1,14 @@