mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-25 14:34:46 +00:00
feat: 用户组绑定所有用户
This commit is contained in:
@@ -374,6 +374,7 @@
|
||||
"PushSystemUserNow": "Push system user now",
|
||||
"PushAllSystemUsersToAsset": "Push all system users to asset",
|
||||
"QuickUpdate": "Quick update",
|
||||
"QuickAdd": "Quick add",
|
||||
"Connectivity": "Reachable",
|
||||
"Unreachable": "Unreachable",
|
||||
"Unknown": "Unknown",
|
||||
@@ -1761,6 +1762,7 @@
|
||||
"UpdateNodeAssetHardwareInfo": "Update node asset hardware information"
|
||||
},
|
||||
"users": {
|
||||
"AllMembers": "All members",
|
||||
"UnbindHelpText": "The user is not a local user and cannot be unbound. Contact the administrator",
|
||||
"SetStatus": "Set status",
|
||||
"Set": "Set",
|
||||
|
||||
@@ -368,6 +368,7 @@
|
||||
"PushSystemUserNow": "プッシュシステムユーザー",
|
||||
"PushAllSystemUsersToAsset": "すべてのシステムユーザーをアセットにプッシュ",
|
||||
"QuickUpdate": "クイックアップデート",
|
||||
"QuickAdd": "クイック追加",
|
||||
"Connectivity": "接続可能",
|
||||
"Unreachable": "接続できません",
|
||||
"Unknown": "不明",
|
||||
@@ -1753,6 +1754,7 @@
|
||||
"UpdateNodeAssetHardwareInfo": "ノード資産ハードウェア情報の更新"
|
||||
},
|
||||
"users": {
|
||||
"AllMembers": "すべてのメンバー",
|
||||
"UnbindHelpText": "このユーザーはローカルユーザーではありませんので、解除できません。管理者に連絡してください。",
|
||||
"SetStatus": "ステータスの設定",
|
||||
"Set": "設定",
|
||||
|
||||
@@ -386,6 +386,7 @@
|
||||
"PushSystemUserNow": "推送系统用户",
|
||||
"PushAllSystemUsersToAsset": "推送所有系统用户到资产",
|
||||
"QuickUpdate": "快速更新",
|
||||
"QuickAdd": "快速添加",
|
||||
"Connectivity": "可连接",
|
||||
"Unreachable": "不可连接",
|
||||
"Unknown": "未知",
|
||||
@@ -1752,6 +1753,7 @@
|
||||
"UpdateNodeAssetHardwareInfo": "更新节点资产硬件信息"
|
||||
},
|
||||
"users": {
|
||||
"AllMembers": "全部成员",
|
||||
"UnbindHelpText": "此用户非本地用户,无法进行解绑,请联系管理员",
|
||||
"SetStatus": "设置状态",
|
||||
"Set": "已设置",
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :md="24" :sm="24">
|
||||
<el-alert type="success">
|
||||
{{ $t('accounts.AccountTemplateUpdateSecretHelpText') }}
|
||||
</el-alert>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :md="14" :sm="24">
|
||||
<GenericListTable ref="listTable" :table-config="tableConfig" :header-actions="headerActions" />
|
||||
</el-col>
|
||||
<el-col :md="10" :sm="24">
|
||||
<QuickActions :actions="quickActions" type="primary" />
|
||||
</el-col>
|
||||
<ViewSecret
|
||||
v-if="showViewSecretDialog"
|
||||
:account="account"
|
||||
:url="secretUrl"
|
||||
:visible.sync="showViewSecretDialog"
|
||||
/>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable'
|
||||
import QuickActions from '@/components/QuickActions'
|
||||
import { ActionsFormatter, DetailFormatter } from '@/components/TableFormatters'
|
||||
import ViewSecret from '@/components/AccountListTable/ViewSecret'
|
||||
|
||||
export default {
|
||||
name: 'GroupAddUser',
|
||||
components: {
|
||||
ViewSecret,
|
||||
QuickActions,
|
||||
GenericListTable
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
visible: false,
|
||||
secretUrl: '',
|
||||
showViewSecretDialog: false,
|
||||
quickActions: [
|
||||
{
|
||||
title: this.$t('accounts.UpdateSecret'),
|
||||
attrs: {
|
||||
type: 'primary',
|
||||
label: this.$t('common.Update')
|
||||
},
|
||||
callbacks: Object.freeze({
|
||||
click: () => {
|
||||
vm.visible = true
|
||||
}
|
||||
})
|
||||
}
|
||||
],
|
||||
tableConfig: {
|
||||
url: `/api/v1/accounts/accounts/?source_id=${this.object.id}`,
|
||||
columns: [
|
||||
'name', 'asset', 'secret_type', 'is_active', 'date_created'
|
||||
],
|
||||
columnsMeta: {
|
||||
name: {
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
route: 'AssetAccountDetail',
|
||||
can: vm.$hasPerm('accounts.view_account')
|
||||
}
|
||||
},
|
||||
asset: {
|
||||
label: this.$t('assets.Asset'),
|
||||
formatter: function(row) {
|
||||
const to = {
|
||||
name: 'AssetDetail',
|
||||
params: { id: row.asset.id }
|
||||
}
|
||||
if (vm.$hasPerm('assets.view_asset')) {
|
||||
return <router-link to={to}>{row.asset.name}</router-link>
|
||||
} else {
|
||||
return <span>{row.asset.name}</span>
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
formatter: ActionsFormatter,
|
||||
formatterArgs: {
|
||||
hasUpdate: false,
|
||||
hasDelete: false,
|
||||
hasClone: false,
|
||||
moreActionsTitle: this.$t('common.More'),
|
||||
extraActions: [
|
||||
{
|
||||
name: 'View',
|
||||
title: this.$t('common.View'),
|
||||
can: this.$hasPerm('accounts.view_accountsecret'),
|
||||
type: 'primary',
|
||||
callback: ({ row }) => {
|
||||
vm.secretUrl = `/api/v1/accounts/account-secrets/${row.id}/`
|
||||
vm.account = row
|
||||
vm.showViewSecretDialog = false
|
||||
setTimeout(() => {
|
||||
vm.showViewSecretDialog = true
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
tableAttrs: {
|
||||
border: false
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasSearch: true,
|
||||
hasRefresh: true,
|
||||
hasLeftActions: false,
|
||||
hasRightActions: true,
|
||||
hasExport: false,
|
||||
hasImport: false,
|
||||
hasCreate: false,
|
||||
searchConfig: {
|
||||
getUrlQuery: false
|
||||
},
|
||||
hasMoreActions: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cell a {
|
||||
color: var(--color-info);
|
||||
}
|
||||
</style>
|
||||
@@ -3,21 +3,16 @@
|
||||
<el-col :md="14" :sm="24">
|
||||
<AutoDetailCard :url="url" :object="object" :excludes="excludes" />
|
||||
</el-col>
|
||||
<el-col :md="10" :sm="24">
|
||||
<RelationCard v-bind="relationConfig" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AutoDetailCard from '@/components/DetailCard/auto'
|
||||
import RelationCard from '@/components/RelationCard'
|
||||
|
||||
export default {
|
||||
name: 'GroupInfo',
|
||||
components: {
|
||||
AutoDetailCard,
|
||||
RelationCard
|
||||
AutoDetailCard
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
@@ -27,34 +22,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
relationConfig: {
|
||||
icon: 'fa-user',
|
||||
title: this.$t('common.Members'),
|
||||
objectsAjax: {
|
||||
url: '/api/v1/users/users/?fields_size=mini&order=name',
|
||||
transformOption: (item) => {
|
||||
return { label: item.name + '(' + item.username + ')', value: item.id }
|
||||
}
|
||||
},
|
||||
hasObjectsId: this.object.users,
|
||||
performDelete: (item) => {
|
||||
const itemId = item.value
|
||||
const objectId = this.object.id
|
||||
const relationUrl = `/api/v1/users/users-groups-relations/?usergroup=${objectId}&user=${itemId}`
|
||||
return this.$axios.delete(relationUrl)
|
||||
},
|
||||
performAdd: (items) => {
|
||||
const relationUrl = `/api/v1/users/users-groups-relations/`
|
||||
const objectId = this.object.id
|
||||
const data = items.map(v => {
|
||||
return {
|
||||
user: v.value,
|
||||
usergroup: objectId
|
||||
}
|
||||
})
|
||||
return this.$axios.post(relationUrl, data)
|
||||
}
|
||||
},
|
||||
url: `/api/v1/users/groups/${this.object.id}`,
|
||||
excludes: ['users']
|
||||
}
|
||||
|
||||
148
src/views/users/Group/UserGroupDetail/GroupUser.vue
Normal file
148
src/views/users/Group/UserGroupDetail/GroupUser.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :md="14" :sm="24">
|
||||
<GenericListTable ref="listTable" :table-config="tableConfig" :header-actions="headerActions" />
|
||||
</el-col>
|
||||
<el-col :md="10" :sm="24">
|
||||
<QuickActions :actions="quickActions" :title="title" type="primary" />
|
||||
<RelationCard v-bind="relationConfig" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GenericListTable from '@/layout/components/GenericListTable'
|
||||
import QuickActions from '@/components/QuickActions'
|
||||
import RelationCard from '@/components/RelationCard'
|
||||
import { DeleteActionFormatter, DetailFormatter } from '@/components/TableFormatters'
|
||||
|
||||
export default {
|
||||
name: 'GroupUser',
|
||||
components: {
|
||||
QuickActions,
|
||||
RelationCard,
|
||||
GenericListTable
|
||||
},
|
||||
props: {
|
||||
object: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const vm = this
|
||||
return {
|
||||
title: this.$t('assets.QuickAdd'),
|
||||
quickActions: [
|
||||
{
|
||||
title: this.$t('users.AllMembers'),
|
||||
attrs: {
|
||||
type: 'primary',
|
||||
label: this.$tc('common.Add'),
|
||||
disabled: !this.$hasPerm('users.change_usergroup')
|
||||
},
|
||||
callbacks: Object.freeze({
|
||||
click: () => {
|
||||
this.$axios.post(
|
||||
`/api/v1/users/groups/${this.object.id}/add-all-users/`,
|
||||
).then(res => {
|
||||
window.location.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
],
|
||||
tableConfig: {
|
||||
url: `/api/v1/users/users/?group_id=${this.object.id}`,
|
||||
columns: [
|
||||
'name', 'username', 'email', 'is_valid', 'delete_action'
|
||||
],
|
||||
columnsMeta: {
|
||||
name: {
|
||||
formatter: DetailFormatter,
|
||||
formatterArgs: {
|
||||
route: 'UserDetail',
|
||||
can: vm.$hasPerm('user.view_user')
|
||||
}
|
||||
},
|
||||
delete_action: {
|
||||
prop: 'id',
|
||||
label: this.$t('common.Actions'),
|
||||
align: 'center',
|
||||
width: 150,
|
||||
objects: this.object.users,
|
||||
formatter: DeleteActionFormatter,
|
||||
onDelete: function(col, row, cellValue, reload) {
|
||||
this.$axios.delete(
|
||||
'/api/v1/users/users-groups-relations/', {
|
||||
params: {
|
||||
usergroup: this.object.id,
|
||||
user: row.id
|
||||
}
|
||||
}
|
||||
).then(res => {
|
||||
this.$message.success(this.$tc('common.deleteSuccessMsg'))
|
||||
reload()
|
||||
}).catch(error => {
|
||||
this.$message.error(this.$tc('common.deleteErrorMsg') + ' ' + error)
|
||||
})
|
||||
}.bind(this)
|
||||
},
|
||||
actions: {
|
||||
has: false
|
||||
}
|
||||
},
|
||||
tableAttrs: {
|
||||
border: false
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasSearch: true,
|
||||
hasRefresh: true,
|
||||
hasLeftActions: false,
|
||||
hasRightActions: true,
|
||||
hasExport: false,
|
||||
hasImport: false,
|
||||
hasCreate: false,
|
||||
searchConfig: {
|
||||
getUrlQuery: false
|
||||
},
|
||||
hasMoreActions: false
|
||||
},
|
||||
relationConfig: {
|
||||
icon: 'fa-user',
|
||||
title: this.$t('common.Members'),
|
||||
objectsAjax: {
|
||||
url: `/api/v1/users/users/?fields_size=mini&order=name&exclude_group_id=${this.object.id}`,
|
||||
transformOption: (item) => {
|
||||
return { label: item.name + '(' + item.username + ')', value: item.id }
|
||||
}
|
||||
},
|
||||
showHasObjects: false,
|
||||
hasObjectsId: this.object.users,
|
||||
performAdd: (items) => {
|
||||
const relationUrl = `/api/v1/users/users-groups-relations/`
|
||||
const groupId = this.object.id
|
||||
const data = items.map(v => {
|
||||
return {
|
||||
user: v.value,
|
||||
usergroup: groupId
|
||||
}
|
||||
})
|
||||
this.$axios.post(relationUrl, data)
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cell a {
|
||||
color: var(--color-info);
|
||||
}
|
||||
</style>
|
||||
@@ -9,11 +9,13 @@
|
||||
<script>
|
||||
import { GenericDetailPage } from '@/layout/components'
|
||||
import GroupInfo from './GroupInfo'
|
||||
import GroupUser from './GroupUser'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GenericDetailPage,
|
||||
GroupInfo
|
||||
GroupInfo,
|
||||
GroupUser
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -28,9 +30,7 @@ export default {
|
||||
},
|
||||
{
|
||||
title: this.$t('route.UserList'),
|
||||
name: 'GroupAddUser'
|
||||
// TODO 稍后加权限
|
||||
// hidden: () => !this.$hasPerm('accounts.change_accounttemplate')
|
||||
name: 'GroupUser'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user