fix(测试跟踪): 测试计划与缺陷页面权限问题

--bug=1027245 --user=陈建星 【测试跟踪】缺陷没有创建权限,但在功能用例详情中按键依然可以点击,但会跳转403 https://www.tapd.cn/55049933/s/1384217
--bug=1027244 --user=陈建星 【测试跟踪】缺陷管理-没有复制权限位,只开启编辑的情况下依然可以点击按钮,但会403 https://www.tapd.cn/55049933/s/1384219
--bug=1027243 --user=陈建星 【测试跟踪】建议没有导出报告权限将按键置灰 https://www.tapd.cn/55049933/s/1384223
--bug=1027242 --user=陈建星 【测试跟踪】测试计划-开启批量编辑权限后功能失效 https://www.tapd.cn/55049933/s/1384224
--bug=1027237 --user=陈建星 【测试跟踪】测试计划开启执行测试计划权限,测试列表中无法通过执行结果字段进行更改测试结果 https://www.tapd.cn/55049933/s/1384255
--bug=1027236 --user=陈建星 【测试跟踪】测试计划没有开启复制计划权限但依然可对计划复制 https://www.tapd.cn/55049933/s/1384259
This commit is contained in:
jianxing 2023-06-20 17:26:09 +08:00 committed by jianxing
parent 8cea318c52
commit 87adb90a0f
10 changed files with 35 additions and 14 deletions

View File

@ -111,11 +111,14 @@ public class PermissionConstants {
public static final String PROJECT_TRACK_PLAN_READ = "PROJECT_TRACK_PLAN:READ"; public static final String PROJECT_TRACK_PLAN_READ = "PROJECT_TRACK_PLAN:READ";
public static final String PROJECT_TRACK_PLAN_READ_CREATE = "PROJECT_TRACK_PLAN:READ+CREATE"; public static final String PROJECT_TRACK_PLAN_READ_CREATE = "PROJECT_TRACK_PLAN:READ+CREATE";
public static final String PROJECT_TRACK_PLAN_READ_COPY = "PROJECT_TRACK_PLAN:READ+COPY";
public static final String PROJECT_TRACK_PLAN_READ_EDIT = "PROJECT_TRACK_PLAN:READ+EDIT"; public static final String PROJECT_TRACK_PLAN_READ_EDIT = "PROJECT_TRACK_PLAN:READ+EDIT";
public static final String PROJECT_TRACK_PLAN_READ_DELETE = "PROJECT_TRACK_PLAN:READ+DELETE"; public static final String PROJECT_TRACK_PLAN_READ_DELETE = "PROJECT_TRACK_PLAN:READ+DELETE";
public static final String PROJECT_TRACK_PLAN_READ_SCHEDULE = "PROJECT_TRACK_PLAN:READ+SCHEDULE"; public static final String PROJECT_TRACK_PLAN_READ_SCHEDULE = "PROJECT_TRACK_PLAN:READ+SCHEDULE";
public static final String PROJECT_TRACK_PLAN_READ_RELEVANCE_OR_CANCEL = "PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL"; public static final String PROJECT_TRACK_PLAN_READ_RELEVANCE_OR_CANCEL = "PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL";
public static final String PROJECT_TRACK_PLAN_READ_CASE_BATCH_DELETE = "PROJECT_TRACK_PLAN:READ+CASE_BATCH_DELETE";
public static final String PROJECT_TRACK_PLAN_READ_RUN = "PROJECT_TRACK_PLAN:READ+RUN"; public static final String PROJECT_TRACK_PLAN_READ_RUN = "PROJECT_TRACK_PLAN:READ+RUN";
public static final String PROJECT_TRACK_PLAN_READ_CASE_BATCH_EDIT = "PROJECT_TRACK_PLAN:READ+CASE_BATCH_EDIT";
public static final String PROJECT_TRACK_ISSUE_READ = "PROJECT_TRACK_ISSUE:READ"; public static final String PROJECT_TRACK_ISSUE_READ = "PROJECT_TRACK_ISSUE:READ";
public static final String PROJECT_TRACK_ISSUE_READ_CREATE = "PROJECT_TRACK_ISSUE:READ+CREATE"; public static final String PROJECT_TRACK_ISSUE_READ_CREATE = "PROJECT_TRACK_ISSUE:READ+CREATE";

View File

@ -25,7 +25,6 @@ public class CustomFieldTemplateController {
} }
@PostMapping("/update") @PostMapping("/update")
@RequiresPermissions(PermissionConstants.PROJECT_TEMPLATE_READ_CUSTOM)
public void update(@RequestBody CustomFieldTemplate request) { public void update(@RequestBody CustomFieldTemplate request) {
customFieldTemplateService.update(request); customFieldTemplateService.update(request);
} }

View File

@ -266,7 +266,7 @@ public class TestCaseController {
} }
@PostMapping(value = "/edit/testPlan", consumes = {"multipart/form-data"}) @PostMapping(value = "/edit/testPlan", consumes = {"multipart/form-data"})
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT) @RequiresPermissions(value = {PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT, PermissionConstants.PROJECT_TRACK_PLAN_READ_RUN}, logical = Logical.OR)
@MsAuditLog(module = OperLogModule.TRACK_TEST_CASE, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogBeforeDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = TestCaseService.class) @MsAuditLog(module = OperLogModule.TRACK_TEST_CASE, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogBeforeDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = TestCaseService.class)
public String editTestCaseByTestPlan(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file", required = false) List<MultipartFile> files) { public String editTestCaseByTestPlan(@RequestPart("request") EditTestCaseRequest request, @RequestPart(value = "file", required = false) List<MultipartFile> files) {
return testCaseService.editTestCase(request, files, Boolean.TRUE); return testCaseService.editTestCase(request, files, Boolean.TRUE);

View File

@ -21,6 +21,7 @@ import io.metersphere.track.request.testplan.TestPlanRunRequest;
import io.metersphere.track.request.testplancase.TestCaseRelevanceRequest; import io.metersphere.track.request.testplancase.TestCaseRelevanceRequest;
import io.metersphere.track.service.TestPlanProjectService; import io.metersphere.track.service.TestPlanProjectService;
import io.metersphere.track.service.TestPlanService; import io.metersphere.track.service.TestPlanService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -193,7 +194,7 @@ public class TestPlanController {
} }
@PostMapping("/copy/{id}") @PostMapping("/copy/{id}")
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_PLAN_READ_CREATE) @RequiresPermissions(value = {PermissionConstants.PROJECT_TRACK_PLAN_READ_CREATE, PermissionConstants.PROJECT_TRACK_PLAN_READ_COPY}, logical = Logical.OR)
@SendNotice(taskType = NoticeConstants.TaskType.TEST_PLAN_TASK, event = NoticeConstants.Event.CREATE, subject = "测试计划通知") @SendNotice(taskType = NoticeConstants.TaskType.TEST_PLAN_TASK, event = NoticeConstants.Event.CREATE, subject = "测试计划通知")
public TestPlan copy(@PathVariable String id) { public TestPlan copy(@PathVariable String id) {
return testPlanService.copy(id); return testPlanService.copy(id);

View File

@ -15,6 +15,7 @@ import io.metersphere.track.request.testcase.TestPlanCaseBatchRequest;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest; import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import io.metersphere.track.request.testplancase.TestPlanFuncCaseBatchRequest; import io.metersphere.track.request.testplancase.TestPlanFuncCaseBatchRequest;
import io.metersphere.track.service.TestPlanTestCaseService; import io.metersphere.track.service.TestPlanTestCaseService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -132,14 +133,14 @@ public class TestPlanTestCaseController {
} }
@PostMapping("/batch/edit") @PostMapping("/batch/edit")
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_PLAN_READ_RUN) @RequiresPermissions(value = {PermissionConstants.PROJECT_TRACK_PLAN_READ_RUN, PermissionConstants.PROJECT_TRACK_PLAN_READ_CASE_BATCH_EDIT}, logical = Logical.OR)
@MsAuditLog(module = OperLogModule.TRACK_TEST_PLAN, type = OperLogConstants.BATCH_UPDATE, beforeEvent = "#msClass.batchLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = TestPlanTestCaseService.class) @MsAuditLog(module = OperLogModule.TRACK_TEST_PLAN, type = OperLogConstants.BATCH_UPDATE, beforeEvent = "#msClass.batchLogDetails(#request.ids)", content = "#msClass.getLogDetails(#request.ids)", msClass = TestPlanTestCaseService.class)
public void editTestCaseBath(@RequestBody TestPlanCaseBatchRequest request) { public void editTestCaseBath(@RequestBody TestPlanCaseBatchRequest request) {
testPlanTestCaseService.editTestCaseBath(request); testPlanTestCaseService.editTestCaseBath(request);
} }
@PostMapping("/batch/delete") @PostMapping("/batch/delete")
@RequiresPermissions(PermissionConstants.PROJECT_TRACK_PLAN_READ_RELEVANCE_OR_CANCEL) @RequiresPermissions(value = {PermissionConstants.PROJECT_TRACK_PLAN_READ_RELEVANCE_OR_CANCEL, PermissionConstants.PROJECT_TRACK_PLAN_READ_CASE_BATCH_DELETE}, logical = Logical.OR)
@MsAuditLog(module = OperLogModule.TRACK_TEST_PLAN, type = OperLogConstants.UN_ASSOCIATE_CASE, beforeEvent = "#msClass.getLogDetails(#request.ids)", msClass = TestPlanTestCaseService.class) @MsAuditLog(module = OperLogModule.TRACK_TEST_PLAN, type = OperLogConstants.UN_ASSOCIATE_CASE, beforeEvent = "#msClass.getLogDetails(#request.ids)", msClass = TestPlanTestCaseService.class)
public void deleteTestCaseBath(@RequestBody TestPlanCaseBatchRequest request) { public void deleteTestCaseBath(@RequestBody TestPlanCaseBatchRequest request) {
testPlanTestCaseService.deleteTestCaseBath(request); testPlanTestCaseService.deleteTestCaseBath(request);

View File

@ -1,7 +1,11 @@
<template> <template>
<div> <div>
<el-button class="add-btn" v-permission="['PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL']" :disabled="readOnly" type="primary" size="mini" @click="addIssue">{{ $t('test_track.issue.add_issue') }}</el-button> <el-button class="add-btn" v-if="hasAddIssuePermission" :disabled="readOnly" type="primary" size="mini" @click="addIssue">
<el-button class="add-btn" v-permission="['PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL']" :disabled="readOnly" type="primary" size="mini" @click="relateIssue">{{ $t('test_track.case.relate_issue') }}</el-button> {{ $t('test_track.issue.add_issue') }}
</el-button>
<el-button class="add-btn" v-if="hasRelateIssuePermission" :disabled="readOnly" type="primary" size="mini" @click="relateIssue">
{{ $t('test_track.case.relate_issue') }}
</el-button>
<el-tooltip class="item" v-permission="['PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL']" effect="dark" <el-tooltip class="item" v-permission="['PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL']" effect="dark"
:content="$t('test_track.issue.platform_tip')" :content="$t('test_track.issue.platform_tip')"
placement="right"> placement="right">
@ -111,7 +115,7 @@ import IssueRelateList from "@/business/components/track/case/components/IssueRe
import {deleteIssueRelate, getIssuePartTemplateWithProject, getIssuesByCaseId} from "@/network/Issue"; import {deleteIssueRelate, getIssuePartTemplateWithProject, getIssuesByCaseId} from "@/network/Issue";
import {getCustomFieldValue, getTableHeaderWithCustomFields} from "@/common/js/tableUtils"; import {getCustomFieldValue, getTableHeaderWithCustomFields} from "@/common/js/tableUtils";
import {LOCAL} from "@/common/js/constants"; import {LOCAL} from "@/common/js/constants";
import {getCurrentProjectID, getCurrentWorkspaceId} from "@/common/js/utils"; import {getCurrentProjectID, getCurrentWorkspaceId, hasPermission} from "@/common/js/utils";
export default { export default {
name: "TestCaseIssueRelate", name: "TestCaseIssueRelate",
components: {IssueRelateList, IssueDescriptionTableItem, MsTableColumn, MsTable, TestPlanIssueEdit}, components: {IssueRelateList, IssueDescriptionTableItem, MsTableColumn, MsTable, TestPlanIssueEdit},
@ -152,6 +156,18 @@ export default {
}, },
projectId() { projectId() {
return getCurrentProjectID(); return getCurrentProjectID();
},
hasAddIssuePermission() {
if (this.planId) {
return hasPermission("PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL") && hasPermission("PROJECT_TRACK_ISSUE:READ+CREATE");
}
return hasPermission("PROJECT_TRACK_CASE:READ+EDIT") && hasPermission("PROJECT_TRACK_ISSUE:READ+CREATE");
},
hasRelateIssuePermission() {
if (this.planId) {
return hasPermission("PROJECT_TRACK_PLAN:READ+RELEVANCE_OR_CANCEL") && hasPermission("PROJECT_TRACK_ISSUE:READ");
}
return hasPermission("PROJECT_TRACK_CASE:READ+EDIT") && hasPermission("PROJECT_TRACK_ISSUE:READ");
} }
}, },
created() { created() {

View File

@ -220,7 +220,8 @@ export default {
}, { }, {
tip: this.$t('commons.copy'), icon: "el-icon-copy-document", type: "success", tip: this.$t('commons.copy'), icon: "el-icon-copy-document", type: "success",
exec: this.handleCopy, exec: this.handleCopy,
isDisable: this.btnDisable isDisable: this.btnDisable,
permissions: ['PROJECT_TRACK_ISSUE:READ+CREATE']
}, { }, {
tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger", tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger",
exec: this.handleDelete, exec: this.handleDelete,

View File

@ -444,7 +444,7 @@ export default {
{ {
name: this.$t('api_test.automation.batch_execute'), name: this.$t('api_test.automation.batch_execute'),
handleClick: this.handleBatchExecute, handleClick: this.handleBatchExecute,
permissions: ['PROJECT_TRACK_PLAN:READ+SCHEDULE'] permissions: ['PROJECT_TRACK_PLAN:READ+RUN']
} }
], ],
simpleOperators: [ simpleOperators: [
@ -452,13 +452,13 @@ export default {
tip: this.$t('commons.copy'), tip: this.$t('commons.copy'),
icon: "el-icon-copy-document", icon: "el-icon-copy-document",
exec: this.handleCopy, exec: this.handleCopy,
permission: ['PROJECT_TRACK_PLAN:READ+COPY'] permissions: ['PROJECT_TRACK_PLAN:READ+COPY']
}, },
{ {
tip: this.$t('test_track.plan_view.view_report'), tip: this.$t('test_track.plan_view.view_report'),
icon: "el-icon-s-data", icon: "el-icon-s-data",
exec: this.openReport, exec: this.openReport,
permission: ['PROJECT_TRACK_PLAN:READ+EDIT'] permissions: ['PROJECT_TRACK_PLAN:READ+EDIT']
}, },
], ],
batchExecuteType: "serial" batchExecuteType: "serial"

View File

@ -493,7 +493,7 @@ export default {
this.$emit('setCondition', this.condition); this.$emit('setCondition', this.condition);
this.$EventBus.$on("openFailureTestCase", this.handleOpenFailureTestCase); this.$EventBus.$on("openFailureTestCase", this.handleOpenFailureTestCase);
this.refreshTableAndPlan(); this.refreshTableAndPlan();
this.hasEditPermission = hasPermission('PROJECT_TRACK_PLAN:READ+EDIT'); this.hasEditPermission = hasPermission('PROJECT_TRACK_PLAN:READ+RUN');
this.getMaintainerOptions(); this.getMaintainerOptions();
this.getTemplateField(); this.getTemplateField();
this.getVersionOptions(); this.getVersionOptions();

View File

@ -22,7 +22,7 @@
</el-button> </el-button>
</el-row> </el-row>
<el-row> <el-row>
<el-button icon="el-icon-download" :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleExportHtml()"> <el-button v-permission="['PROJECT_TRACK_REPORT:READ+EXPORT']" icon="el-icon-download" :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleExportHtml()">
{{ $t('commons.export')}} {{ $t('commons.export')}}
</el-button> </el-button>
</el-row> </el-row>