diff --git a/src/components/AccountCreateUpdateForm/index.vue b/src/components/AccountCreateUpdateForm/index.vue index d7f27c748..31b25683b 100644 --- a/src/components/AccountCreateUpdateForm/index.vue +++ b/src/components/AccountCreateUpdateForm/index.vue @@ -32,7 +32,7 @@ export default { form: this.account || { }, fields: [ [this.$t('common.Basic'), ['name', 'username', 'privileged']], - [this.$t('assets.Secret'), ['secret_type', 'password', 'ssh_key', 'token', 'api_key', 'passphrase']], + [this.$t('assets.Secret'), ['secret_type', 'secret', 'ssh_key', 'token', 'api_key', 'passphrase']], [this.$t('common.Other'), ['push_now', 'comment']] ], defaultPrivilegedAccounts: ['root', 'administrator'], @@ -58,7 +58,7 @@ export default { } } }, - password: { + secret: { label: this.$t('assets.Password'), component: UpdateToken, hidden: (formValue) => formValue.secret_type !== 'password' diff --git a/src/components/AccountListTable/PasswordHistoryDialog.vue b/src/components/AccountListTable/PasswordHistoryDialog.vue index eb66af16e..ced686122 100644 --- a/src/components/AccountListTable/PasswordHistoryDialog.vue +++ b/src/components/AccountListTable/PasswordHistoryDialog.vue @@ -26,7 +26,7 @@ export default { visible: false, width: '60%', tableConfig: { - url: `/api/v1/assets/accounts-historys?id=${this.account.id}`, + url: `/api/v1/assets/account-secrets/${this.account.id}/histories/`, columns: [ 'name', 'version', 'password', 'date_created' ], diff --git a/src/components/AccountListTable/index.vue b/src/components/AccountListTable/index.vue index 73f5b53f8..71cf48eb3 100644 --- a/src/components/AccountListTable/index.vue +++ b/src/components/AccountListTable/index.vue @@ -188,7 +188,7 @@ export default { }, { title: this.$t('accounts.HistoryPassword'), - can: this.$hasPerm('assets.change_assetaccountsecret') && !this.$store.getters.currentOrgIsRoot, + can: this.$hasPerm('assets.view_accountsecret') && !this.$store.getters.currentOrgIsRoot, callback: ({ row }) => { vm.account = row vm.showPasswordHistoryDialog = false @@ -207,7 +207,7 @@ export default { hasMoreActions: true, hasCreate: false, hasImport: true, - hasExport: this.$hasPerm('assets.view_assetaccountsecret'), + hasExport: this.$hasPerm('assets.view_account'), exportOptions: { url: this.exportUrl, mfaVerifyRequired: true diff --git a/src/components/AssetSelect/index.vue b/src/components/AssetSelect/index.vue index a95af21e2..ab364b792 100644 --- a/src/components/AssetSelect/index.vue +++ b/src/components/AssetSelect/index.vue @@ -110,7 +110,7 @@ export default { { prop: 'protocols', formatter: function(row) { - return {row.protocols.toString()} + return {row.protocols?.toString()} }, label: this.$t('assets.Protocols') } diff --git a/src/components/FormFields/UpdateToken.vue b/src/components/FormFields/UpdateToken.vue index d0cdf7e70..aacb38c1c 100644 --- a/src/components/FormFields/UpdateToken.vue +++ b/src/components/FormFields/UpdateToken.vue @@ -32,6 +32,10 @@ export default { return this.$t('common.Update') } }, + showInput: { + type: Boolean, + default: true + }, placeholder: { type: String, default: () => '' @@ -39,13 +43,13 @@ export default { }, data() { return { - isShow: false, + isShow: this.showInput, curValue: this.value } }, created() { - if (this.$route.path.indexOf('/create') !== -1) { - this.isShow = true + if (this.$route.path.indexOf('/update') !== -1) { + this.isShow = false } }, methods: { diff --git a/src/components/TableFormatters/ShowKeyCopyFormatter.vue b/src/components/TableFormatters/ShowKeyCopyFormatter.vue index 9d533ea9f..22e3ee307 100644 --- a/src/components/TableFormatters/ShowKeyCopyFormatter.vue +++ b/src/components/TableFormatters/ShowKeyCopyFormatter.vue @@ -32,7 +32,7 @@ export default { }, cellValue: { type: [String, Number], - default: null + default: '' }, hasShow: { type: Boolean, @@ -56,7 +56,7 @@ export default { methods: { switchShowValue() { const value = this.value || this.cellValue - return '******' + value.replace(/[\s\S]/g, '') + return value ? '******' + value.replace(/[\s\S]/g, '') : '' }, onShow() { const { currentValue, switchShowValue } = this diff --git a/src/i18n/langs/en.json b/src/i18n/langs/en.json index ec77b2f69..365e25b38 100644 --- a/src/i18n/langs/en.json +++ b/src/i18n/langs/en.json @@ -93,6 +93,10 @@ "NoSQLProtocol": "NoSQL Protocol" }, "assets": { + "SelectTemplate": "Select template", + "InAssetDetail": "Update account information in asset details", + "SecretType": "Secret type", + "PrivilegedTemplate": "Privileged", "All": "All", "CloudPlatform": "Cloud platform", "RecentlyUsed": "Recently used", @@ -314,6 +318,7 @@ "Active": "Active", "TableColSettingInfo": "Please select the list details you want to display", "Add": "Add", + "TemplateAdd": "Template add", "PleaseAgreeToTheTerms": "Please agree to the terms", "PushSelected": "Push selected", "PushSelectedSystemUsersToAsset": "Push selected system users to asset", @@ -713,6 +718,9 @@ "SessionDetail": "SessionDetail", "Accounts": "Accounts", "AssetAccount": "Asset Account", + "AccountTemplate": "Account template", + "CreateAccountTemplate": "Create account template", + "UpdateAccountTemplate": "Update account template", "AssetHistoryAccount": "Asset History Account", "ApplicationAccount": "Application Account", "Ticket": "Tickets", @@ -735,7 +743,8 @@ "SessionsAudit": "Sessions audit", "SessionList": "Session list", "BatchCommand": "Batch Command", - "BatchCommandLog": "Batch Command Logs", + "BatchScript": "Batch Script", + "tasksLog": "Batch Command Logs", "CeleryTaskLog": "Celery task log", "CommandExecutions": "CommandExecutions ", "CommandFilterCreate": "Command filter create", @@ -784,7 +793,8 @@ "FtpLog": "FTP Logs", "GatewayCreate": "Gateway create", "GatewayUpdate": "Gateway update", - "JobCenter": "Devops", + "TaskCenter": "Task", + "JobCenter": "Job", "LabelCreate": "Label create", "LabelList": "Labels", "LabelUpdate": "Label update", diff --git a/src/i18n/langs/ja.json b/src/i18n/langs/ja.json index 73e09dd76..4e51d27b1 100644 --- a/src/i18n/langs/ja.json +++ b/src/i18n/langs/ja.json @@ -98,6 +98,10 @@ "NoSQLProtocol": "非リレーショナルデータベース" }, "assets": { + "SelectTemplate": "テンプレートの選択", + "InAssetDetail": "資産詳細でのアカウント情報の更新", + "SecretType": "機密タイプ", + "PrivilegedTemplate": "特権的", "All": "すべて", "CloudPlatform": "クラウドプラットフォーム", "RecentlyUsed": "最近使われる", @@ -321,6 +325,7 @@ "actionsTips": "クリップボード権限制御は現在RDP/VNCプロトコルの接続のみをサポートしています", "TableColSettingInfo": "表示したいリストの詳細を選択してください。", "Add": "追加", + "TemplateAdd": "テンプレートの追加", "UpdateAssetDetail": "詳細情報の設定", "AddSuccessMsg": "追加に成功しました", "Auth": "認証", @@ -721,6 +726,9 @@ "TicketFlowUpdate": "承認フローの更新", "Accounts": "アカウント管理", "AssetAccount": "資産アカウント", + "AccountTemplate": "アカウントテンプレート", + "CreateAccountTemplate": "アカウントテンプレートの作成", + "UpdateAccountTemplate": "アカウントテンプレートの更新", "AssetHistoryAccount": "資産履歴", "ApplicationAccount": "アプリアカウント", "Ticket": "ワークオーダー", @@ -748,7 +756,7 @@ "TicketsTodo": "To-doオーダー", "TicketsDone": "すでに勤務単", "TicketsNew": "ワークオーダーを提出する", - "BatchCommandLog": "一括コマンド", + "tasksLog": "一括コマンド", "CeleryTaskLog": "Celeryタスクログ", "CommandExecutions": "コマンド実行", "CommandFilterCreate": "コマンドフィルタの作成", diff --git a/src/i18n/langs/zh.json b/src/i18n/langs/zh.json index 6afebb901..15c252b4b 100644 --- a/src/i18n/langs/zh.json +++ b/src/i18n/langs/zh.json @@ -98,6 +98,10 @@ "NoSQLProtocol": "非关系数据库" }, "assets": { + "SelectTemplate": "选择模版", + "InAssetDetail": "在资产详情中更新账号信息", + "SecretType": "密文类型", + "PrivilegedTemplate": "特权的", "InitialDeploy": "初始化部署", "Address": "地址", "PrivateKey": "密钥", @@ -330,6 +334,7 @@ "actionsTips": "剪切板权限控制目前仅支持 RDP/VNC 协议的连接", "TableColSettingInfo": "请选择您想显示的列表详细信息。", "Add": "添加", + "TemplateAdd": "模版添加", "UpdateAssetDetail": "配置更多信息", "AddSuccessMsg": "添加成功", "Auth": "认证", @@ -739,6 +744,9 @@ "TicketFlowUpdate": "更新审批流", "Accounts": "账号管理", "AssetAccount": "资产账号", + "AccountTemplate": "账号模版", + "CreateAccountTemplate": "创建账号模版", + "UpdateAccountTemplate": "更新账号模版", "AssetHistoryAccount": "资产历史账号", "ApplicationAccount": "应用账号", "Ticket": "工单", @@ -768,10 +776,11 @@ "LogsAudit": "日志审计", "SessionList": "会话记录", "BatchCommand": "批量命令", + "BatchScript": "批量脚本", "TicketsTodo": "待办工单", "TicketsDone": "已办工单", "TicketsNew": "提交工单", - "BatchCommandLog": "批量命令", + "tasksLog": "批量命令", "CeleryTaskLog": "Celery任务日志", "CommandExecutions": "命令执行", "CommandFilterCreate": "创建命令过滤器", @@ -822,6 +831,7 @@ "FtpLog": "FTP日志", "GatewayCreate": "创建网关", "GatewayUpdate": "更新网关", + "TaskCenter": "任务中心", "JobCenter": "作业中心", "LabelCreate": "创建标签", "LabelList": "标签管理", diff --git a/src/router/audit/logs.js b/src/router/audit/logs.js index d4ae0c2ee..aa127c6a5 100644 --- a/src/router/audit/logs.js +++ b/src/router/audit/logs.js @@ -30,10 +30,10 @@ export default [ }, { path: 'command-execution-log', - name: 'BatchCommandLog', + name: 'tasksLog', component: () => import('@/views/audits/CommandExecutionList'), meta: { - title: i18n.t('route.BatchCommandLog'), + title: i18n.t('route.tasksLog'), permissions: ['ops.view_commandexecution'] } } diff --git a/src/router/common.js b/src/router/common.js index 208bc277d..1e781f366 100644 --- a/src/router/common.js +++ b/src/router/common.js @@ -7,7 +7,7 @@ import i18n from '@/i18n/i18n' export default [ { path: '/ops/celery/task/:id/log/', - component: () => import('@/views/ops/CeleryTaskLog'), + component: () => import('@/views/tasks/CeleryTaskLog'), name: 'CeleryTaskLog', hidden: true, meta: { @@ -17,7 +17,7 @@ export default [ }, { path: '/ops/task/task/:id/log/', - component: () => import('@/views/ops/CeleryTaskLog'), + component: () => import('@/views/tasks/CeleryTaskLog'), name: 'TaskLog', hidden: true, meta: { diff --git a/src/router/console/accounts.js b/src/router/console/accounts.js index a2eeab4d0..7d5c72f5e 100644 --- a/src/router/console/accounts.js +++ b/src/router/console/accounts.js @@ -34,6 +34,54 @@ export default [ } ] }, + { + path: 'account-template', + component: empty, + meta: { + title: i18n.t('route.AccountTemplate'), + app: 'assets', + permissions: ['assets.view_accounttemplate'] + }, + redirect: '', + children: [ + { + path: '', + name: 'AccountTemplateList', + component: () => import('@/views/accounts/AccountTemplate/AccountTemplateList'), + meta: { + title: i18n.t('route.AccountTemplate'), + permissions: ['assets.view_accounttemplate'] + } + }, + { + path: 'create', + component: () => import('@/views/accounts/AccountTemplate/AccountTemplateCreateUpdate.vue'), + name: 'AccountTemplateCreate', + meta: { + title: i18n.t('route.CreateAccountTemplate'), + action: 'create' + }, + hidden: true + }, + { + path: ':id/update', + component: () => import('@/views/accounts/AccountTemplate/AccountTemplateCreateUpdate.vue'), + name: 'AccountTemplateUpdate', + meta: { + title: i18n.t('route.UpdateAccountTemplate'), + action: 'update' + }, + hidden: true + }, + { + path: ':id', + component: () => import('@/views/accounts/AccountTemplate/AccountTemplateDetail/index.vue'), + name: 'AccountTemplateDetail', + meta: { title: i18n.t('route.AccountTemplate') }, + hidden: true + } + ] + }, { path: 'gathered-user', component: empty, diff --git a/src/router/console/index.js b/src/router/console/index.js index fe143b9d2..823c01eb1 100644 --- a/src/router/console/index.js +++ b/src/router/console/index.js @@ -6,7 +6,7 @@ import store from '@/store' import UsersRoute from './users' import AssetsRoute from './assets' import PermsRoute from './perms' -import OpsRoutes from './ops' +import TaskRoutes from './tasks' import AclRoutes from './acls' import AccountRoutes from './accounts' @@ -88,14 +88,14 @@ export default { children: AclRoutes }, { - path: '/console/ops', + path: '/console/tasks', component: empty, - name: 'JobCenter', + name: 'TaskCenter', meta: { - title: i18n.t('route.JobCenter'), - icon: 'coffee' + title: i18n.t('route.TaskCenter'), + icon: 'tasks' }, - children: OpsRoutes + children: TaskRoutes } ] } diff --git a/src/router/console/ops.js b/src/router/console/ops.js deleted file mode 100644 index c6cbab122..000000000 --- a/src/router/console/ops.js +++ /dev/null @@ -1,64 +0,0 @@ -import i18n from '@/i18n/i18n' -import { BASE_URL } from '@/utils/common' -import empty from '@/layout/empty' - -export default [ - { - path: 'tasks', - component: empty, - meta: { title: i18n.t('route.TaskList') }, - children: [ - { - path: '', - name: 'TaskList', - component: () => import('@/views/ops/TaskList'), - meta: { title: i18n.t('route.TaskList'), permissions: [] } - }, - { - path: ':id', - component: () => import('@/views/ops/TaskDetail'), - name: 'TaskDetail', - hidden: true, - meta: { title: i18n.t('route.TaskDetail'), permissions: [] } - } - ] - }, - { - path: 'adhoc/:id', - component: () => import('@/views/ops/TaskDetail/AdhocDetail'), - name: 'AdhocDetail', - hidden: true, - meta: { - title: i18n.t('route.TaskDetail'), - permissions: ['ops.view_adhoc'], - activeMenu: '/ops/tasks' - } - }, - { - path: 'executions/:id', - component: () => import('@/views/ops/TaskDetail/HistoryExecutionDetail'), - name: 'HistoryExecutionDetail', - hidden: true, - meta: { - title: i18n.t('route.TaskDetail'), - permissions: ['ops.view_adhocexecution'], - activeMenu: '/console/ops/tasks' - } - }, - { - path: 'command-executions/create', - name: 'BatchCommand', - component: () => import('@/views/ops/CommandExecution'), - meta: { - title: i18n.t('route.BatchCommand'), - permissions: ['ops.add_adhocexecution'], - hidden: ({ settings }) => !settings['SECURITY_COMMAND_EXECUTION'] - } - }, - { - path: `${BASE_URL}/core/flower/?_=${Date.now()}`, - name: 'TaskMonitor', - // component: () => window.open(`/core/flower?_=${Date.now()}`), - meta: { title: i18n.t('route.TaskMonitor'), permissions: ['ops.view_taskmonitor'] } - } -] diff --git a/src/router/console/tasks.js b/src/router/console/tasks.js new file mode 100644 index 000000000..a2bf48290 --- /dev/null +++ b/src/router/console/tasks.js @@ -0,0 +1,32 @@ +import i18n from '@/i18n/i18n' +import { BASE_URL } from '@/utils/common' +import empty from '@/layout/empty' + +export default [ + { + path: 'tasks', + component: empty, + meta: { title: i18n.t('route.TaskList') }, + children: [ + { + path: '', + name: 'TaskList', + component: () => import('@/views/tasks/TaskList'), + meta: { title: i18n.t('route.TaskList'), permissions: [] } + }, + { + path: ':id', + component: () => import('@/views/tasks/TaskDetail'), + name: 'TaskDetail', + hidden: true, + meta: { title: i18n.t('route.TaskDetail'), permissions: [] } + } + ] + }, + { + path: `${BASE_URL}/core/flower/?_=${Date.now()}`, + name: 'TaskMonitor', + // component: () => window.open(`/core/flower?_=${Date.now()}`), + meta: { title: i18n.t('route.TaskMonitor'), permissions: ['ops.view_taskmonitor'] } + } +] diff --git a/src/router/workbench/index.js b/src/router/workbench/index.js index e4d64545d..a7f0741aa 100644 --- a/src/router/workbench/index.js +++ b/src/router/workbench/index.js @@ -42,26 +42,7 @@ export default { permissions: ['perms.view_myassets'] } }, - { - path: '/workbench/ops', - component: empty, - meta: { - permissions: ['ops.add_commandexecution'], - hidden: ({ settings }) => !settings['SECURITY_COMMAND_EXECUTION'] - }, - children: [ - { - path: '', - name: 'CommandExecutions', - component: () => import('@/views/ops/CommandExecution'), - meta: { - title: i18n.t('route.BatchCommand'), - icon: 'terminal', - permissions: ['ops.add_commandexecution'] - } - } - ] - }, + { path: `external-luna`, component: empty, @@ -97,6 +78,38 @@ export default { } } ] + }, + { + path: '/workbench/ops', + component: empty, + name: 'JobCenter', + meta: { + title: i18n.t('route.JobCenter'), + icon: 'coffee', + permissions: [] + }, + children: [ + { + path: 'a', + name: 'CommandExecutions2', + component: () => import('@/views/ops/Command'), + meta: { + title: i18n.t('route.BatchCommand'), + icon: 'terminal', + permissions: [] + } + }, + { + path: '', + name: 'CommandExecutions', + component: () => import('@/views/ops/Command'), + meta: { + title: i18n.t('route.BatchScript'), + icon: 'book', + permissions: [] + } + } + ] } ] } diff --git a/src/views/accounts/AccountTemplate/AccountTemplateCreateUpdate.vue b/src/views/accounts/AccountTemplate/AccountTemplateCreateUpdate.vue new file mode 100644 index 000000000..e19b5286a --- /dev/null +++ b/src/views/accounts/AccountTemplate/AccountTemplateCreateUpdate.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/views/accounts/AccountTemplate/AccountTemplateDetail/Detail.vue b/src/views/accounts/AccountTemplate/AccountTemplateDetail/Detail.vue new file mode 100644 index 000000000..23f55bea9 --- /dev/null +++ b/src/views/accounts/AccountTemplate/AccountTemplateDetail/Detail.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/views/accounts/AccountTemplate/AccountTemplateDetail/index.vue b/src/views/accounts/AccountTemplate/AccountTemplateDetail/index.vue new file mode 100644 index 000000000..034698181 --- /dev/null +++ b/src/views/accounts/AccountTemplate/AccountTemplateDetail/index.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/views/accounts/AccountTemplate/AccountTemplateList.vue b/src/views/accounts/AccountTemplate/AccountTemplateList.vue new file mode 100644 index 000000000..0e43de0e7 --- /dev/null +++ b/src/views/accounts/AccountTemplate/AccountTemplateList.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/views/acl/UserLoginACL/UserDetail/Detail.vue b/src/views/acl/UserLoginACL/UserDetail/Detail.vue index c2c9c69b3..4256d9f97 100644 --- a/src/views/acl/UserLoginACL/UserDetail/Detail.vue +++ b/src/views/acl/UserLoginACL/UserDetail/Detail.vue @@ -55,7 +55,7 @@ export default { quickActions: [ { title: this.$t('common.Active'), - type: 'switcher', + type: 'switch', attrs: { model: this.object.is_active }, diff --git a/src/views/assets/Asset/AssetCreateUpdate/BaseAssetCreateUpdate.vue b/src/views/assets/Asset/AssetCreateUpdate/BaseAssetCreateUpdate.vue index 604b8f4fb..17f1cb421 100644 --- a/src/views/assets/Asset/AssetCreateUpdate/BaseAssetCreateUpdate.vue +++ b/src/views/assets/Asset/AssetCreateUpdate/BaseAssetCreateUpdate.vue @@ -50,7 +50,13 @@ export default { [this.$t('assets.Label'), ['labels']], [this.$t('common.Other'), ['is_active', 'comment']] ], - fieldsMeta: assetFieldsMeta(this) + fieldsMeta: assetFieldsMeta(this), + cleanFormValue(values) { + const { id = '' } = this.$route.params + if (id) delete values['accounts'] + + return values + } } } }, diff --git a/src/views/assets/Asset/AssetCreateUpdate/components/AccountTemplateDialog.vue b/src/views/assets/Asset/AssetCreateUpdate/components/AccountTemplateDialog.vue index 5feb8c747..793fe2f0c 100644 --- a/src/views/assets/Asset/AssetCreateUpdate/components/AccountTemplateDialog.vue +++ b/src/views/assets/Asset/AssetCreateUpdate/components/AccountTemplateDialog.vue @@ -1,12 +1,27 @@ @@ -20,19 +35,82 @@ export default { AutoDataTable }, props: { + visible: { + type: Boolean, + default: false + }, + accounts: { + type: Array, + default: () => ([]) + } }, data() { return { + accountsSelected: [], tableConfig: { url: '/api/v1/assets/account-templates/', - columns: ['name', 'username', 'privileged', 'actions'], + columns: ['name', 'username', 'privileged'], columnsMeta: { privileged: { width: '100px' } + }, + listeners: { + 'toggle-row-selection': (isSelected, row) => { + if (isSelected) { + this.addRowToSelect(row) + } else { + this.removeRowToSelect(row) + } + } + }, + theRowDefaultIsSelected: (row) => { + return this.accounts.some((account) => { + return account.id === row.id + }) } } } + }, + computed: { + iVisible: { + get() { + return this.visible + }, + set(val) { + this.$emit('update:visible', val) + } + } + }, + methods: { + handleConfirm() { + this.iVisible = false + // 过滤掉添加里还没有id的账号 + const hasIdAccounts = this.accounts.filter(i => i?.id) + const data = _.xorBy(hasIdAccounts, this.accountsSelected, 'id') + this.accounts.push(...data) + }, + handleCancel() { + this.iVisible = false + }, + onAddClick() { + this.$router.push({ name: 'AccountTemplateList' }) + }, + hasSelectValue(row) { + return this.accountsSelected.some(item => item.id === row.id) + }, + addRowToSelect(row) { + const hasSelectValue = this.hasSelectValue(row) + if (!hasSelectValue) { + this.accountsSelected.push(row) + } + }, + removeRowToSelect(row) { + const hasSelectValue = this.hasSelectValue(row) + if (hasSelectValue) { + this.accountsSelected.splice(hasSelectValue, 1) + } + } } } diff --git a/src/views/assets/Asset/AssetCreateUpdate/components/AddAccountDialog.vue b/src/views/assets/Asset/AssetCreateUpdate/components/AddAccountDialog.vue index 2153cd426..e998333e7 100644 --- a/src/views/assets/Asset/AssetCreateUpdate/components/AddAccountDialog.vue +++ b/src/views/assets/Asset/AssetCreateUpdate/components/AddAccountDialog.vue @@ -1,8 +1,8 @@