fix(测试跟踪): 功能用例权限相关
--bug=1024454 --user=宋昌昌 【测试跟踪】只读权限用户,无法查看用例 https://www.tapd.cn/55049933/s/1351748, --bug=1024530 --user=宋昌昌 github #22784【用户组与权限】项目成员不勾选“删除用例”的权限,【测试跟踪-功能用例】页面,勾选某条用例,发现下面还有“删除”的选项,建议隐藏不显示。 https://www.tapd.cn/55049933/s/1351752, --bug=1024527 --user=宋昌昌 github #22781【用户组与权限】不勾选“删除用例”权限,在用例详情页面,【更多】里有删除按钮且能正常删除该用例。 https://www.tapd.cn/55049933/s/1351755
This commit is contained in:
parent
444381ff11
commit
c8a7647bd8
|
@ -58,13 +58,13 @@
|
|||
<el-dropdown placement="bottom-start" v-if="data.id && data.id !== 'root' && data.name !== defaultLabel && !hideNodeOperator" trigger="click">
|
||||
<el-button class="node-operate-btn" icon="el-icon-more" />
|
||||
<el-dropdown-menu slot="dropdown" class="module-more-operate">
|
||||
<el-dropdown-item :disabled="!updatePermission">
|
||||
<el-dropdown-item :disabled="!hasPermissions(updatePermission)">
|
||||
<span @click.stop="edit(node, data)" class="more-operate-btn">
|
||||
<svg-icon icon-class="icon_global_rename" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('test_track.module.rename')}}
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!deletePermission" :divided="true">
|
||||
<el-dropdown-item :disabled="!hasPermissions(deletePermission)" :divided="true">
|
||||
<span @click.stop="remove(node, data)" class="more-operate-btn" style="color: #F54A45;">
|
||||
<svg-icon icon-class="icon_delete-trash_outlined_red" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('commons.delete')}}
|
||||
|
@ -76,13 +76,13 @@
|
|||
<el-dropdown placement="bottom-start" v-if="data.id && data.name === defaultLabel && data.level !== 1 && !hideNodeOperator" trigger="click">
|
||||
<el-button class="node-operate-btn"/>
|
||||
<el-dropdown-menu slot="dropdown" class="module-more-operate">
|
||||
<el-dropdown-item :disabled="!updatePermission">
|
||||
<el-dropdown-item :disabled="!hasPermissions(updatePermission)">
|
||||
<span @click.stop="edit(node, data)" class="more-operate-btn">
|
||||
<svg-icon icon-class="icon_global_rename" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('test_track.module.rename')}}
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!deletePermission" :divided="true">
|
||||
<el-dropdown-item :disabled="!hasPermissions(deletePermission)" :divided="true">
|
||||
<span @click.stop="remove(node, data)" class="more-operate-btn" style="color: #F54A45;">
|
||||
<svg-icon icon-class="icon_delete-trash_outlined_red" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('commons.delete')}}
|
||||
|
@ -149,13 +149,13 @@
|
|||
<el-dropdown placement="bottom-start" v-if="data.id && data.id !== 'root' && data.name !== defaultLabel && !hideNodeOperator">
|
||||
<el-button class="node-operate-btn" icon="el-icon-more"/>
|
||||
<el-dropdown-menu slot="dropdown" class="module-more-operate">
|
||||
<el-dropdown-item :disabled="!updatePermission">
|
||||
<el-dropdown-item :disabled="!hasPermissions(updatePermission)">
|
||||
<span @click.stop="edit(node, data)" class="more-operate-btn">
|
||||
<svg-icon icon-class="icon_global_rename" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('test_track.module.rename')}}
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!deletePermission" :divided="true">
|
||||
<el-dropdown-item :disabled="!hasPermissions(deletePermission)" :divided="true">
|
||||
<span @click.stop="remove(node, data)" class="more-operate-btn" style="color: #F54A45;">
|
||||
<svg-icon icon-class="icon_delete-trash_outlined_red" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('commons.delete')}}
|
||||
|
@ -167,13 +167,13 @@
|
|||
<el-dropdown placement="bottom-start" v-if="data.id && data.name === defaultLabel && data.level !== 1 && !hideNodeOperator">
|
||||
<el-button class="node-operate-btn"/>
|
||||
<el-dropdown-menu slot="dropdown" class="module-more-operate">
|
||||
<el-dropdown-item :disabled="!updatePermission">
|
||||
<el-dropdown-item :disabled="!hasPermissions(updatePermission)">
|
||||
<span @click.stop="edit(node, data)" class="more-operate-btn">
|
||||
<svg-icon icon-class="icon_global_rename" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('test_track.module.rename')}}
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="!deletePermission" :divided="true">
|
||||
<el-dropdown-item :disabled="!hasPermissions(deletePermission)" :divided="true">
|
||||
<span @click.stop="remove(node, data)" class="more-operate-btn" style="color: #F54A45;">
|
||||
<svg-icon icon-class="icon_delete-trash_outlined_red" style="margin-right: 9px; margin-top: 1px; width: 1.1em; height: 1.1em"/>
|
||||
{{$t('commons.delete')}}
|
||||
|
@ -193,6 +193,7 @@
|
|||
|
||||
<script>
|
||||
import MsLeft2RightContainer from "../MsLeft2RightContainer";
|
||||
import {hasPermissions} from "../../utils/permission";
|
||||
|
||||
export default {
|
||||
name: "MsNodeTree",
|
||||
|
@ -283,6 +284,9 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
hasPermissions(permission) {
|
||||
return hasPermissions(permission[0]);
|
||||
},
|
||||
init() {
|
||||
let num = 0;
|
||||
this.treeNodes.forEach(t => {
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
<el-dropdown-menu slot="dropdown" class="more-operate-menu-children" @mouseenter.native="() => $refs.parentMenu.show()" @mouseleave.native="() => $refs.parentMenu.hide()">
|
||||
<template v-for='childOperator in operator.children'>
|
||||
<el-dropdown-item v-if="isXPack(childOperator)" :disabled="isDisable(childOperator)" :divided="isDivide(childOperator)"
|
||||
@click.native.stop="click(childOperator)" @mouseenter="childMove" style="height: 50px">
|
||||
<span class="operator" :class="{active: operator.isActive}">{{childOperator.name}}</span>
|
||||
style="height: 50px" @click.native.stop="click(childOperator)" @mouseenter="childMove">
|
||||
<span class="operator" :class="{active: operator.isActive}" :style="isDisable(operator) ? 'color: #bbb!important' : ''">{{childOperator.name}}</span>
|
||||
<span class="tips">{{childOperator.tips}}</span>
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
|
@ -26,7 +26,7 @@
|
|||
</el-dropdown>
|
||||
</el-dropdown-item>
|
||||
<!-- 一级 -->
|
||||
<el-dropdown-item v-else :disabled="isDisable(operator)" :divided="isDivide(operator)" @click.native.stop="click(operator)" :key="index" :class="{active: operator.isActive}">
|
||||
<el-dropdown-item v-else :disabled="isDisable(operator)" :style="isDisable(operator) ? 'color: #bbb!important' : ''" :divided="isDivide(operator)" @click.native.stop="click(operator)" :key="index" :class="{active: operator.isActive}">
|
||||
{{ operator.name }}
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
|
@ -287,6 +287,10 @@ export default {
|
|||
font-size: 15px;
|
||||
color: #8F959E;
|
||||
}
|
||||
|
||||
.disabled-class {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -3209,7 +3209,7 @@ public class TestCaseService {
|
|||
public TestCaseWithBLOBs getSimpleCaseForEdit(String testCaseId) {
|
||||
TestCaseWithBLOBs testCase = testCaseMapper.selectByPrimaryKey(testCaseId);
|
||||
Project project = baseProjectService.getProjectById(testCase.getProjectId());
|
||||
if (!SessionUtils.hasPermission(project.getWorkspaceId(), project.getId(), PermissionConstants.PROJECT_TRACK_CASE_READ_EDIT)) {
|
||||
if (!SessionUtils.hasPermission(project.getWorkspaceId(), project.getId(), PermissionConstants.PROJECT_TRACK_CASE_READ)) {
|
||||
MSException.throwException(Translator.get("check_owner_project"));
|
||||
}
|
||||
return testCaseMapper.selectByPrimaryKey(testCaseId);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<ms-container v-if="renderComponent" v-loading="loading">
|
||||
<!-- operate-button -->
|
||||
<div class="top-btn-group-layout" v-if="!showPublicNode && !showTrashNode" style="margin-bottom: 16px">
|
||||
<el-button size="small" v-permission="['PROJECT_TRACK_CASE:READ+BATCH_EDIT']" @click="handleCreateCase" type="primary">
|
||||
<el-button size="small" v-permission="['PROJECT_TRACK_CASE:READ+CREATE']" @click="handleCreateCase" type="primary">
|
||||
<svg-icon icon-class="icon_add_outlined_white"/>
|
||||
{{$t('test_track.case.create_case')}}
|
||||
</el-button>
|
||||
|
@ -25,7 +25,7 @@
|
|||
</div>
|
||||
|
||||
<!-- public, trash back header -->
|
||||
<div v-if="showPublicNode || showTrashNode" class="back-layout">
|
||||
<div v-show="showPublicNode || showTrashNode" class="back-layout">
|
||||
<i class="el-icon-back" style="float: left;position: relative;top: 15px;left: 21px;" @click="activeName = 'default'"/>
|
||||
<span class="back-content">{{showPublicNode? $t('project.case_public') : $t('commons.trash')}}</span>
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
:is-add="isAdd"
|
||||
:editable-state="editableState"
|
||||
:is-name-edit.sync="isNameEdit"
|
||||
:is-public-show="isPublicShow"
|
||||
:is-public-show="isPublicShow || hasReadonlyPermission"
|
||||
:form="form"
|
||||
@save="saveCaseWithoutRefresh"
|
||||
/>
|
||||
|
@ -27,7 +27,7 @@
|
|||
ref="versionHistory"
|
||||
:current-id="currentTestCaseInfo.id"
|
||||
:is-read="readOnly"
|
||||
:is-public-show="isPublicShow"
|
||||
:is-public-show="isPublicShow || hasReadonlyPermission"
|
||||
:current-version-id="form.versionId"
|
||||
@confirmOtherInfo="confirmOtherInfo"
|
||||
:current-project-id="projectId"
|
||||
|
@ -115,7 +115,7 @@
|
|||
</div>
|
||||
<!-- 功能用例库头部按钮展示 -->
|
||||
<div
|
||||
class="follow-row head-opt" v-if="!isPublicShow"
|
||||
class="follow-row head-opt" v-if="!isPublicShow && !hasReadonlyPermission"
|
||||
@click="toEdit"
|
||||
>
|
||||
<div class="icon-row">
|
||||
|
@ -125,7 +125,7 @@
|
|||
</div>
|
||||
<div
|
||||
class="follow-row head-opt"
|
||||
v-if="!showFollow && !isPublicShow"
|
||||
v-if="!showFollow && !isPublicShow && !hasReadonlyPermission"
|
||||
@click="saveFollow"
|
||||
>
|
||||
<div class="icon-row">
|
||||
|
@ -135,7 +135,7 @@
|
|||
</div>
|
||||
<div
|
||||
class="follow-row head-opt"
|
||||
v-if="showFollow && !isPublicShow"
|
||||
v-if="showFollow && !isPublicShow && !hasReadonlyPermission"
|
||||
@click="saveFollow"
|
||||
>
|
||||
<div class="icon-row">
|
||||
|
@ -143,7 +143,7 @@
|
|||
</div>
|
||||
<div class="label-row">{{ $t("case.followed") }}</div>
|
||||
</div>
|
||||
<div class="more-row head-opt" v-if="!isPublicShow">
|
||||
<div class="more-row head-opt" v-if="!isPublicShow && !hasReadonlyPermission">
|
||||
<div class="icon-row" @mouseenter="$refs.headMoreOptPopover.doShow()" @mouseleave="$refs.headMoreOptPopover.doClose()">
|
||||
<img src="/assets/module/figma/icon_more_outlined.svg" alt="" />
|
||||
</div>
|
||||
|
@ -177,14 +177,14 @@
|
|||
<div class="title">{{ $t("case.added_to_public_case") }}</div>
|
||||
</div>
|
||||
<div class="split"></div>
|
||||
<div class="copy-row sub-opt-row" @click="copyRow">
|
||||
<div class="copy-row sub-opt-row" @click="copyRow" :style="!hasCopyPermission ? 'cursor: not-allowed' : 'cursor: default'">
|
||||
<div class="icon">
|
||||
<i class="el-icon-copy-document"></i>
|
||||
</div>
|
||||
<div class="title">{{ $t("commons.copy") }}</div>
|
||||
</div>
|
||||
<div class="split"></div>
|
||||
<div class="delete-row sub-opt-row" @click="deleteRow">
|
||||
<div class="delete-row sub-opt-row" @click="deleteRow" :style="!hasDeletePermission ? 'cursor: not-allowed' : 'cursor: default'">
|
||||
<div class="icon">
|
||||
<i class="el-icon-delete"></i>
|
||||
</div>
|
||||
|
@ -198,7 +198,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- 检测版本 是否不是最新 -->
|
||||
<div class="diff-latest-container" v-if="!editable && versionEnable && !isLastedVersion && !isPublicShow">
|
||||
<div class="diff-latest-container" v-if="!editable && versionEnable && !isLastedVersion && !isPublicShow && !hasReadonlyPermission">
|
||||
<div class="left-view-row">
|
||||
<div class="view-icon"><img src="/assets/module/figma/icon_warning_colorful.svg" alt=""></div>
|
||||
<div class="view-content">{{$t("case.current_display_history_version")}}</div>
|
||||
|
@ -222,6 +222,7 @@
|
|||
:copy-case-id="caseId"
|
||||
:label-width="formLabelWidth"
|
||||
:is-public-show="isPublicShow"
|
||||
:is-readonly-user="hasReadonlyPermission"
|
||||
:case-id="caseId"
|
||||
:type="!caseId ? 'add' : 'edit'"
|
||||
:comments.sync="comments"
|
||||
|
@ -604,6 +605,15 @@ export default {
|
|||
publicCaseId: String,
|
||||
},
|
||||
computed: {
|
||||
hasCopyPermission() {
|
||||
return hasPermission('PROJECT_TRACK_CASE:READ+COPY')
|
||||
},
|
||||
hasDeletePermission() {
|
||||
return hasPermission('PROJECT_TRACK_CASE:READ+DELETE')
|
||||
},
|
||||
hasReadonlyPermission() {
|
||||
return hasPermission('PROJECT_TRACK_CASE:READ') && !hasPermission('PROJECT_TRACK_CASE:READ+EDIT')
|
||||
},
|
||||
routeProjectId() {
|
||||
return this.$route.query.projectId;
|
||||
},
|
||||
|
@ -614,7 +624,7 @@ export default {
|
|||
return this.type === "edit" ? "preview" : "edit";
|
||||
},
|
||||
readOnly() {
|
||||
if (this.isPublicShow) {
|
||||
if (this.isPublicShow || this.hasReadonlyPermission) {
|
||||
return true;
|
||||
}
|
||||
const { rowClickHasPermission } = this.currentTestCaseInfo;
|
||||
|
@ -1595,9 +1605,15 @@ export default {
|
|||
this.saveCase();
|
||||
},
|
||||
copyRow() {
|
||||
if (!hasPermission('PROJECT_TRACK_CASE:READ+COPY')) {
|
||||
return;
|
||||
}
|
||||
openCaseEdit({caseId: this.testCase.id, type: 'copy', projectId: this.projectId}, this);
|
||||
},
|
||||
deleteRow() {
|
||||
if (!hasPermission('PROJECT_TRACK_CASE:READ+DELETE')) {
|
||||
return;
|
||||
}
|
||||
getTestCaseVersions(this.testCase.id)
|
||||
.then(response => {
|
||||
if (hasLicense() && this.versionEnable && response.data.length > 1) {
|
||||
|
|
|
@ -420,7 +420,7 @@ export default {
|
|||
{
|
||||
name: this.$t('test_track.case.batch_delete_btn'),
|
||||
handleClick: this.handleDeleteBatchToGc,
|
||||
permissions: ['PROJECT_TRACK_CASE:READ+BATCH_DELETE'],
|
||||
permissions: ['PROJECT_TRACK_CASE:READ+DELETE'],
|
||||
isDivide: true,
|
||||
isActive: true
|
||||
}
|
||||
|
@ -469,7 +469,7 @@ export default {
|
|||
isTextButton: true,
|
||||
tip: this.$t('test_track.case.batch_delete_case'),
|
||||
exec: this.handleDelete,
|
||||
permissions: ['PROJECT_TRACK_CASE:READ+DELETE']
|
||||
permissions: ['PROJECT_TRACK_CASE:READ+BATCH_DELETE']
|
||||
}
|
||||
],
|
||||
typeArr: [],
|
||||
|
|
|
@ -208,7 +208,7 @@
|
|||
:type="type"
|
||||
:isCopy="isCopy"
|
||||
:copyCaseId="copyCaseId"
|
||||
:readOnly="(readOnly && editable) || isPublicShow"
|
||||
:readOnly="(readOnly && editable) || isPublicShow || isReadonlyUser"
|
||||
:projectId="projectId"
|
||||
:isClickAttachmentTab="isClickAttachmentTab"
|
||||
:isDelete="!isTestPlan"
|
||||
|
@ -269,7 +269,8 @@ export default {
|
|||
copyCaseId: String,
|
||||
isCopy: Boolean,
|
||||
editableState: Boolean,
|
||||
isPublicShow: Boolean
|
||||
isPublicShow: Boolean,
|
||||
isReadonlyUser: Boolean
|
||||
},
|
||||
methods: {
|
||||
getUploadFiles() {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
:project-id="projectId"
|
||||
:is-copy="isCopy"
|
||||
:is-public-show="isPublicShow"
|
||||
:is-readonly-user="isReadonlyUser"
|
||||
:copy-case-id="copyCaseId"
|
||||
:isClickAttachmentTab="isClickAttachmentTab"
|
||||
:isTestPlan="isTestPlan"
|
||||
|
@ -113,7 +114,7 @@
|
|||
<el-scrollbar>
|
||||
<div class="content-container">
|
||||
<case-comment-viewer
|
||||
:is-public-show="isPublicShow"
|
||||
:is-public-show="isPublicShow || isReadonlyUser"
|
||||
@getComments="getComments"
|
||||
:comments="comments"
|
||||
ref="commentRef"
|
||||
|
@ -161,6 +162,7 @@
|
|||
:isClickAttachmentTab="isClickAttachmentTab"
|
||||
:isTestPlan="isTestPlan"
|
||||
:is-public-show="isPublicShow"
|
||||
:is-readonly-user="isReadonlyUser"
|
||||
:editable="editable"
|
||||
:editable-state="editableState"
|
||||
:form="form"
|
||||
|
@ -220,7 +222,8 @@ export default {
|
|||
"defaultOpen",
|
||||
"edit",
|
||||
"editableState",
|
||||
"isPublicShow"
|
||||
"isPublicShow",
|
||||
"isReadonlyUser"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -303,7 +303,6 @@ export default {
|
|||
{
|
||||
name: this.$t('test_track.case.public_remove'),
|
||||
handleClick: this.handleDeleteBatchToPublic,
|
||||
permissions: ['PROJECT_TRACK_CASE:READ+BATCH_DELETE'],
|
||||
isDelete: true
|
||||
}
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue