merge: with dev

This commit is contained in:
ibuler 2023-10-13 17:06:01 +08:00
commit f8ec2bce0c
16 changed files with 130 additions and 115 deletions

View File

@ -116,6 +116,8 @@
"AccountExportTips": "The exported information contains account secret, which involves sensitive information. The exported format is an encrypted zip file (if no encryption password is set, please go to personal information to set the file encryption password).",
"TaskID": "Task ID",
"AccountTemplate": "Account template",
"Sync": "Sync",
"SyncUpdateAccountInfo": "Sync update account info",
"AddAccountResult": "Add account result",
"AutoPush": "Auto Push",
"GeneralAccounts": "General Accounts",
@ -228,6 +230,7 @@
"NoSQLProtocol": "NoSQL Protocol"
},
"assets": {
"SyncProtocolToAsset": "Sync protocol to asset",
"CommentHelpText": "Note: Note information will be hovered and displayed in the user authorization asset tree of Luna page, which can be viewed by ordinary users. Please do not fill in sensitive information.",
"BulkUpdatePlatformHelpText": "Only when the original platform type of the asset is the same as the selected platform type will it be updated, if the platform type before and after the update is different, it will not be updated.",
"ImportMessage": "Please go to the page of mapping type to import data",
@ -2311,5 +2314,10 @@
"applets": {
"PublishStatus": "Publish status",
"NoPublished": "Unpublished"
},
"profile": {
"CreateAccessKey": "Create Access key",
"ApiKeyWarning": "To reduce the risk of AccessKey exposure, Secret is provided only during creation and cannot be queried again later. Please keep it safe.",
"PasskeyAddDisableInfo": "Your authentication source is {source}, and Passkey addition is not supported."
}
}

View File

@ -116,6 +116,8 @@
"AccountExportTips": "エクスポート情報には機密情報を含むアカウント暗号文が含まれており、エクスポートされたフォーマットは暗号化されたzipファイルです暗号化パスワードが設定されていない場合は、個人情報にファイル暗号化パスワードを設定してください。",
"TaskID": "タスク ID",
"AccountTemplate": "账号模版",
"Sync": "同期",
"SyncUpdateAccountInfo": "アカウント情報の同期更新",
"AddAccountResult": "账号批量添加结果",
"AutoPush": "自動プッシュ",
"GeneralAccounts": "一般アカウント",
@ -228,6 +230,7 @@
"NoSQLProtocol": "非リレーショナルデータベース"
},
"assets": {
"SyncProtocolToAsset": "プロトコルをアセットに同期",
"CommentHelpText": "注意コメント情報はLunaページのユーザー認可資産ツリーに表示されます。一般ユーザーは表示できますので、機密情報を記入しないでください。",
"BulkUpdatePlatformHelpText": "アセットの元のプラットフォーム タイプが選択したプラットフォーム タイプと同じ場合にのみ更新され、更新の前後のプラットフォーム タイプが異なる場合は更新されません。",
"ImportMessage": "ミラータイプのページにデータをインポートしてください",
@ -1021,7 +1024,7 @@
"ratio": "スケール",
"run": "実行",
"runAs": "実行ユーザー",
"runningPath":"実行パス",
"runningPath": "実行パス",
"runTimes": "実行回数",
"selectAssetsMessage": "左側の資産を選択し、実行するシステムユーザーを選択し、コマンドを一括実行します",
"selectedAssets": "選択済アセット:",
@ -2302,5 +2305,10 @@
"applets": {
"PublishStatus": "投稿ステータス",
"NoPublished": "未発表"
},
"profile": {
"CreateAccessKey": "Create Access key",
"ApiKeyWarning": "AccessKeyの漏洩リスクを低減するため、Secretは作成時にのみ提供され、後で再度クエリできません。安全に保管してください。",
"PasskeyAddDisableInfo": "あなたの認証元は {source} であり、Passkeyの追加はサポートされていません。"
}
}

View File

@ -10,6 +10,8 @@
"GenerateSuccessMsg": "账号生成成功",
"GenerateAccounts": "重新生成账号",
"UpdateSecret": "更新密文",
"Sync": "同步",
"SyncUpdateAccountInfo": "同步更新账号信息",
"AddAccountResult": "账号批量添加结果",
"AccountPolicy": "账号策略",
"BulkCreateStrategy": "创建时对于不符合要求的账号,如:密钥类型不合规,唯一键约束,可选择以上策略。",
@ -228,6 +230,7 @@
},
"assets": {
"CustomType": "自定义类型",
"SyncProtocolToAsset": "同步协议到资产",
"CustomHelpMessage": "自定义类型资产,依赖于远程应用,请前往系统设置在远程应用中配置",
"CustomFields": "自定义属性",
"CommentHelpText": "注意:备注信息会在 Luna 页面的用户授权资产树中进行悬停显示,普通用户可以查看,请不要填写敏感信息。",
@ -1876,7 +1879,8 @@
},
"profile": {
"CreateAccessKey": "创建访问密钥",
"ApiKeyWarning": "为降低 AccessKey 泄露的风险,只在创建时提供 Secret后续不可再进行查询请妥善保存。"
"ApiKeyWarning": "为降低 AccessKey 泄露的风险,只在创建时提供 Secret后续不可再进行查询请妥善保存。",
"PasskeyAddDisableInfo": "你的认证来源是 {source}, 不支持添加 Passkey"
},
"users": {
"LunaSettingUpdate": "Luna 配置设置",

View File

@ -28,7 +28,7 @@
</template>
</el-tabs>
<transition appear mode="out-in" name="fade-transform">
<transition v-if="loading" appear mode="out-in" name="fade-transform">
<slot>
<keep-alive>
<component :is="computeActiveComponent" />
@ -60,6 +60,11 @@ export default {
required: true
}
},
data() {
return {
loading: true
}
},
computed: {
iActiveMenu: {
get() {
@ -90,6 +95,18 @@ export default {
return needActiveComponent
}
},
watch: {
$route(to, from) {
const activeTab = to.query?.activeTab
if (activeTab && this.iActiveMenu !== activeTab) {
this.iActiveMenu = activeTab
this.loading = false
setTimeout(() => {
this.loading = true
})
}
}
},
created() {
this.iActiveMenu = this.getPropActiveTab()
},

BIN
src/styles/icons/db2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

View File

@ -88,6 +88,9 @@
background: url('./icons/unix.png') no-repeat center left transparent;
}
&.db2_ico_docu {
background: url('./icons/db2.png') no-repeat center left transparent;
}
&.private_ico_docu {
background: url('./icons/private.png') no-repeat center left transparent;

View File

@ -14,6 +14,14 @@ export default {
},
data() {
const vm = this
const isUpdate = vm.$route.path.indexOf('/update') > -1 && vm.$route.params?.id
const formFields = templateFields(vm)
for (const [key, value] of formFields) {
if (key === vm.$t('assets.Secret')) {
isUpdate && value.push('is_sync_account')
}
}
return {
initial: {
secret_type: 'password',
@ -21,11 +29,28 @@ export default {
},
url: '/api/v1/accounts/account-templates/',
hasDetailInMsg: false,
fields: [
...templateFields(vm)
],
fields: formFields,
fieldsMeta: {
...templateFieldsMeta(vm)
...templateFieldsMeta(vm),
is_sync_account: {
label: this.$t('accounts.SyncUpdateAccountInfo'),
el: {
icon: 'fa fa-external-link',
type: 'primary',
size: 'mini'
},
component: 'el-button',
on: {
click: () => {
vm.$router.push({
name: 'AccountTemplateDetail',
query: {
activeTab: 'Account'
}
})
}
}
}
},
cleanFormValue(value) {
Object.keys(value).forEach((item, index, arr) => {
@ -35,6 +60,7 @@ export default {
}
})
value['secret'] = encryptPassword(value['secret'])
delete value.is_sync_account
return value
},
createSuccessNextRoute: { name: 'AccountTemplateList' },

View File

@ -20,10 +20,6 @@
:url="secretUrl"
:visible.sync="showViewSecretDialog"
/>
<AccountTemplateChangeSecretDialog
:object="object"
:visible.sync="visible"
/>
</el-row>
</div>
</template>
@ -31,17 +27,16 @@
<script>
import GenericListTable from '@/layout/components/GenericListTable'
import QuickActions from '@/components/QuickActions'
import AccountTemplateChangeSecretDialog from './AccountTemplateChangeSecretDialog'
import { ActionsFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
import ViewSecret from '@/components/Apps/AccountListTable/ViewSecret'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'AccountTemplateChangeSecret',
components: {
ViewSecret,
QuickActions,
GenericListTable,
AccountTemplateChangeSecretDialog
GenericListTable
},
props: {
object: {
@ -58,14 +53,18 @@ export default {
showViewSecretDialog: false,
quickActions: [
{
title: this.$t('accounts.UpdateSecret'),
title: this.$t('accounts.SyncUpdateAccountInfo'),
attrs: {
type: 'primary',
label: this.$t('common.Update')
label: this.$t('accounts.Sync')
},
callbacks: Object.freeze({
click: () => {
vm.visible = true
this.$axios.patch(
`/api/v1/accounts/account-templates/${this.object.id}/sync-related-accounts/`
).then(res => {
openTaskPage(res['task'])
})
}
})
}

View File

@ -1,93 +0,0 @@
<template>
<Dialog
v-if="iVisible"
:destroy-on-close="true"
:show-cancel="false"
:show-confirm="false"
:title="$tc('accounts.UpdateSecret')"
:visible.sync="iVisible"
width="50%"
>
<AutoDataForm
:form="form"
v-bind="config"
@submit="onSubmit"
/>
</Dialog>
</template>
<script>
import { AutoDataForm, Dialog } from '@/components'
import { templateFieldsMeta } from '../const.js'
import { encryptPassword } from '@/utils/crypto'
export default {
name: 'AccountTemplateChangeSecretDialog',
components: {
Dialog,
AutoDataForm
},
props: {
visible: {
type: Boolean,
default: false
},
object: {
type: Object,
default: null
}
},
data() {
return {
form: this.object,
secretType: this.object?.secret_type?.value,
config: {
hasSaveContinue: false,
url: '/api/v1/accounts/account-templates/',
fields: [
['', [
'secret_type', 'secret', 'ssh_key', 'token',
'access_key', 'passphrase', 'api_key'
]]
],
fieldsMeta: {
...templateFieldsMeta(this),
secret_type: {
disabled: true
}
}
}
}
},
computed: {
iVisible: {
get() {
return this.visible
},
set(val) {
this.$emit('update:visible', val)
}
}
},
methods: {
onSubmit(form) {
const { object, secretType } = this
const currentSecretType = secretType === 'password' ? form?.['secret'] : form?.[secretType]
const params = {
secret: currentSecretType ? encryptPassword(currentSecretType) : '',
is_sync_account: true,
...(secretType === 'ssh_key' && { passphrase: encryptPassword(form?.['passphrase']) })
}
this.$axios.patch(
`/api/v1/accounts/account-templates/${object.id}/`,
params
).then(() => {
this.$message.success(this.$tc('common.updateSuccessMsg'))
}).finally(() => {
this.iVisible = false
})
}
}
}
</script>

View File

@ -17,6 +17,9 @@ export default {
addFieldsMeta: this.getAddFieldsMeta()
}
},
mounted() {
this.url = `${this.url}?platform=${this.$route.query.platform}`
},
methods: {
getAddFields() {
const platform = this.$route.query.type

View File

@ -131,6 +131,22 @@ export default {
})
}
})
},
{
title: this.$t(`assets.SyncProtocolToAsset`),
attrs: {
type: 'primary',
label: this.$t('accounts.Sync')
},
callbacks: Object.freeze({
click: () => {
const data = { platform_id: this.object.id }
this.$axios.post(
'/api/v1/assets/assets/sync-platform-protocols/', data).then(res => {
this.$message.success(this.$tc('common.updateSuccessMsg'))
})
}
})
}
]
this.quickActions = quickActions

View File

@ -52,7 +52,7 @@ export default {
name: 'Expired',
title: this.$t('setting.Expire'),
type: 'info',
can: ({ row }) => !row['is_expired'] && this.$hasPerm('authentication.change_connectiontoken'),
can: ({ row }) => !row['is_expired'] && this.$hasPerm('authentication.expire_connectiontoken'),
callback: function({ row }) {
this.$axios.patch(`${ajaxUrl}${row.id}/expire/`,
).then(res => {

View File

@ -11,7 +11,10 @@
:visible.sync="dialogVisible"
width="600px"
>
<AutoDataForm v-bind="form" @submit="onAddConfirm" />
<el-alert v-if="!isLocalUser" :closable="false" class="source-alert" type="error">
{{ $t('profile.PasskeyAddDisableInfo', {source: source.label}) }}
</el-alert>
<AutoDataForm v-else v-bind="form" @submit="onAddConfirm" />
</Dialog>
</div>
</template>
@ -116,6 +119,12 @@ export default {
computed: {
getRefsListTable() {
return this.$refs.GenericListTable.$refs.ListTable.$refs.ListTable || {}
},
isLocalUser() {
return this.source?.value === 'local'
},
source() {
return this.$store.getters.currentUser?.source
}
},
methods: {
@ -153,5 +162,8 @@ export default {
}
</script>
<style scoped>
<style lang='scss' scoped>
.source-alert >>> .el-alert__content {
text-align: center;
}
</style>

View File

@ -26,7 +26,8 @@ export default {
},
{
title: this.$t('setting.Ticket'),
name: 'Ticket'
name: 'Ticket',
hidden: !this.$store.getters.hasValidLicense
},
{
title: this.$t('setting.AppOps'),

View File

@ -39,6 +39,17 @@ export default {
key: this.$t('acl.apply_login_account'),
value: object.apply_login_account
},
{
key: this.$t('tickets.ApplyFromSession'),
value: object.apply_from_session,
formatter: function(item, value) {
const to = { name: 'SessionDetail', params: { id: value?.id }, query: { oid: object.org_id }}
if (!this.$hasPerm('terminal.view_session')) {
return <span>{this.$t('sessions.session')}</span>
}
return <router-link to={to}>{this.$t('sessions.session')}</router-link>
}
},
{
key: this.$t('acl.apply_login_user'),
value: object.apply_login_user.name

View File

@ -181,7 +181,7 @@ export default {
key: this.$t('users.Phone'),
formatter: () => {
const phoneObj = this.object.phone
return <div>{phoneObj?.code}{phoneObj?.phone}</div>
return <div>{phoneObj?.code} {phoneObj?.phone}</div>
}
},
'wecom_id', 'dingtalk_id', 'feishu_id',