Merge pull request #665 from jumpserver/dev

Merge V2.8 Rc3
This commit is contained in:
老广
2021-03-15 20:00:09 +08:00
committed by GitHub
28 changed files with 185 additions and 233 deletions

View File

@@ -88,6 +88,10 @@ export default {
hasExport: {
type: Boolean,
default: true
},
hasClone: {
type: Boolean,
default: true
}
},
data() {
@@ -146,6 +150,7 @@ export default {
formatterArgs: {
hasUpdate: false, // can set function(row, value)
hasDelete: false, // can set function(row, value)
hasClone: this.hasClone,
moreActionsTitle: this.$t('common.More'),
extraActions: [
{

View File

@@ -66,7 +66,8 @@ export default {
async optionUrlMetaAndGenCols() {
const url = (this.config.url.indexOf('?') === -1) ? `${this.config.url}?draw=1&display=1` : `${this.config.url}&draw=1&display=1`
this.$store.dispatch('common/getUrlMeta', { url: url }).then(data => {
this.meta = data.actions[this.method.toUpperCase()] || {}
const method = this.method.toUpperCase()
this.meta = data.actions && data.actions[method] ? data.actions[method] : {}
this.generateTotalColumns()
}).then(() => {
// 根据当前列重新生成最终渲染表格

View File

@@ -82,7 +82,7 @@ export default {
title: this.$t('common.Create'),
type: 'primary',
has: true,
can: true,
can: this.canCreate,
dropdown: [],
callback: this.handleCreate
}

View File

@@ -84,7 +84,9 @@ export default {
canUpdate: true, // can set function(row, value)
hasDelete: true, // can set function(row, value)
canDelete: true,
hasClone: true,
hasClone: () => {
return !this.$store.getters.currentOrgIsRoot
},
canClone: true,
updateRoute: this.$route.name.replace('List', 'Update'),
cloneRoute: this.$route.name.replace('List', 'Create'),

View File

@@ -1,15 +1,12 @@
<template>
<span>{{ cellValue }}</span>
<span>{{ cellValue.toString() }}</span>
</template>
<script>
import BaseFormatter from './base'
export default {
name: 'ArrayFormatter',
extends: BaseFormatter,
mounted() {
console.log(this.cellValue, '111')
}
extends: BaseFormatter
}
</script>

View File

@@ -4,7 +4,7 @@
<TreeTable
ref="TreeTable"
:table-config="tableConfig"
:header-actions="headerActions"
:header-actions="iHeaderActions"
:tree-setting="treeSetting"
v-on="$listeners"
>
@@ -39,6 +39,7 @@ export default {
iHeaderActions() {
const attrs = _.cloneDeep(this.headerActions)
const canCreate = _.get(attrs, 'canCreate', null)
// this.$log.debug('Current org: ', this.currentOrg)
if (canCreate === null && this.currentOrg && this.currentOrg.is_root) {
_.set(attrs, 'canCreate', false)
}

View File

@@ -48,7 +48,10 @@ export default {
},
methods: {
needShow() {
return !this.isCollapse && this.userAdminOrgList.length > 1 && this.inAdminPage
const otherOrgs = this.userAdminOrgList.filter(org => {
return !org.is_root && !org.is_default
})
return !this.isCollapse && otherOrgs.length > 0 && this.inAdminPage
},
changeOrg(orgId) {
orgUtil.changeOrg(orgId)

View File

@@ -4,7 +4,9 @@ const getters = {
token: state => state.users.token,
currentOrg: state => state.users.currentOrg,
currentOrgIsDefault: state => state.users.currentOrg.is_default,
currentOrgIsRoot: state => state.users.currentOrg.is_root,
currentOrgIsRoot: state => {
return state.users.currentOrg && state.users.currentOrg.is_root
},
currentRole: state => state.users.currentRole,
userAdminOrgList: state => state.users.orgs,
currentUser: state => state.users.profile,
@@ -16,6 +18,9 @@ const getters = {
currentOrgPerms: state => state.users.perms,
MFAVerifyAt: state => state.users.MFAVerifyAt,
MFA_TTl: state => state.settings.publicSettings.SECURITY_MFA_VERIFY_TTL,
tableConfig: state => state.table.tableConfig
tableConfig: state => state.table.tableConfig,
currentUserIsSuperAdmin: state => {
return state.users.sysRole === 'Admin'
}
}
export default getters

View File

@@ -16,9 +16,11 @@ const getDefaultState = () => {
currentRole: getCurrentRoleFromCookie(),
profile: {},
roles: {},
sysRole: '',
orgs: [],
perms: 0b00000000,
MFAVerifyAt: null
MFAVerifyAt: null,
isSuperAdmin: false
}
}
@@ -52,6 +54,9 @@ const mutations = {
SET_ROLES(state, roles) {
state.roles = roles
},
SET_SYS_ROLE(state, role) {
state.sysRole = role
},
SET_PERMS(state, perms) {
state.perms = perms
},
@@ -111,6 +116,7 @@ const actions = {
return dispatch('getProfile').then((profile) => {
const { current_org_roles: currentOrgRoles, role } = profile
const roles = rolec.parseUserRoles(currentOrgRoles, role)
commit('SET_SYS_ROLE', role)
commit('SET_ROLES', roles)
commit('SET_PERMS', rolec.sumPerms(roles))
resolve(roles)

View File

@@ -64,6 +64,16 @@ export default {
}
},
methods: {
getUrl() {
const params = this.$route.params
let url = `/api/v1/acls/login-asset-acls/`
if (params.id) {
url = `${url}${params.id}`
} else {
url = `${url}`
}
return url
},
getMethod() {
const params = this.$route.params
if (params.id) {
@@ -82,28 +92,26 @@ export default {
return validValues
},
performSubmit(validValues) {
if (validValues.assets.ip_group) {
console.log(validValues.assets.ip_group)
validValues.assets.ip_group = validValues.assets.ip_group.split(',')
if (!Array.isArray(validValues.assets.ip_group)) {
validValues.assets.ip_group = validValues.assets.ip_group ? validValues.assets.ip_group.split(',') : []
}
if (validValues.assets.hostname_group) {
validValues.assets.hostname_group = validValues.assets.hostname_group.split(',')
if (!Array.isArray(validValues.assets.hostname_group)) {
validValues.assets.hostname_group = validValues.assets.hostname_group ? validValues.assets.hostname_group.split(',') : []
}
if (validValues.system_users.protocol_group) {
validValues.system_users.protocol_group = validValues.system_users.protocol_group.split(',')
if (!Array.isArray(validValues.system_users.protocol_group)) {
validValues.system_users.protocol_group = validValues.system_users.protocol_group ? validValues.system_users.protocol_group.split(',') : []
}
if (validValues.system_users.name_group) {
validValues.system_users.name_group = validValues.system_users.name_group.split(',')
if (!Array.isArray(validValues.system_users.name_group)) {
validValues.system_users.name_group = validValues.system_users.name_group ? validValues.system_users.name_group.split(',') : []
}
if (validValues.system_users.username_group) {
validValues.system_users.username_group = validValues.system_users.username_group.split(',')
if (!Array.isArray(validValues.system_users.username_group)) {
validValues.system_users.username_group = validValues.system_users.username_group ? validValues.system_users.username_group.split(',') : []
}
if (validValues.users.username_group) {
validValues.users.username_group = validValues.users.username_group.split(',')
if (!Array.isArray(validValues.users.username_group)) {
validValues.users.username_group = validValues.users.username_group ? validValues.users.username_group.split(',') : []
}
const baseUrl = `/api/v1/acls/login-asset-acls/`
const method = this.getMethod()
return this.$axios[method](`${baseUrl}`, validValues)
return this.$axios[method](`${this.getUrl()}`, validValues)
}
}
}

View File

@@ -22,6 +22,9 @@ export default {
user_username_group: {
prop: 'users.username_group',
showOverflowTooltip: true,
formatter: function(row) {
return <span> {row.users.username_group.toString()} </span>
},
label: this.$t('acl.username_group')
},
reviewers: {
@@ -29,23 +32,43 @@ export default {
},
hostname_group: {
prop: 'assets.hostname_group',
label: this.$t('acl.hostname_group')
label: this.$t('acl.hostname_group'),
showOverflowTooltip: true,
formatter: function(row) {
return <span> {row.assets.hostname_group.toString()} </span>
}
},
ip_group: {
prop: 'assets.ip_group',
label: this.$t('acl.asset_ip_group')
label: this.$t('acl.asset_ip_group'),
showOverflowTooltip: true,
formatter: function(row) {
return <span> {row.assets.ip_group.toString()} </span>
}
},
name_group: {
prop: 'system_users.name_group',
label: this.$t('acl.system_users_name_group')
label: this.$t('acl.system_users_name_group'),
showOverflowTooltip: true,
formatter: function(row) {
return <span> {row.system_users.name_group.toString()} </span>
}
},
protocol_group: {
prop: 'system_users.protocol_group',
label: this.$t('acl.system_users_protocol_group')
label: this.$t('acl.system_users_protocol_group'),
showOverflowTooltip: true,
formatter: function(row) {
return <span> {row.system_users.protocol_group.toString()} </span>
}
},
systemuser_username_group: {
prop: 'system_users.username_group',
label: this.$t('acl.system_users_username_group')
label: this.$t('acl.system_users_username_group'),
showOverflowTooltip: true,
formatter: function(row) {
return <span> {row.system_users.username_group.toString()} </span>
}
}
}
},

View File

@@ -76,11 +76,11 @@ export default {
return validValues
},
performSubmit(validValues) {
if (validValues.ip_group) {
validValues.ip_group = validValues.ip_group.split(',')
if (!Array.isArray(validValues.ip_group)) {
validValues.ip_group = validValues.ip_group ? validValues.ip_group.split(',') : []
}
const method = this.getMethod()
return this.$axios[method](`${this.getUrl()}}`, validValues)
return this.$axios[method](`${this.getUrl()}`, validValues)
}
}
}

View File

@@ -2,7 +2,7 @@
<div>
<el-row :gutter="20">
<el-col :span="16">
<AssetUserTable :url="assetUserUrl" :has-import="false" />
<AssetUserTable :url="assetUserUrl" :has-import="false" :has-clone="false" />
</el-col>
</el-row>
</div>

View File

@@ -16,7 +16,7 @@
import QuickActions from '@/components/QuickActions/index'
import ListTable from '@/components/ListTable'
import RelationCard from '@/components/RelationCard'
import { BooleanFormatter } from '@/components/ListTable/formatters'
import { ChoicesFormatter } from '@/components/ListTable/formatters'
export default {
name: 'AssetList',
@@ -44,7 +44,7 @@ export default {
},
connectivity: {
label: this.$t('assets.Reachable'),
formatter: BooleanFormatter,
formatter: ChoicesFormatter,
formatterArgs: {
iconChoices: {
0: 'fa-times text-danger',

View File

@@ -3,22 +3,17 @@
<el-col :span="14">
<DetailCard :items="detailCardItems" />
</el-col>
<el-col :span="10">
<RelationCard ref="RelationCard" type="info" v-bind="nodeRelationConfig" />
</el-col>
</el-row>
</template>
<script>
import DetailCard from '@/components/DetailCard'
import RelationCard from '@/components/RelationCard'
import { toSafeLocalDateStr } from '@/utils/common'
export default {
name: 'Detail',
components: {
DetailCard,
RelationCard
DetailCard
},
props: {
object: {
@@ -28,31 +23,7 @@ export default {
},
data() {
return {
nodeRelationConfig: {
icon: 'fa-info',
title: this.$t('assets.ReplaceNodeAssetsAdminUserWithThis'),
objectsAjax: {
url: '/api/v1/assets/nodes/',
transformOption: (item) => {
return { label: item.full_value, value: item.id }
}
},
performAdd: (items) => {
const data = []
const relationUrl = `/api/v1/assets/admin-users/${this.object.id}/nodes/`
items.map(v => {
data.push(v.value)
})
return this.$axios.patch(relationUrl, { nodes: data }).then(res => {
this.$message.success(this.$t('common.updateSuccessMsg'))
}).catch(err => {
this.$message.error(this.$t('common.updateErrorMsg' + ' ' + err))
})
},
onAddSuccess: () => {
this.$refs.RelationCard.$refs.select2.clearSelected()
}
}
}
},
computed: {

View File

@@ -67,7 +67,7 @@
<script>
import GenericTreeListPage from '@/layout/components/GenericTreeListPage/index'
import { DetailFormatter, ActionsFormatter, BooleanFormatter } from '@/components/ListTable/formatters'
import { DetailFormatter, ActionsFormatter, ChoicesFormatter } from '@/components/ListTable/formatters'
import $ from '@/utils/jquery-vendor'
import Dialog from '@/components/Dialog'
import TreeTable from '@/components/TreeTable'
@@ -138,7 +138,7 @@ export default {
},
connectivity: {
label: this.$t('assets.Reachable'),
formatter: BooleanFormatter,
formatter: ChoicesFormatter,
formatterArgs: {
iconChoices: {
0: 'fa-times text-danger',

View File

@@ -82,8 +82,8 @@ export default {
name: 'detail',
title: this.$t('ops.detail'),
type: 'primary',
callback: function({ cellValue, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: cellValue }})
callback: function({ row, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: row.id }})
}
}
]

View File

@@ -79,8 +79,8 @@ export default {
name: 'detail',
title: this.$t('ops.detail'),
type: 'primary',
callback: function({ cellValue, tableData }) {
return this.$router.push({ name: 'AdhocDetail', params: { id: cellValue }})
callback: function({ row, tableData }) {
return this.$router.push({ name: 'AdhocDetail', params: { id: row.id }})
}
}
]

View File

@@ -91,8 +91,8 @@ export default {
name: 'detail',
title: this.$t('ops.detail'),
type: 'primary',
callback: function({ cellValue, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: cellValue }})
callback: function({ row, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: row.id }})
}
}
]

View File

@@ -77,9 +77,9 @@ export default {
name: 'run',
title: this.$t('ops.run'),
type: 'primary',
callback: function({ cellValue, tableData }) {
callback: function({ row, tableData }) {
this.$axios.get(
`/api/v1/ops/tasks/${cellValue}/run/`
`/api/v1/ops/tasks/${row.id}/run/`
).then(res => {
window.open(`/#/ops/celery/task/${res.task}/log/`, '', 'width=900,height=600')
})

View File

@@ -143,7 +143,7 @@ export default {
icon: 'fa-edit',
title: this.$t('perms.addSystemUserToThisPermission'),
objectsAjax: {
url: '/api/v1/assets/system-users/',
url: '/api/v1/assets/system-users/?protocol__in=rdp,ssh,vnc,telnet',
transformOption: (item) => {
return { label: item.name + '(' + item.username + ')', value: item.id }
}

View File

@@ -50,7 +50,7 @@ export default {
actions: {
formatterArgs: {
onUpdate: ({ row, col, cellValue }) => {
this.$router.push({ name: 'ApplicationPermissionUpdate', params: { id: cellValue }})
this.$router.push({ name: 'ApplicationPermissionUpdate', params: { id: row.id }})
},
performDelete: ({ row, col }) => {
const id = row.id

View File

@@ -31,6 +31,15 @@ export default {
},
data() {
const vm = this
const hasDelete = () => {
return vm.currentUserIsSuperAdmin
}
const hasRemove = () => {
if (!vm.publicSettings.XPACK_LICENSE_IS_VALID) {
return false
}
return !vm.currentOrgIsRoot
}
return {
tableConfig: {
url: '/api/v1/users/users/',
@@ -69,7 +78,7 @@ export default {
},
actions: {
formatterArgs: {
hasDelete: () => this.currentOrgIsRoot,
hasDelete: hasDelete,
canUpdate: function(row, cellValue) {
return row.can_update
},
@@ -81,7 +90,7 @@ export default {
title: this.$t('users.Remove'),
name: 'remove',
type: 'warning',
has: () => !this.currentOrgIsRoot,
has: hasRemove,
can: function(row, cellValue) {
return row.can_delete
},
@@ -93,27 +102,27 @@ export default {
}
},
headerActions: {
hasBulkDelete: false,
hasBulkDelete: hasDelete,
canCreate: true,
extraActions: [
{
name: this.$t('users.InviteUser'),
title: this.$t('users.InviteUser'),
has:
(JSON.parse(this.$cookie.get('jms_current_org'))
? JSON.parse(this.$cookie.get('jms_current_org')).id
: '') !== 'DEFAULT',
has: () => {
return !this.currentOrgIsRoot && this.publicSettings.XPACK_LICENSE_IS_VALID
},
callback: function() { this.InviteDialogSetting.InviteDialogVisible = true }.bind(this)
}
],
extraMoreActions: [
{
title: this.$t('common.deleteSelected'),
name: 'deleteSelected',
title: this.$t('common.removeSelected'),
name: 'removeSelected',
has: hasRemove,
can({ selectedRows }) {
return selectedRows.length > 0
},
callback: this.bulkDeleteCallback.bind(this)
callback: this.bulkRemoveCallback.bind(this)
},
{
name: 'disableSelected',
@@ -203,95 +212,29 @@ export default {
}
},
computed: {
...mapGetters(['currentOrgIsRoot', 'currentUser', 'device'])
},
mounted() {
if (!this.currentOrgIsRoot) {
this.headerActions.extraMoreActions[0].title = this.$t(
'common.removeSelected'
)
}
...mapGetters([
'currentOrgIsRoot', 'currentUser', 'publicSettings',
'device', 'currentOrgIsDefault', 'currentUserIsSuperAdmin'
])
},
methods: {
removeUserFromOrg({ row, col, reload }) {
const msg =
this.$t('users.removeFromOrgWarningMsg') + ' "' + row.name + '"'
const title = this.$t('common.Info')
const performDelete = function() {
const url = `/api/v1/users/users/${row.id}/`
return this.$axios.delete(url)
}
this.$alert(msg, title, {
type: 'warning',
confirmButtonClass: 'el-button--danger',
showCancelButton: true,
beforeClose: async(action, instance, done) => {
if (action !== 'confirm') return done()
instance.confirmButtonLoading = true
try {
await performDelete.bind(this)({ row: row, col: col })
done()
reload()
this.$message.success(this.$t('common.removeSuccessMsg'))
} catch (error) {
this.$message.error(this.$t('common.removeErrorMsg' + ' ' + error))
} finally {
instance.confirmButtonLoading = false
}
}
const url = `/api/v1/users/users/${row.id}/remove/`
this.$axios.post(url).then(() => {
reload()
this.$message.success(this.$t('common.removeSuccessMsg'))
})
},
bulkDeleteCallback({ selectedRows, reloadTable }) {
let msgPrefix = this.$t('common.deleteWarningMsg')
if (!this.currentOrgIsRoot) {
msgPrefix = this.$t('common.removeWarningMsg')
}
const msg =
msgPrefix +
' ' +
selectedRows.length +
' ' +
this.$t('common.rows') +
' ?'
const title = this.$t('common.Info')
const performDelete = this.performBulkDelete
this.$alert(msg, title, {
type: 'warning',
confirmButtonClass: 'el-button--danger',
showCancelButton: true,
beforeClose: async(action, instance, done) => {
if (action !== 'confirm') return done()
instance.confirmButtonLoading = true
try {
await performDelete(selectedRows)
done()
reloadTable()
let successMsg = this.$t('common.bulkDeleteSuccessMsg')
if (!this.currentOrgIsRoot) {
successMsg = this.$t('common.bulkRemoveSuccessMsg')
}
this.$message.success(successMsg)
} catch (error) {
// let errorMsg = this.$t('common.bulkDeleteErrorMsg')
// if (!this.currentOrgIsRoot) {
// errorMsg = this.$t('common.bulkRemoveErrorMsg')
// }
// this.$message.error(errorMsg + error)
} finally {
instance.confirmButtonLoading = false
}
}
}).catch(() => {
/* 取消*/
})
},
async performBulkDelete(selectedRows) {
async bulkRemoveCallback({ selectedRows, reloadTable }) {
const ids = selectedRows.map(v => {
return v.id
})
const data = await createSourceIdCache(ids)
const url = `${this.tableConfig.url}?spm=` + data.spm
return this.$axios.delete(url)
const url = `${this.tableConfig.url}/remove/?spm=` + data.spm
this.$axios.post(url).then(() => {
reloadTable()
this.$message.success(this.$t('common.removeSuccessMsg'))
})
},
handleInviteDialogClose() {
this.InviteDialogSetting.InviteDialogVisible = false

View File

@@ -51,9 +51,9 @@ export default {
name: 'retry',
type: 'info',
title: this.$t('xpack.ChangeAuthPlan.Retry'),
callback: function({ cellValue, tableData }) {
callback: function({ row, tableData }) {
this.$axios.put(
`/api/v1/xpack/change-auth-plan/plan-execution-subtask/${cellValue}/`,
`/api/v1/xpack/change-auth-plan/plan-execution-subtask/${row.id}/`,
).then(res => {
window.open(`/#/ops/celery/task/${res.task}/log/`, '_blank', 'toolbar=yes, width=900, height=600')
})

View File

@@ -74,16 +74,16 @@ export default {
name: 'log',
type: 'primary',
title: this.$t('xpack.ChangeAuthPlan.Log'),
callback: function({ cellValue, tableData }) {
window.open(`/#/ops/celery/task/${cellValue}/log/`, '_blank', 'toolbar=yes, width=900, height=600')
callback: function({ row }) {
window.open(`/#/ops/celery/task/${row.id}/log/`, '_blank', 'toolbar=yes, width=900, height=600')
}
},
{
name: 'detail',
title: this.$t('xpack.ChangeAuthPlan.Detail'),
type: 'info',
callback: function({ cellValue, tableData }) {
return this.$router.push({ name: 'ChangeAuthPlanExecutionDetail', params: { id: cellValue }})
callback: function({ row }) {
return this.$router.push({ name: 'ChangeAuthPlanExecutionDetail', params: { id: row.id }})
}
}
]

View File

@@ -64,10 +64,10 @@ export default {
title: vm.$t('xpack.Execute'),
name: 'execute',
type: 'info',
callback: function(data) {
callback: function({ row }) {
this.$axios.post(
`/api/v1/xpack/change-auth-plan/plan-execution/`,
{ plan: data.cellValue }
{ plan: row.id }
).then(res => {
window.open(`/#/ops/celery/task/${res.task}/log/`, '_blank', 'toolbar=yes, width=900, height=600')
})

View File

@@ -67,60 +67,46 @@ export default {
headerActions: {
hasBulkDelete: false,
hasImport: false,
hasCreate: false,
moreActionsTitle: this.$t('common.Create'),
moreActionsType: 'primary',
extraMoreActions: [
{
name: aliyun,
title: ACCOUNT_PROVIDER_ATTRS_MAP[aliyun].title,
type: 'primary',
can: true,
callback: this.createAccount(aliyun).bind(this)
hasMoreActions: false,
moreCreates: {
callback: (option) => {
vm.$router.push({ name: 'AccountCreate', query: { provider: option.name }})
},
{
name: qcloud,
title: ACCOUNT_PROVIDER_ATTRS_MAP[qcloud].title,
type: 'primary',
can: true,
callback: this.createAccount(qcloud).bind(this)
},
{
name: aws_china,
title: ACCOUNT_PROVIDER_ATTRS_MAP[aws_china].title,
type: 'primary',
can: true,
callback: this.createAccount(aws_china).bind(this)
},
{
name: aws_international,
title: ACCOUNT_PROVIDER_ATTRS_MAP[aws_international].title,
type: 'primary',
can: true,
callback: this.createAccount(aws_international).bind(this)
},
{
name: huaweicloud,
title: ACCOUNT_PROVIDER_ATTRS_MAP[huaweicloud].title,
type: 'primary',
can: true,
callback: this.createAccount(huaweicloud).bind(this)
},
{
name: azure,
title: ACCOUNT_PROVIDER_ATTRS_MAP[azure].title,
type: 'primary',
can: true,
callback: this.createAccount(azure).bind(this)
},
{
name: vmware,
title: ACCOUNT_PROVIDER_ATTRS_MAP[vmware].title,
type: 'primary',
can: true,
callback: this.createAccount(vmware).bind(this)
}
]
dropdown: [
{
name: aliyun,
title: ACCOUNT_PROVIDER_ATTRS_MAP[aliyun].title,
type: 'primary',
can: true
},
{
name: qcloud,
title: ACCOUNT_PROVIDER_ATTRS_MAP[qcloud].title,
type: 'primary',
can: true
},
{
name: aws_china,
title: ACCOUNT_PROVIDER_ATTRS_MAP[aws_china].title
},
{
name: aws_international,
title: ACCOUNT_PROVIDER_ATTRS_MAP[aws_international].title
},
{
name: huaweicloud,
title: ACCOUNT_PROVIDER_ATTRS_MAP[huaweicloud].title
},
{
name: azure,
title: ACCOUNT_PROVIDER_ATTRS_MAP[azure].title
},
{
name: vmware,
title: ACCOUNT_PROVIDER_ATTRS_MAP[vmware].title
}
]
}
}
}
},

View File

@@ -105,6 +105,7 @@ export default {
assetUserConfig: {
hasLeftActions: true,
hasCreate: true,
hasClone: false,
url: '/api/v1/assets/asset-users/',
handleImport: function({ selectedRows }) {
this.selectedRows = selectedRows