feat(系统设置): 新增个人信息权限 (#10436)

--user=郭雨琦 【ID1005644】权限管理增加个人信息的权限管控

Co-authored-by: guoyuqi <xiaomeinvG@126.com>
Co-authored-by: 刘瑞斌 <bin@fit2cloud.com>
This commit is contained in:
metersphere-bot 2022-02-11 17:09:59 +08:00 committed by GitHub
parent 4ed013d455
commit cf053b4905
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 158 additions and 58 deletions

View File

@ -262,7 +262,7 @@ public class GroupService {
private List<GroupResourceDTO> getResourcePermission(List<GroupResource> resource, List<GroupPermission> permissions, String type, List<String> permissionList) {
List<GroupResourceDTO> dto = new ArrayList<>();
List<GroupResource> resources = resource.stream().filter(g -> g.getId().startsWith(type)).collect(Collectors.toList());
List<GroupResource> resources = resource.stream().filter(g -> g.getId().startsWith(type)||g.getId().startsWith("PERSONAL")).collect(Collectors.toList());
permissions.forEach(p -> {
if (permissionList.contains(p.getId())) {
p.setChecked(true);

View File

@ -8,4 +8,46 @@ CREATE TABLE `operating_log_resource`
PRIMARY KEY (`id`),
KEY `operating_log_id_index` (`operating_log_id`),
KEY `source_id_index` (`source_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE utf8mb4_general_ci;
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE utf8mb4_general_ci;
-- permission
DROP PROCEDURE IF EXISTS test_personal;
DELIMITER //
CREATE PROCEDURE test_personal()
BEGIN
#声明结束标识
DECLARE end_flag int DEFAULT 0;
DECLARE groupId varchar(64);
#声明游标 group_curosr
DECLARE group_curosr CURSOR FOR SELECT DISTINCT group_id FROM user_group;
#设置终止标志
DECLARE CONTINUE HANDLER FOR NOT FOUND SET end_flag=1;
#打开游标
OPEN group_curosr;
#遍历游标
REPEAT
#获取当前游标指针记录,取出值赋给自定义的变量
FETCH group_curosr INTO groupId;
#利用取到的值进行数据库的操作
INSERT INTO user_group_permission (id, group_id, permission_id, module_id)
VALUES (uuid(), groupId, 'PERSONAL_INFORMATION:READ+EDIT', 'PERSONAL_INFORMATION'),
(uuid(), groupId, 'PERSONAL_INFORMATION:READ+THIRD_ACCOUNT', 'PERSONAL_INFORMATION'),
(uuid(), groupId, 'PERSONAL_INFORMATION:READ+API_KEYS', 'PERSONAL_INFORMATION'),
(uuid(), groupId, 'PERSONAL_INFORMATION:READ+EDIT_PASSWORD', 'PERSONAL_INFORMATION');
# 根据 end_flag 判断是否结束
UNTIL end_flag END REPEAT;
#关闭游标
close group_curosr;
END
//
DELIMITER ;
CALL test_personal();
DROP PROCEDURE IF EXISTS test_personal;

View File

@ -943,6 +943,30 @@
"name": "permission.project_error_report_library.delete",
"resourceId": "PROJECT_ERROR_REPORT_LIBRARY",
"license": true
},
{
"id": "PERSONAL_INFORMATION:READ+EDIT",
"name": "permission.personal_information.personal_setting",
"resourceId": "PERSONAL_INFORMATION",
"license": true
},
{
"id": "PERSONAL_INFORMATION:READ+API_KEYS",
"name": "permission.personal_information.api_keys",
"resourceId": "PERSONAL_INFORMATION",
"license": true
},
{
"id": "PERSONAL_INFORMATION:READ+EDIT_PASSWORD",
"name": "permission.personal_information.edit_password",
"resourceId": "PERSONAL_INFORMATION",
"license": true
},
{
"id": "PERSONAL_INFORMATION:READ+THIRD_ACCOUNT",
"name": "permission.personal_information.third_account",
"resourceId": "PERSONAL_INFORMATION",
"license": true
}
],
"resource": [
@ -1101,5 +1125,10 @@
"id": "SYSTEM_PLUGIN",
"name": "permission.system_plugin.name"
},
{
"id": "PERSONAL_INFORMATION",
"name": "permission.personal_information.name",
"license": true
}
]
}

View File

@ -1,23 +1,25 @@
<template>
<div>
<el-tabs v-model="activeIndex" >
<el-tab-pane v-for="menu in persons" :key = "menu.title" :name="menu.title" :label="$t(menu.title)" class="setting-item"></el-tab-pane>
<el-tab-pane name="change_password" :label="$t('member.edit_password')" class="setting-item"></el-tab-pane>
<el-tab-pane name="third_account" :label="$t('commons.third_account')" class="setting-item"></el-tab-pane>
<el-tab-pane name="commons.personal_setting" :label="$t('commons.personal_setting')" class="setting-item"></el-tab-pane>
<el-tab-pane name="commons.api_keys" :label="$t('commons.api_keys')" class="setting-item" ></el-tab-pane>
<el-tab-pane name="change_password" :label="$t('member.edit_password')" class="setting-item" ></el-tab-pane>
<el-tab-pane name="third_account" :label="$t('commons.third_account')" class="setting-item" ></el-tab-pane>
</el-tabs>
<ms-main-container>
<ms-person-from-setting v-if="activeIndex==='commons.personal_setting'" :form = form @getPlatformInfo = "getPlatformInfo" @cancel = "cancel" />
<ms-api-keys v-if="activeIndex==='commons.api_keys'"/>
<password-info v-if="activeIndex==='change_password'" :rule-form = "ruleForm" @cancel="cancel"></password-info>
<el-form v-if="activeIndex==='third_account'">
<jira-user-info @auth="handleAuth" v-if="hasJira" :data="currentPlatformInfo"/>
<tapd-user-info @auth="handleAuth" v-if="hasTapd" :data="currentPlatformInfo"/>
<zentao-user-info @auth="handleAuth" v-if="hasZentao" :data="currentPlatformInfo"/>
<azure-devops-user-info @auth="handleAuth" v-if="hasAzure" :data="currentPlatformInfo"/>
<el-form-item>
<ms-person-from-setting v-if="activeIndex==='commons.personal_setting'" :form = form @getPlatformInfo = "getPlatformInfo" @cancel = "cancel" />
<ms-api-keys v-if="activeIndex==='commons.api_keys'" />
<password-info v-if="activeIndex==='change_password'" :rule-form = "ruleForm" @cancel="cancel" ></password-info>
<el-form v-if="activeIndex==='third_account'" >
<jira-user-info @auth="handleAuth" v-if="hasJira" :data="currentPlatformInfo" v-permission="['PERSONAL_INFORMATION:READ+THIRD_ACCOUNT']"/>
<tapd-user-info @auth="handleAuth" v-if="hasTapd" :data="currentPlatformInfo" v-permission="['PERSONAL_INFORMATION:READ+THIRD_ACCOUNT']"/>
<zentao-user-info @auth="handleAuth" v-if="hasZentao" :data="currentPlatformInfo" v-permission="['PERSONAL_INFORMATION:READ+THIRD_ACCOUNT']"/>
<azure-devops-user-info @auth="handleAuth" v-if="hasAzure" :data="currentPlatformInfo" v-permission="['PERSONAL_INFORMATION:READ+THIRD_ACCOUNT']"/>
<el-form-item v-permission="['PERSONAL_INFORMATION:READ+THIRD_ACCOUNT']" v-if="hasJira||hasTapd||hasZentao||hasAzure">
<el-button @click="cancel">{{$t('commons.cancel')}}</el-button>
<el-button type="primary" @click="updateUser('updateUserForm')" @keydown.enter.native.prevent>{{$t('commons.confirm')}}</el-button>
</el-form-item>
<div v-if="!isShowText||(!hasJira&&!hasTapd&&!hasZentao&&!hasAzure)" style="width: 6%;margin: auto">{{$t('commons.no_permission')}}</div>
</el-form>
</ms-main-container>
@ -31,13 +33,13 @@
import MsApiKeys from "@/business/components/settings/personal/ApiKeys";
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import PasswordInfo from "@/business/components/settings/personal/PasswordInfo";
import {getCurrentUser, getCurrentWorkspaceId} from "@/common/js/utils";
import {getCurrentUser, getCurrentWorkspaceId, hasPermission} from "@/common/js/utils";
import ZentaoUserInfo from "@/business/components/settings/personal/ZentaoUserInfo";
import TapdUserInfo from "@/business/components/settings/personal/TapdUserInfo";
import JiraUserInfo from "@/business/components/settings/personal/JiraUserInfo";
import AzureDevopsUserInfo from "@/business/components/settings/personal/AzureDevopsUserInfo";
import {getIntegrationService} from "@/network/organization";
import {TokenKey} from "@/common/js/constants";
import {AZURE_DEVOPS, JIRA, TAPD, TokenKey, ZEN_TAO} from "@/common/js/constants";
export default {
name: "MsPersonRouter",
@ -61,9 +63,10 @@
return menus;
};
return{
persons: getMenus('person'),
//persons: getMenus('person'),
activeIndex: 'commons.personal_setting',
ruleForm:{},
isShowText:false,
hasJira: false,
hasTapd: false,
hasZentao: false,
@ -187,7 +190,10 @@
},
},
created() {
this.isShowText = hasPermission('PERSONAL_INFORMATION:READ+THIRD_ACCOUNT');
this.initTableData();
}
}

View File

@ -1,6 +1,6 @@
<template>
<div v-loading="result.loading">
<el-card class="table-card">
<el-card class="table-card" v-permission="['PERSONAL_INFORMATION:READ+API_KEYS']">
<template v-slot:header>
<div>
<el-row class="table-title" type="flex" justify="space-between" align="middle">
@ -66,21 +66,14 @@
</el-table-column>
</el-table>
</el-card>
<!-- <el-dialog title="Secret Key" :visible.sync="apiKeysVisible">
<div class="variable">
{{ currentRow.secretKey }}
<el-tooltip :content="$t('api_test.copied')" manual v-model="currentRow.visible2" placement="top"
:visible-arrow="false">
<i class="el-icon-copy-document copy" @click="copy(currentRow, 'secretKey', 'visible2')"/>
</el-tooltip>
</div>
</el-dialog>-->
<div v-if="!isShowText" style="width: 6%;margin: auto">{{$t('commons.no_permission')}}</div>
</div>
</template>
<script>
import MsDialogFooter from "../../common/components/MsDialogFooter";
import {getCurrentUser} from "../../../../common/js/utils";
import {getCurrentUser, hasPermission} from "../../../../common/js/utils";
import MsTableOperatorButton from "../../common/components/MsTableOperatorButton";
import MsTableHeader from "../../common/components/MsTableHeader";
@ -90,6 +83,7 @@ export default {
data() {
return {
result: {},
isShowText:false,
updateVisible: false,
editPasswordVisible: false,
apiKeysVisible: false,
@ -100,6 +94,7 @@ export default {
},
created() {
this.isShowText = hasPermission('PERSONAL_INFORMATION:READ+API_KEYS');
this.search();
},

View File

@ -1,28 +1,33 @@
<template>
<el-form :model="ruleForm" :rules="rules" ref="editPasswordForm" label-width="120px" class="demo-ruleForm">
<el-form-item :label="$t('member.old_password')" prop="password" style="margin-bottom: 29px">
<el-input v-model="ruleForm.password" autocomplete="off" show-password/>
</el-form-item>
<el-form-item :label="$t('member.new_password')" prop="newpassword">
<el-input v-model="ruleForm.newpassword" autocomplete="off" show-password/>
</el-form-item>
<el-form-item :label="$t('member.repeat_password')" prop="repeatPassword">
<el-input v-model="ruleForm.repeatPassword" autocomplete="off" show-password/>
</el-form-item>
<el-form-item>
<el-button @click="cancel">{{$t('commons.cancel')}}</el-button>
<el-button type="primary" @click="updatePassword('editPasswordForm')" @keydown.enter.native.prevent>{{$t('commons.confirm')}}</el-button>
</el-form-item>
</el-form>
<div>
<el-form :model="ruleForm" :rules="rules" ref="editPasswordForm" label-width="120px" class="demo-ruleForm" v-permission="['PERSONAL_INFORMATION:READ+EDIT_PASSWORD']">
<el-form-item :label="$t('member.old_password')" prop="password" style="margin-bottom: 29px">
<el-input v-model="ruleForm.password" autocomplete="off" show-password/>
</el-form-item>
<el-form-item :label="$t('member.new_password')" prop="newpassword">
<el-input v-model="ruleForm.newpassword" autocomplete="off" show-password/>
</el-form-item>
<el-form-item :label="$t('member.repeat_password')" prop="repeatPassword">
<el-input v-model="ruleForm.repeatPassword" autocomplete="off" show-password/>
</el-form-item>
<el-form-item>
<el-button @click="cancel">{{$t('commons.cancel')}}</el-button>
<el-button type="primary" @click="updatePassword('editPasswordForm')" @keydown.enter.native.prevent>{{$t('commons.confirm')}}</el-button>
</el-form-item>
</el-form>
<div v-if="!isShowText" style="width: 6%;margin: auto">{{$t('commons.no_permission')}}</div>
</div>
</template>
<script>
import {logout} from "@/network/user";
import {hasPermission} from "@/common/js/utils";
export default {
name:'PasswordInfo',
data(){
return{
result:{},
isShowText:false,
updatePasswordPath: '/user/update/password',
rules: {
password: [
@ -79,6 +84,9 @@ export default {
}
});
},
},
created() {
this.isShowText = hasPermission('PERSONAL_INFORMATION:READ+EDIT_PASSWORD');
}
}

View File

@ -1,7 +1,7 @@
<template>
<div v-loading="result.loading">
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
ref="updateUserForm">
ref="updateUserForm" v-permission="['PERSONAL_INFORMATION:READ+EDIT']">
<el-form-item label="ID" prop="id">
<el-input v-model="form.id" autocomplete="off" :disabled="true"/>
</el-form-item>
@ -14,21 +14,12 @@
<el-form-item :label="$t('commons.phone')" prop="phone">
<el-input v-model="form.phone" autocomplete="off"/>
</el-form-item>
<!-- <el-form-item label="所属工作空间" v-if="workspaceList.length>0">
<span v-for="(item,index) in workspaceList" :key = item.id >
<span>{{item.name}}</span><span v-if="index<workspaceList.length-1"> | </span>
</span>
</el-form-item>
<el-form-item label="所属工作项目" v-if ="projectList.length>0">
<span v-for="(item,index) in projectList" :key = item.id >
<span>{{item.name}}</span><span v-if="index<projectList.length-1"> | </span>
</span>
</el-form-item>-->
<el-form-item>
<el-button @click="cancel">{{$t('commons.cancel')}}</el-button>
<el-button type="primary" @click="updateUser('updateUserForm')" @keydown.enter.native.prevent>{{$t('commons.confirm')}}</el-button>
</el-form-item>
</el-form>
<div v-if="!isShowText" style="width: 6%;margin: auto">{{$t('commons.no_permission')}}</div>
</div>
</template>
@ -38,7 +29,7 @@ import MsDialogFooter from "../../common/components/MsDialogFooter";
import {
fullScreenLoading, getCurrentProjectID,
getCurrentUser,
getCurrentWorkspaceId,
getCurrentWorkspaceId, hasPermission,
listenGoBack,
removeGoBackListener, saveLocalStorage, stopFullScreenLoading
} from "@/common/js/utils";
@ -67,6 +58,7 @@ export default {
return {
result: {},
isLocalUser: false,
isShowText:false,
updatePath: '/user/update/current',
ruleForm: {},
rule: {
@ -101,7 +93,7 @@ export default {
},
created() {
this.isShowText = hasPermission('PERSONAL_INFORMATION:READ+EDIT');
},
methods: {
currentUser: () => {

View File

@ -128,7 +128,8 @@ export function API_SCENARIO_FILTERS () {
export const USER_GROUP_SCOPE = {
'SYSTEM': 'group.system',
'WORKSPACE': 'group.workspace',
'PROJECT': 'group.project'
'PROJECT': 'group.project',
'PERSONAL': 'group.personal'
}
export const PROJECT_GROUP_SCOPE = {

View File

@ -1,6 +1,7 @@
export default {
commons: {
project_permission: 'Please add the project permission first',
no_permission:'No permission yet',
failure_continues: "Failure continues",
full_screen_editing: "Full screen editing",
trash: "Trash",
@ -861,6 +862,7 @@ export default {
select_type: 'please select type',
view_permission: 'view permission',
system: 'System',
personal: 'Personal Information',
organization: 'Organization',
workspace: 'Workspace',
project: 'Project',
@ -3002,6 +3004,13 @@ export default {
delete: "DELETE",
read: "READ",
},
personal_information:{
name:'Setting',
personal_setting: 'Personal Setting',
api_keys: 'API Keys',
edit_password: "EDIT PASSWORD",
third_account: 'Third Account',
},
other: {
track: "Track",
api: "API",

View File

@ -1,6 +1,7 @@
export default {
commons: {
project_permission: '请先添加该项目权限',
no_permission:'暂无权限',
failure_continues: "失败继续",
full_screen_editing: "全屏编辑",
trash: "回收站",
@ -865,6 +866,7 @@ export default {
admin_not_allow_delete: '系统用户组不支持删除!',
select_type: '请选择所属类型',
system: '系统',
personal: '个人信息',
organization: '组织',
workspace: '工作空间',
project: '项目',
@ -3006,12 +3008,19 @@ export default {
delete: "删除",
read: "查看脚本",
},
personal_information:{
name:'设置',
personal_setting: '个人设置',
api_keys: 'API Keys',
edit_password: "修改密码",
third_account: '第三方平台账号',
},
other: {
track: "测试跟踪",
api: "接口测试",
performance: "性能测试",
project: "项目设置",
report: "报表统计"
report: "报表统计",
}
},
env_options: {

View File

@ -1,6 +1,7 @@
export default {
commons: {
project_permission: '請先添加該項目權限',
no_permission:'暫無權限',
failure_continues: "失敗繼續",
full_screen_editing: "全屏編輯",
trash: "回收站",
@ -865,6 +866,7 @@ export default {
admin_not_allow_delete: '系統用戶組不支持刪除!',
select_type: '請選擇所屬類型',
system: '系統',
personal: '個人信息',
organization: '組織',
workspace: '工作空間',
project: '項目',
@ -3005,6 +3007,13 @@ export default {
delete: "刪除",
read: "查看腳本",
},
personal_information:{
name:'設置',
personal_setting: '個人設置',
api_keys: 'API Keys',
edit_password: "修改密碼",
third_account: '第三方平臺賬號',
},
other: {
track: "測試跟蹤",
api: "接口測試",