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:
parent
8cea318c52
commit
87adb90a0f
|
@ -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";
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue