Perf: Add Account Change Or Move To Different Asset (#4567)

* Perf: Add Account Change Or Move To Different Asset

* Fixed: Fixed Add Account And Template input disabled

* Perf: Add Account Operation Bulk Result

---------

Co-authored-by: zhaojisen <1301338853@qq.com>
This commit is contained in:
fit2bot
2025-01-03 11:05:49 +08:00
committed by GitHub
parent 78e6d4e367
commit fee2123b49
5 changed files with 148 additions and 43 deletions

View File

@@ -5,6 +5,9 @@ import AutomationParamsForm from '@/views/assets/Platform/AutomationParamsSettin
export const accountFieldsMeta = (vm) => {
const defaultPrivilegedAccounts = ['root', 'administrator']
const isPam = vm.$route.query.flag === 'copy' || vm.$route.query.flag === 'move'
return {
assets: {
component: Select2,
@@ -27,6 +30,7 @@ export const accountFieldsMeta = (vm) => {
component: Select2,
rules: [Required],
el: {
disabled: isPam,
multiple: false,
ajax: {
url: '/api/v1/accounts/account-templates/',
@@ -43,6 +47,9 @@ export const accountFieldsMeta = (vm) => {
rules: [Required],
label: vm.$t('AccountPolicy'),
helpTip: vm.$t('AccountPolicyHelpText'),
el: {
disabled: isPam
},
hidden: () => {
return vm.platform || vm.asset
}
@@ -50,6 +57,9 @@ export const accountFieldsMeta = (vm) => {
name: {
label: vm.$t('Name'),
rules: [RequiredChange],
el: {
disabled: isPam
},
on: {
input: ([value], updateForm) => {
if (!vm.usernameChanged) {
@@ -66,7 +76,7 @@ export const accountFieldsMeta = (vm) => {
},
username: {
el: {
disabled: !!vm.account?.name
disabled: !!vm.account?.name || isPam
},
on: {
input: ([value], updateForm) => {
@@ -85,6 +95,9 @@ export const accountFieldsMeta = (vm) => {
},
privileged: {
label: vm.$t('Privileged'),
el: {
disabled: isPam
},
hidden: () => {
return vm.addTemplate
}
@@ -97,6 +110,7 @@ export const accountFieldsMeta = (vm) => {
el: {
multiple: false,
clearable: true,
disabled: isPam,
ajax: {
url: `/api/v1/accounts/accounts/su-from-accounts/?account=${vm.account?.id || ''}&asset=${vm.asset?.id || ''}`,
transformOption: (item) => {
@@ -107,6 +121,7 @@ export const accountFieldsMeta = (vm) => {
},
su_from_username: {
label: vm.$t('UserSwitchFrom'),
disabled: isPam,
hidden: (formValue) => {
return vm.platform || vm.asset || vm.addTemplate
}
@@ -115,39 +130,57 @@ export const accountFieldsMeta = (vm) => {
label: vm.$t('Password'),
component: UpdateToken,
hidden: (formValue) => {
return formValue.secret_type !== 'password' || vm.addTemplate
return formValue.secret_type !== 'password' || vm.addTemplate || vm.$route.fullPath.includes('pam')
}
},
ssh_key: {
label: vm.$t('PrivateKey'),
component: UploadSecret,
el: {
disabled: isPam
},
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || vm.addTemplate
},
passphrase: {
label: vm.$t('Passphrase'),
component: UpdateToken,
el: {
disabled: isPam
},
hidden: (formValue) => formValue.secret_type !== 'ssh_key' || vm.addTemplate
},
token: {
label: vm.$t('Token'),
component: UploadSecret,
el: {
disabled: isPam
},
hidden: (formValue) => formValue.secret_type !== 'token' || vm.addTemplate
},
access_key: {
id: 'access_key',
label: vm.$t('AccessKey'),
component: UploadSecret,
el: {
disabled: isPam
},
hidden: (formValue) => formValue.secret_type !== 'access_key' || vm.addTemplate
},
api_key: {
id: 'api_key',
label: vm.$t('ApiKey'),
component: UploadSecret,
el: {
disabled: isPam
},
hidden: (formValue) => formValue.secret_type !== 'api_key' || vm.addTemplate
},
secret_type: {
type: 'radio-group',
options: [],
el: {
disabled: isPam
},
hidden: () => {
return vm.addTemplate
}
@@ -182,10 +215,22 @@ export const accountFieldsMeta = (vm) => {
}
},
is_active: {
label: vm.$t('IsActive')
label: vm.$t('IsActive'),
el: {
disabled: isPam
}
},
comment: {
label: vm.$t('Comment')
label: vm.$t('Comment'),
el: {
disabled: isPam
}
},
secret_reset: {
label: vm.$t('SecretReset'),
el: {
disabled: isPam
}
}
}
}

View File

@@ -4,7 +4,7 @@
:title="title"
:visible="iVisible"
class="drawer"
@close-drawer="iVisible = false"
@close-drawer="handleCloseDrawer"
>
<Page :title="'null'">
<IBox class="content">
@@ -109,18 +109,27 @@ export default {
}
}).catch(error => {
this.iVisible = true
console.log(this.iVisible)
console.log(this.origin)
this.handleResult(null, error)
})
},
editAccount(form) {
const data = { ...form }
this.$axios.patch(`/api/v1/accounts/accounts/${this.account.id}/`, data).then(() => {
this.iVisible = false
this.$emit('add', true)
this.$message.success(this.$tc('UpdateSuccessMsg'))
}).catch(error => this.setFieldError(error))
const flag = this.$route.query.flag
switch (flag) {
case 'copy':
this.handleAccountOperation(this.account.id, 'copy-to-assets', data)
break
case 'move':
this.handleAccountOperation(this.account.id, 'move-to-assets', data)
break
default:
this.$axios.patch(`/api/v1/accounts/accounts/${this.account.id}/`, data).then(() => {
this.iVisible = false
this.$emit('add', true)
this.$message.success(this.$tc('UpdateSuccessMsg'))
}).catch(error => this.setFieldError(error))
}
},
handleResult(resp, error) {
let bulkCreate = !this.asset
@@ -173,6 +182,18 @@ export default {
refsAutoDataForm.setFieldError(current, err)
}
}
},
handleCloseDrawer() {
this.iVisible = false
Reflect.deleteProperty(this.$route.query, 'flag')
},
handleAccountOperation(id, path, data) {
this.$axios.post(`/api/v1/accounts/accounts/${id}/${path}/`, data).then((res) => {
this.iVisible = false
this.$emit('add', true)
this.handleResult(res, null)
this.$message.success(this.$tc('UpdateSuccessMsg'))
}).catch(error => this.handleResult(null, error))
}
}
}
@@ -187,8 +208,4 @@ export default {
}
}
}
.content {
}
</style>

View File

@@ -50,18 +50,28 @@
v-bind="updateSelectedDialogSetting"
@update="handleAccountBulkUpdate"
/>
<PasswordHistoryDialog
v-if="showPasswordHistoryDialog"
:account="currentAccountColumn"
:visible.sync="showPasswordHistoryDialog"
/>
</div>
</template>
<script>
import ListTable from '@/components/Table/DrawerListTable/index.vue'
import { ActionsFormatter, PlatformFormatter, SecretViewerFormatter } from '@/components/Table/TableFormatters'
import ViewSecret from './ViewSecret.vue'
import UpdateSecretInfo from './UpdateSecretInfo.vue'
import AccountCreateUpdate from './AccountCreateUpdate.vue'
import { connectivityMeta } from './const'
import { openTaskPage } from '@/utils/jms'
import {
ActionsFormatter,
PlatformFormatter,
SecretViewerFormatter
} from '@/components/Table/TableFormatters'
import ViewSecret from './ViewSecret.vue'
import UpdateSecretInfo from './UpdateSecretInfo.vue'
import ResultDialog from './BulkCreateResultDialog.vue'
import AccountCreateUpdate from './AccountCreateUpdate.vue'
import PasswordHistoryDialog from './PasswordHistoryDialog.vue'
import ListTable from '@/components/Table/DrawerListTable/index.vue'
import AccountBulkUpdateDialog from '@/components/Apps/AccountListTable/AccountBulkUpdateDialog.vue'
export default {
@@ -72,7 +82,8 @@ export default {
ListTable,
UpdateSecretInfo,
ViewSecret,
AccountCreateUpdate
AccountCreateUpdate,
PasswordHistoryDialog
},
props: {
url: {
@@ -119,8 +130,7 @@ export default {
},
columnsMeta: {
type: Object,
default: () => {
}
default: () => {}
},
columnsDefault: {
type: Array,
@@ -140,6 +150,8 @@ export default {
data() {
const vm = this
return {
currentAccountColumn: {},
showPasswordHistoryDialog: false,
showViewSecretDialog: false,
showUpdateSecretDialog: false,
showResultDialog: false,
@@ -323,14 +335,14 @@ export default {
return (
<span className='connect'>
<el-button type='primary' size='mini' plain>
<i className='fa fa-desktop'/>
<i className='fa fa-desktop' />
</el-button>
</span>
)
}
},
asset: {
formatter: (row) => {
formatter: row => {
const to = {
name: 'AssetDetail',
params: { id: row.asset.id }
@@ -451,18 +463,45 @@ export default {
},
{
name: 'SecretHistory',
title: '密文历史'
// 密文历史
title: this.$t('SecretHistory'),
can: () => this.$hasPerm('accounts.view_accountsecret'),
type: 'primary',
callback: ({ row }) => {
this.currentAccountColumn = row
this.$nextTick(() => {
this.showPasswordHistoryDialog = true
})
}
},
{
name: 'CopyToOther',
title: '复制到其他资产',
type: 'primary',
divided: true
divided: true,
callback: async({ row }) => {
await this.getAssetDetail()
this.$nextTick(() => {
vm.$route.query.flag = 'copy'
vm.iAsset = this.asset
vm.account = row
vm.showAddDialog = true
})
}
},
{
name: 'MoveToOther',
title: '移动到其他资产',
type: 'primary'
type: 'primary',
callback: async({ row }) => {
await this.getAssetDetail()
this.$nextTick(() => {
vm.$route.query.flag = 'move'
vm.iAsset = this.asset
vm.account = row
vm.showAddDialog = true
})
}
},
{
name: 'Clone',
@@ -654,6 +693,7 @@ export default {
Object.assign(this.account, account)
},
addAccountSuccess() {
Reflect.deleteProperty(this.$route.query, 'flag')
this.$refs.ListTable.reloadTable()
},
async getAssetDetail() {
@@ -692,9 +732,8 @@ export default {
}
</script>
<style lang='scss' scoped>
<style lang="scss" scoped>
.cell a {
color: var(--color-info);
}
</style>

View File

@@ -391,18 +391,22 @@ export default {
async getCloneForm(cloneFrom) {
const [curUrl, query] = this.url.split('?')
const url = `${curUrl}${cloneFrom}/${query ? ('?' + query) : ''}`
const object = await this.getObjectDetail(url)
let name = ''
let attr = ''
if (object['name']) {
name = object['name']
attr = 'name'
} else if (object['hostname']) {
name = object['hostname']
attr = 'hostname'
try {
const object = await this.getObjectDetail(url)
let name = ''
let attr = ''
if (object['name']) {
name = object['name']
attr = 'name'
} else if (object['hostname']) {
name = object['hostname']
attr = 'hostname'
}
object[attr] = name + '-' + this.cloneNameSuffix.toString()
return object
} catch (e) {
throw new Error(`Error for reason: ${e.message}`)
}
object[attr] = name + '-' + this.cloneNameSuffix.toString()
return object
},
async getFormValue() {
if (this.action === 'create' || !this.needGetObjectDetail) {

View File

@@ -56,7 +56,7 @@ export default {
this.getPermdProtocols(row.asset.id)
}
},
command: protocol => {
'command': protocol => {
this.$store.commit('table/SET_PROTOCOL_MAP_ITEM', {
key: row.id,
value: protocol