mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-25 14:25:23 +00:00
feat: 资产详情添加授权用户列表页 (#1093)
* feat: 资产详情添加授权用户列表页 * feat: 取消console log * perf: 优化一下前端 * feat: 修改授权用户组分隔符 Co-authored-by: Michael Bai <baijiangjie@gmail.com> Co-authored-by: ibuler <ibuler@qq.com>
This commit is contained in:
@@ -109,6 +109,8 @@
|
|||||||
"Assets": "资产",
|
"Assets": "资产",
|
||||||
"Auth": "认证",
|
"Auth": "认证",
|
||||||
"AccountList": "账号列表",
|
"AccountList": "账号列表",
|
||||||
|
"PermUserList": "授权用户",
|
||||||
|
"ViewPerm": "查看授权",
|
||||||
"AutoGenerateKey": "自动生成",
|
"AutoGenerateKey": "自动生成",
|
||||||
"AutoPush": "自动推送",
|
"AutoPush": "自动推送",
|
||||||
"BasePlatform": "基础平台",
|
"BasePlatform": "基础平台",
|
||||||
@@ -551,6 +553,7 @@
|
|||||||
"User": "用户",
|
"User": "用户",
|
||||||
"UserGroups": "用户组",
|
"UserGroups": "用户组",
|
||||||
"PermName":"授权名称",
|
"PermName":"授权名称",
|
||||||
|
"Permissions": "授权列表",
|
||||||
"DatabaseAppPermission": "数据库授权",
|
"DatabaseAppPermission": "数据库授权",
|
||||||
"RemoteAppPermission": "远程应用授权",
|
"RemoteAppPermission": "远程应用授权",
|
||||||
"addApplicationToThisPermission": "添加应用",
|
"addApplicationToThisPermission": "添加应用",
|
||||||
|
@@ -100,6 +100,8 @@
|
|||||||
"HardwareInfo": "Hardware info",
|
"HardwareInfo": "Hardware info",
|
||||||
"Hardware": "Hardware",
|
"Hardware": "Hardware",
|
||||||
"AccountList": "Account list",
|
"AccountList": "Account list",
|
||||||
|
"PermUserList": "Authorized user",
|
||||||
|
"ViewPerm": "View permission",
|
||||||
"LoginOption": "Login option",
|
"LoginOption": "Login option",
|
||||||
"AssetDetail": "Asset detail",
|
"AssetDetail": "Asset detail",
|
||||||
"AssetList": "Asset list",
|
"AssetList": "Asset list",
|
||||||
@@ -531,6 +533,7 @@
|
|||||||
"perms": {
|
"perms": {
|
||||||
"": "",
|
"": "",
|
||||||
"Actions": "Permission",
|
"Actions": "Permission",
|
||||||
|
"Permission": "Permissions",
|
||||||
"Asset": "Asset",
|
"Asset": "Asset",
|
||||||
"Basic": "Basic",
|
"Basic": "Basic",
|
||||||
"Exclude": "Exclude",
|
"Exclude": "Exclude",
|
||||||
@@ -541,6 +544,7 @@
|
|||||||
"SystemUser": "System user",
|
"SystemUser": "System user",
|
||||||
"User": "User",
|
"User": "User",
|
||||||
"UserGroups": "UserGroups",
|
"UserGroups": "UserGroups",
|
||||||
|
"Permissions": "Permissions",
|
||||||
"DatabaseAppPermission": "Databases permissions",
|
"DatabaseAppPermission": "Databases permissions",
|
||||||
"RemoteAppPermission": "Remote apps permissions",
|
"RemoteAppPermission": "Remote apps permissions",
|
||||||
"KubernetesAppPermission": "Kubernetes permissions",
|
"KubernetesAppPermission": "Kubernetes permissions",
|
||||||
|
60
src/layout/components/GenericListTableDialog/index.vue
Normal file
60
src/layout/components/GenericListTableDialog/index.vue
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog
|
||||||
|
:title="title"
|
||||||
|
:visible.sync="iVisible"
|
||||||
|
top="1vh"
|
||||||
|
:width="width"
|
||||||
|
:show-cancel="false"
|
||||||
|
:show-confirm="false"
|
||||||
|
>
|
||||||
|
<GenericListTable :table-config="tableConfig" :header-actions="headerActions" />
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Dialog from '@/components/Dialog'
|
||||||
|
import { GenericListTable } from '@/layout/components'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Index',
|
||||||
|
components: {
|
||||||
|
Dialog, GenericListTable
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
tableConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '60%'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iVisible: {
|
||||||
|
set(val) {
|
||||||
|
this.$emit('update:visible', val)
|
||||||
|
},
|
||||||
|
get() {
|
||||||
|
return this.visible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@@ -11,3 +11,4 @@ export { default as GenericListTable } from './GenericListTable'
|
|||||||
export { default as GenericCreateUpdatePage } from './GenericCreateUpdatePage'
|
export { default as GenericCreateUpdatePage } from './GenericCreateUpdatePage'
|
||||||
export { default as GenericCreateUpdateForm } from './GenericCreateUpdateForm'
|
export { default as GenericCreateUpdateForm } from './GenericCreateUpdateForm'
|
||||||
export { default as GenericUpdateFormDialog } from './GenericUpdateFormDialog'
|
export { default as GenericUpdateFormDialog } from './GenericUpdateFormDialog'
|
||||||
|
export { default as GenericListTableDialog } from './GenericListTableDialog'
|
||||||
|
225
src/views/assets/Asset/AssetDetail/PermUser.vue
Normal file
225
src/views/assets/Asset/AssetDetail/PermUser.vue
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="16">
|
||||||
|
<ListTable ref="ListTable" :table-config="tableConfig" :header-actions="headerActions" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<PermUserGroupCard v-bind="UserGroupCardConfig" />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<GenericListTableDialog
|
||||||
|
:visible.sync="GenericListTableDialogConfig.visible"
|
||||||
|
v-bind="GenericListTableDialogConfig"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ListTable from '@/components/ListTable'
|
||||||
|
import { GenericListTableDialog } from '@/layout/components'
|
||||||
|
import { ChoicesFormatter, DetailFormatter } from '@/components/TableFormatters'
|
||||||
|
import PermUserGroupCard from './components/PermUserGroupCard'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PermUserList',
|
||||||
|
components: {
|
||||||
|
ListTable, GenericListTableDialog, PermUserGroupCard
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
object: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
const vm = this
|
||||||
|
return {
|
||||||
|
tableConfig: {
|
||||||
|
url: `/api/v1/assets/assets/${this.object.id}/perm-users/`,
|
||||||
|
columns: [
|
||||||
|
'name', 'username', 'email', 'phone', 'wechat',
|
||||||
|
'groups_display', 'total_role_display', 'source',
|
||||||
|
'is_valid', 'login_blocked', 'mfa_enabled',
|
||||||
|
'mfa_force_enabled', 'is_expired',
|
||||||
|
'last_login', 'date_joined', 'date_password_last_updated',
|
||||||
|
'comment', 'created_by', 'actions'
|
||||||
|
],
|
||||||
|
columnsShow: {
|
||||||
|
min: ['name', 'username', 'actions'],
|
||||||
|
default: [
|
||||||
|
'name', 'username',
|
||||||
|
'source', 'is_valid', 'actions'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
columnsMeta: {
|
||||||
|
name: {
|
||||||
|
formatterArgs: {
|
||||||
|
route: 'UserDetail'
|
||||||
|
},
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
width: '120px'
|
||||||
|
},
|
||||||
|
total_role_display: {
|
||||||
|
label: this.$t('users.Role'),
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
|
mfa_enabled: {
|
||||||
|
label: 'MFA',
|
||||||
|
formatterArgs: {
|
||||||
|
showFalse: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mfa_force_enabled: {
|
||||||
|
formatterArgs: {
|
||||||
|
showFalse: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
is_expired: {
|
||||||
|
formatterArgs: {
|
||||||
|
showFalse: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
groups_display: {
|
||||||
|
width: '200px',
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
formatterArgs: {
|
||||||
|
hasUpdate: false,
|
||||||
|
hasDelete: false,
|
||||||
|
hasClone: false,
|
||||||
|
extraActions: [
|
||||||
|
{
|
||||||
|
title: vm.$t('assets.ViewPerm'),
|
||||||
|
name: 'view',
|
||||||
|
type: 'primary',
|
||||||
|
callback: function(data) {
|
||||||
|
vm.GenericListTableDialogConfig.visible = true
|
||||||
|
vm.GenericListTableDialogConfig.tableConfig.url = `/api/v1/assets/assets/${vm.object.id}/perm-users/${data.row.id}/permissions/`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
hasImport: false,
|
||||||
|
hasExport: false,
|
||||||
|
hasLeftActions: false
|
||||||
|
},
|
||||||
|
UserGroupCardConfig: {
|
||||||
|
icon: 'fa-users',
|
||||||
|
title: this.$t('perms.UserGroups'),
|
||||||
|
url: `/api/v1/assets/assets/${vm.object.id}/perm-user-groups/`,
|
||||||
|
detailRoute: 'UserGroupDetail',
|
||||||
|
buttonTitle: this.$t('assets.ViewPerm'),
|
||||||
|
buttonClickCallback(obj) {
|
||||||
|
vm.GenericListTableDialogConfig.visible = true
|
||||||
|
vm.GenericListTableDialogConfig.tableConfig.url = `/api/v1/assets/assets/${vm.object.id}/perm-user-groups/${obj.id}/permissions/`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
GenericListTableDialogConfig: {
|
||||||
|
title: this.$t('perms.Permissions'),
|
||||||
|
visible: false,
|
||||||
|
width: '60%',
|
||||||
|
tableConfig: {
|
||||||
|
url: '',
|
||||||
|
columns: [
|
||||||
|
'name',
|
||||||
|
'users_amount', 'user_groups_amount', 'assets_amount', 'nodes_amount',
|
||||||
|
'is_valid', 'is_active', 'date_expired', 'comment', 'org_name', 'created_by', 'date_created'
|
||||||
|
],
|
||||||
|
columnsShow: {
|
||||||
|
min: ['name'],
|
||||||
|
default: [
|
||||||
|
'name', 'is_valid', 'created_by', 'date_created'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
columnsMeta: {
|
||||||
|
name: {
|
||||||
|
formatterArgs: {
|
||||||
|
route: 'AssetPermissionDetail'
|
||||||
|
},
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
|
users_amount: {
|
||||||
|
label: this.$t('perms.User'),
|
||||||
|
width: '60px',
|
||||||
|
formatter: DetailFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
route: 'AssetPermissionDetail',
|
||||||
|
routeQuery: {
|
||||||
|
activeTab: 'AssetPermissionUser'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
from_ticket: {
|
||||||
|
width: 100,
|
||||||
|
formatter: ChoicesFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
showFalse: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created_by: {
|
||||||
|
showOverflowTooltip: true
|
||||||
|
},
|
||||||
|
user_groups_amount: {
|
||||||
|
label: this.$t('perms.UserGroups'),
|
||||||
|
width: '100px',
|
||||||
|
formatter: DetailFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
route: 'AssetPermissionDetail',
|
||||||
|
routeQuery: {
|
||||||
|
activeTab: 'AssetPermissionUser'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
assets_amount: {
|
||||||
|
label: this.$t('perms.Asset'),
|
||||||
|
width: '60px',
|
||||||
|
formatter: DetailFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
route: 'AssetPermissionDetail',
|
||||||
|
routeQuery: {
|
||||||
|
activeTab: 'AssetPermissionAsset'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes_amount: {
|
||||||
|
label: this.$t('perms.Node'),
|
||||||
|
width: '60px',
|
||||||
|
formatter: DetailFormatter,
|
||||||
|
formatterArgs: {
|
||||||
|
route: 'AssetPermissionDetail',
|
||||||
|
routeQuery: {
|
||||||
|
activeTab: 'AssetPermissionAsset'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
hasImport: false,
|
||||||
|
hasExport: false,
|
||||||
|
hasLeftActions: false,
|
||||||
|
hasColumnSetting: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@@ -0,0 +1,110 @@
|
|||||||
|
<template>
|
||||||
|
<IBox :fa="icon" :type="type" :title="title" v-bind="$attrs">
|
||||||
|
<table style="width: 100%;table-layout:fixed;" class="CardTable">
|
||||||
|
<tr v-for="obj of iObjects" :key="obj.value" class="item">
|
||||||
|
<td style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
|
||||||
|
<el-tooltip style="margin: 4px;" effect="dark" :content="obj.label" placement="left">
|
||||||
|
<el-link class="detail" @click="goDetail(obj)">{{ obj.label }}</el-link>
|
||||||
|
</el-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<el-button size="mini" type="primary" style="float: right" @click="buttonClickCallback(obj)">
|
||||||
|
{{ buttonTitle }}
|
||||||
|
</el-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</IBox>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import IBox from '@/components/IBox'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PermUserGroupCard',
|
||||||
|
components: {
|
||||||
|
IBox
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'primary'
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
detailRoute: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
buttonTitle: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
buttonClickCallback: {
|
||||||
|
type: Function,
|
||||||
|
default: (obj) => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
objects: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iObjects() {
|
||||||
|
return this.objects
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadObjects()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadObjects() {
|
||||||
|
const data = await this.$axios.get(this.url)
|
||||||
|
data.forEach((v) => {
|
||||||
|
v['label'] = v['name']
|
||||||
|
})
|
||||||
|
this.objects = data
|
||||||
|
},
|
||||||
|
goDetail(obj) {
|
||||||
|
this.$router.push({ name: this.detailRoute, params: { id: obj.id }})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
b, strong {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr td {
|
||||||
|
line-height: 1.42857;
|
||||||
|
padding: 8px;
|
||||||
|
vertical-align: top;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.item {
|
||||||
|
border-bottom: 1px solid #e7eaec;
|
||||||
|
padding: 8px;
|
||||||
|
display: block;
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.box-margin {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -11,6 +11,7 @@ import { GenericDetailPage, TabPage } from '@/layout/components'
|
|||||||
import Detail from './Detail.vue'
|
import Detail from './Detail.vue'
|
||||||
import Account from './Account.vue'
|
import Account from './Account.vue'
|
||||||
import SystemUserList from './SystemUser.vue'
|
import SystemUserList from './SystemUser.vue'
|
||||||
|
import PermUserList from './PermUser.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetListDetail',
|
name: 'AssetListDetail',
|
||||||
@@ -19,7 +20,8 @@ export default {
|
|||||||
TabPage,
|
TabPage,
|
||||||
Detail,
|
Detail,
|
||||||
Account,
|
Account,
|
||||||
SystemUserList
|
SystemUserList,
|
||||||
|
PermUserList
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -38,6 +40,10 @@ export default {
|
|||||||
{
|
{
|
||||||
title: this.$t('assets.AccountList'),
|
title: this.$t('assets.AccountList'),
|
||||||
name: 'Account'
|
name: 'Account'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('assets.PermUserList'),
|
||||||
|
name: 'PermUserList'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
hasRightSide: true,
|
hasRightSide: true,
|
||||||
|
Reference in New Issue
Block a user