Merge branch 'v4' of github.com:jumpserver/lina into v4

This commit is contained in:
ibuler
2024-05-23 15:19:12 +08:00
31 changed files with 123 additions and 241 deletions

View File

@@ -245,6 +245,7 @@ $color-drop-menu-border: #e4e7ed;
// 主要是 Table 中的操作列
.layout.table-actions {
display: flex;
justify-content: center;
align-items: flex-end;
.el-button {

View File

@@ -239,7 +239,6 @@ export class FormFieldGenerator {
if (!label) {
return field
}
if (field.placeholder || field.el.placeholder) {
return field
}

View File

@@ -6,7 +6,7 @@
<div style="height: 100%">
<el-tabs
v-if="tabIndices.length > 0"
v-if="tabIndices.length > 1"
slot="submenu"
v-model="iActiveMenu"
class="page-submenu"

View File

@@ -24,7 +24,7 @@ export default {
name: 'Basic',
component: () => import('@/views/settings/Basic'),
meta: {
title: i18n.t('Basic'),
title: i18n.t('BasicSettings'),
icon: 'basic',
permissions: ['settings.view_setting']
}
@@ -414,7 +414,7 @@ export default {
path: '/settings/tasks',
component: empty,
meta: {
title: i18n.t('TaskList'),
title: i18n.t('SystemTasks'),
icon: 'tasks',
permissions: ['ops.view_celerytask']
},
@@ -424,7 +424,7 @@ export default {
name: 'TaskList',
component: () => import('@/views/settings/Task/index.vue'),
meta: {
title: i18n.t('TaskList'),
title: i18n.t('SystemTasks'),
permissions: ['ops.view_celerytask']
}
},

View File

@@ -53,11 +53,11 @@ export default {
}
},
{
path: 'batch-Transfer',
name: 'BatchTransfer',
path: 'file-transfer',
name: 'FileTransfer',
component: () => import('@/views/ops/File/index'),
meta: {
title: i18n.t('BatchTransfer'),
title: i18n.t('FileTransfer'),
permissions: ['rbac.view_filemanager']
}
},
@@ -86,8 +86,8 @@ export default {
},
children: [
{
path: 'quick-job',
name: 'QuickJob',
path: 'adhoc',
name: 'Adhoc',
component: () => import('@/views/ops/Job/QuickJob'),
meta: {
title: i18n.t('QuickJob'),

View File

@@ -1,12 +1,11 @@
<template>
<div>
<ExecutionDetailDialog v-if="showExecutionDetailDialog" :item="item" :visible.sync="showExecutionDetailDialog" />
<GenericListPage :header-actions="headerActions" :table-config="tableConfig" />
<GenericListPage ref="GenericListPage" :header-actions="headerActions" :table-config="tableConfig" />
</div>
</template>
<script>
import { ActionsFormatter } from '@/components/Table/TableFormatters'
import { GenericListPage } from '@/layout/components'
import { openTaskPage } from '@/utils/jms'
import ExecutionDetailDialog from '@/views/ops/Execution/ExecutionDetail'
@@ -23,62 +22,33 @@ export default {
showExecutionDetailDialog: false,
tableConfig: {
url: '/api/v1/ops/job-executions/',
columns: [
'id', 'job', 'material', 'job_type', 'is_finished', 'is_success',
'time_cost', 'date_created', 'actions'
],
columnsShow: {
min: ['material', 'actions'],
default: [
'id', 'job', 'material', 'job_type', 'is_success',
'id', 'job', 'material', 'job_type', 'is_finished', 'is_success',
'time_cost', 'date_created', 'actions'
]
},
columnsMeta: {
job_type: {
width: '100px'
},
id: {
width: '100px',
formatter(row) {
return row.id.slice(0, 8)
}
},
count: {
width: '96px',
formatter: (row) => {
if (row.count) {
return <div>
<el-tooltip open-delay='1000' content='success'><span Class='text-success'>{row.count.ok}&nbsp;</span></el-tooltip>
<el-tooltip open-delay='1000' content='failed'><span Class='text-danger'>&nbsp;{row.count.failed}&nbsp;</span>
</el-tooltip>
<el-tooltip open-delay='1000' content='exclude'><span Class='text-warning'>&nbsp;{row.count.excludes}&nbsp;</span>
</el-tooltip>
<el-tooltip open-delay='1000' content='total'><span Class='text-primary'>&nbsp;{row.count.total}</span></el-tooltip>
</div>
}
return '-'
}
},
job: {
formatter: (row) => {
return <span>{row.job?.name || '-'}</span>
}
},
is_finished: {
width: '96px',
formatter: (row) => {
if (row.is_finished) {
return <i Class='fa fa-check text-primary'/>
}
return <i Class='fa fa-times text-danger'/>
},
formatterArgs: {
width: '14px'
}
},
is_success: {
width: '96px',
formatter: (row) => {
if (!row.is_finished) {
return <i Class='fa fa fa-spinner fa-spin'/>
@@ -87,13 +57,9 @@ export default {
return <i Class='fa fa-check text-primary'/>
}
return <i Class='fa fa-times text-danger'/>
},
formatterArgs: {
width: '14px'
}
},
time_cost: {
width: '100px',
formatter: function(row) {
if (row.time_cost) {
return row.time_cost.toFixed(2) + 's'
@@ -102,7 +68,7 @@ export default {
}
},
actions: {
formatter: ActionsFormatter,
width: '120px',
formatterArgs: {
hasUpdate: false,
hasDelete: false,

View File

@@ -137,7 +137,7 @@ import { formatFileSize } from '@/utils/common'
import store from '@/store'
export default {
name: 'BatchTransfer',
name: 'FileTransfer',
components: {
AssetTreeTable,
Page,

View File

@@ -283,4 +283,20 @@ export default {
font-size: 12px;
color: #999999;
}
::v-deep .el-checkbox-group {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
::v-deep .el-checkbox-group label:nth-child(1),
::v-deep .el-checkbox-group label:nth-child(2) {
grid-row: 1 / 2;
}
::v-deep .el-checkbox-group label:nth-child(3),
::v-deep .el-checkbox-group label:nth-child(4),
::v-deep .el-checkbox-group label:nth-child(5) {
grid-row: 2 / 3;
}
</style>

View File

@@ -17,14 +17,14 @@ export default {
return {
url: '/api/v1/settings/setting/?category=auth',
fields: [
[
this.$t('Basic'),
[
'FORGOT_PASSWORD_URL', 'LOGIN_REDIRECT_MSG_ENABLED'
]
]
'EMAIL_SUFFIX', 'FORGOT_PASSWORD_URL', 'LOGIN_REDIRECT_MSG_ENABLED'
],
fieldsMeta: {
FORGOT_PASSWORD_URL: {
el: {
placeholder: this.$t('ForgotPasswordURL')
}
}
},
submitMethod() {
return 'patch'

View File

@@ -24,8 +24,11 @@ export default {
[this.$t('Basic'), [
'AUTH_CAS', 'CAS_SERVER_URL', 'CAS_ROOT_PROXIED_AS', 'CAS_VERSION'
]],
[this.$t('Search'), [
'CAS_RENAME_ATTRIBUTES'
]],
[this.$t('Other'), [
'CAS_LOGOUT_COMPLETELY', 'CAS_RENAME_ATTRIBUTES', 'CAS_CREATE_USER'
'CAS_CREATE_USER', 'CAS_LOGOUT_COMPLETELY'
]]
],
fieldsMeta: {

View File

@@ -39,7 +39,7 @@ export default {
]
],
[
this.$t('LDAPUser'),
this.$t('Search'),
[
'AUTH_LDAP_SEARCH_OU', 'AUTH_LDAP_SEARCH_FILTER',
'AUTH_LDAP_USER_ATTR_MAP'

View File

@@ -26,7 +26,7 @@ export default {
'AUTH_OPENID', 'BASE_SITE_URL', 'AUTH_OPENID_CLIENT_ID',
'AUTH_OPENID_CLIENT_SECRET', 'AUTH_OPENID_CLIENT_AUTH_METHOD'
]],
[this.$t('Params'), [
[this.$t('Server'), [
'AUTH_OPENID_KEYCLOAK', 'AUTH_OPENID_SERVER_URL', 'AUTH_OPENID_REALM_NAME',
'AUTH_OPENID_PROVIDER_ENDPOINT', 'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT',
'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT', 'AUTH_OPENID_PROVIDER_JWKS_ENDPOINT',
@@ -35,7 +35,10 @@ export default {
'AUTH_OPENID_PKCE', 'AUTH_OPENID_CODE_CHALLENGE_METHOD',
'AUTH_OPENID_SCOPES', 'AUTH_OPENID_ID_TOKEN_MAX_AGE', 'AUTH_OPENID_ID_TOKEN_INCLUDE_CLAIMS',
'AUTH_OPENID_USE_STATE', 'AUTH_OPENID_USE_NONCE', 'AUTH_OPENID_ALWAYS_UPDATE_USER',
'AUTH_OPENID_IGNORE_SSL_VERIFICATION', 'AUTH_OPENID_SHARE_SESSION', 'AUTH_OPENID_USER_ATTR_MAP'
'AUTH_OPENID_IGNORE_SSL_VERIFICATION', 'AUTH_OPENID_SHARE_SESSION'
]],
[this.$t('Search'), [
'AUTH_OPENID_USER_ATTR_MAP'
]]
],
fieldsMeta: {

View File

@@ -20,12 +20,7 @@ export default {
url: '/api/v1/settings/setting/?category=passkey',
hasDetailInMsg: false,
fields: [
[
this.$t('BasicInfo'),
[
'AUTH_PASSKEY', 'FIDO_SERVER_ID', 'FIDO_SERVER_NAME'
]
]
'AUTH_PASSKEY', 'FIDO_SERVER_ID', 'FIDO_SERVER_NAME'
],
fieldsMeta: {
},

View File

@@ -24,25 +24,13 @@ export default {
data() {
return {
fields: [
[
this.$t('BasicInfo'), [
'SITE_URL' // 'USER_GUIDE_URL',
]
],
[this.$t('NavHelp'), [
'HELP_DOCUMENT_URL', 'HELP_SUPPORT_URL'
]]
[this.$t('Basic'), ['SITE_URL']], // 'USER_GUIDE_URL',]
[this.$t('Navigation'), ['HELP_DOCUMENT_URL', 'HELP_SUPPORT_URL']]
],
fieldsMeta: {
SITE_URL: {
rules: [rules.Required]
},
HELP_DOCUMENT_URL: {
helpText: this.$t('HelpDocumentTip')
},
HELP_SUPPORT_URL: {
helpText: this.$t('HelpSupportTip')
rules: [rules.Required],
helpText: this.$t('SiteURLTip')
}
},
successUrl: { name: 'Basic' },

View File

@@ -50,8 +50,7 @@ export default {
GPT_BASE_URL: {
el: {
autocomplete: 'new-password'
},
helpText: this.$t('Example', { example: 'https://api.openai.com/v1' })
}
},
GPT_API_KEY: {
el: {
@@ -59,7 +58,6 @@ export default {
}
},
GPT_PROXY: {
helpText: this.$t('Example', { example: 'http://ip:port' })
}
},
submitMethod() {

View File

@@ -60,7 +60,7 @@ export default {
],
encryptedFields: ['VAULT_HCP_TOKEN'],
fields: [
[this.$t('Storage'),
[this.$t('Backend'),
[
'VAULT_ENABLED',
'VAULT_HCP_HOST',
@@ -68,7 +68,7 @@ export default {
'VAULT_HCP_MOUNT_POINT'
]
],
[this.$t('HistoryRecord'), ['HISTORY_ACCOUNT_CLEAN_LIMIT']]
[this.$t('History'), ['HISTORY_ACCOUNT_CLEAN_LIMIT']]
],
fieldsMeta: {
HISTORY_ACCOUNT_CLEAN_LIMIT: {

View File

@@ -46,7 +46,7 @@ export default {
hidden: !this.$hasPerm('settings.change_vault')
},
{
title: this.$t('VirtualApp'),
title: this.$t('VirtualApps'),
name: 'VirtualApp',
hidden: !this.$hasPerm('settings.change_virtualapp') || !this.$store.getters.hasValidLicense
}

View File

@@ -1,11 +1,11 @@
<template>
<div>
<el-button size="mini" type="primary" @click="visible = !visible"> {{ $t("Setting") }} </el-button>
<el-button size="mini" type="primary" icon="el-icon-setting" @click="visible = !visible"> {{ $t("Settings...") }} </el-button>
<Dialog
v-if="visible"
:show-cancel="false"
:show-confirm="false"
:title="$tc('CreateUserSetting')"
:title="$tc('Template')"
:visible.sync="visible"
width="70%"
@confirm="onConfirm()"
@@ -21,7 +21,7 @@ import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm
import { Dialog } from '@/components'
export default {
name: 'EmailContent',
name: 'EmailTemplate',
components: {
GenericCreateUpdateForm,
Dialog
@@ -30,8 +30,12 @@ export default {
return {
visible: false,
fields: [
'EMAIL_CUSTOM_USER_CREATED_SUBJECT', 'EMAIL_CUSTOM_USER_CREATED_HONORIFIC',
'EMAIL_CUSTOM_USER_CREATED_BODY'
[this.$t('General'), ['EMAIL_SUBJECT_PREFIX']],
[this.$t('User creation'),
[
'EMAIL_CUSTOM_USER_CREATED_SUBJECT', 'EMAIL_CUSTOM_USER_CREATED_HONORIFIC', 'EMAIL_CUSTOM_USER_CREATED_BODY'
]
]
],
successUrl: { name: 'Settings', params: { activeMenu: 'EmailContent' }},
fieldsMeta: {

View File

@@ -1,94 +0,0 @@
<template>
<div>
<el-button size="mini" type="primary" @click="visible = !visible"> {{ $t("Setting") }} </el-button>
<Dialog
v-if="visible"
:destroy-on-close="true"
:show-cancel="false"
:show-confirm="false"
:title="$tc('SMTP')"
:visible.sync="visible"
width="70%"
@confirm="onConfirm()"
>
<GenericCreateUpdateForm v-bind="$data" />
</Dialog>
</div>
</template>
<script>
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm/index.vue'
import { Dialog } from '@/components'
import { UpdateToken } from '@/components/Form/FormFields'
export default {
name: 'SMTP',
components: {
GenericCreateUpdateForm,
Dialog
},
data() {
return {
visible: false,
encryptedFields: ['EMAIL_HOST_PASSWORD'],
fields: [
[
this.$t('BasicInfo'),
[
'EMAIL_PROTOCOL', 'EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_HOST_USER',
'EMAIL_HOST_PASSWORD', 'EMAIL_USE_SSL', 'EMAIL_USE_TLS'
]
]
],
successUrl: { name: 'Settings', params: { activeMenu: 'EmailContent' }},
fieldsMeta: {
EMAIL_PORT: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
},
EMAIL_HOST_PASSWORD: {
component: UpdateToken
},
'EMAIL_CUSTOM_USER_CREATED_BODY': {
el: {
type: 'textarea',
rows: 3
}
},
EMAIL_USE_SSL: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
},
EMAIL_USE_TLS: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
}
},
url: '/api/v1/settings/setting/?category=email',
submitMethod() {
return 'patch'
},
onConfirm() {
},
cleanFormValue(data) {
if (!data['EMAIL_HOST_PASSWORD']) {
delete data['EMAIL_HOST_PASSWORD']
}
if (data['EMAIL_USE_SSL'] === null) {
delete data['EMAIL_USE_SSL']
}
if (data['EMAIL_USE_TLS'] === null) {
delete data['EMAIL_USE_TLS']
}
if (data['EMAIL_PORT'] === null) {
delete data['EMAIL_PORT']
}
return data
}
}
},
methods: {}
}
</script>
<style scoped>
</style>

View File

@@ -6,15 +6,14 @@
v-bind="$data"
/>
</IBox>
</template>
<script>
import { IBox } from '@/components'
import { GenericCreateUpdateForm } from '@/layout/components'
import { testEmailSetting } from '@/api/settings'
import EmailContent from './EmailContent.vue'
import SMTP from './SMTP.vue'
import EmailTemplate from './EmailTemplate.vue'
import { UpdateToken } from '@/components/Form/FormFields'
import rules from '@/components/Form/DataForm/rules'
export default {
@@ -26,39 +25,41 @@ export default {
data() {
const vm = this
return {
encryptedFields: ['EMAIL_HOST_PASSWORD'],
fields: [
[
this.$t('Server'),
[
'SMTP'
]
],
[
this.$t('MailSend'),
[
'EMAIL_FROM', 'EMAIL_SUBJECT_PREFIX'
]
],
[
this.$t('EmailContent'),
[
'CREATE_USER_MSG'
]
],
[
this.$t('Other'),
[
'EMAIL_RECIPIENT', 'EMAIL_SUFFIX'
]
[this.$t('Server'), [
'EMAIL_PROTOCOL',
'EMAIL_HOST',
'EMAIL_PORT',
'EMAIL_HOST_USER',
'EMAIL_HOST_PASSWORD',
'EMAIL_FROM',
'EMAIL_USE_SSL',
'EMAIL_USE_TLS'
]
],
[this.$t('Other'), ['CREATE_USER_MSG']],
[this.$t('Test'), ['EMAIL_RECIPIENT']]
],
fieldsMeta: {
EMAIL_PORT: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
},
EMAIL_HOST_PASSWORD: {
component: UpdateToken
},
EMAIL_HOST_USER: {
rules: [
rules.EmailCheck,
rules.Required
]
},
EMAIL_CUSTOM_USER_CREATED_BODY: {
el: {
type: 'textarea',
rows: 3
}
},
EMAIL_FROM: {
rules: [
rules.EmailCheck
@@ -69,13 +70,16 @@ export default {
rules.EmailCheck
]
},
CREATE_USER_MSG: {
label: this.$t('CreateUserSetting'),
component: EmailContent
EMAIL_USE_SSL: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
},
SMTP: {
label: this.$t('SMTP'),
component: SMTP
EMAIL_USE_TLS: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
},
CREATE_USER_MSG: {
label: this.$t('EmailTemplate'),
component: EmailTemplate,
helpTip: this.$t('EmailTemplateHelpTip')
}
},
hasDetailInMsg: false,
@@ -104,6 +108,9 @@ export default {
if (data[key] === null) {
delete data[key]
}
if (!data['EMAIL_HOST_PASSWORD']) {
delete data['EMAIL_HOST_PASSWORD']
}
}
)
return data

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-button size="mini" type="primary" @click="visible=true">{{ $t('Setting') }}</el-button>
<el-button size="mini" type="primary" icon="el-icon-setting" @click="visible=true">{{ $t('Settings...') }}</el-button>
<Dialog
v-if="visible"
:destroy-on-close="true"

View File

@@ -39,14 +39,14 @@ export default {
],
fields: [
[
this.$t('BasicInfo'),
this.$t('Basic'),
[
'CMPP2_HOST', 'CMPP2_PORT', 'CMPP2_SP_ID', 'CMPP2_SP_SECRET', 'CMPP2_SRC_ID', 'CMPP2_SERVICE_ID',
'CMPP2_VERIFY_SIGN_NAME', 'CMPP2_VERIFY_TEMPLATE_CODE'
]
],
[
this.$t('Other'),
this.$t('Test'),
[
'SMS_TEST_PHONE'
]

View File

@@ -37,19 +37,19 @@ export default {
],
fields: [
[
this.$t('BasicInfo'),
this.$t('Basic'),
[
'ALIBABA_ACCESS_KEY_ID', 'ALIBABA_ACCESS_KEY_SECRET'
]
],
[
this.$t('VerifySignTmpl'),
this.$t('Template'),
[
'ALIBABA_VERIFY_SIGN_NAME', 'ALIBABA_VERIFY_TEMPLATE_CODE'
]
],
[
this.$t('Other'),
this.$t('Test'),
[
'SMS_TEST_PHONE'
]

View File

@@ -37,13 +37,13 @@ export default {
],
fields: [
[
this.$t('BasicInfo'),
this.$t('Basic'),
[
'CUSTOM_SMS_URL', 'CUSTOM_SMS_REQUEST_METHOD', 'CUSTOM_SMS_API_PARAMS'
]
],
[
this.$t('Other'),
this.$t('Test'),
[
'SMS_TEST_PHONE'
]

View File

@@ -41,7 +41,7 @@ export default {
],
fields: [
[
this.$t('Other'),
this.$t('Test'),
[
'SMS_TEST_PHONE'
]

View File

@@ -39,19 +39,19 @@ export default {
],
fields: [
[
this.$t('BasicInfo'),
this.$t('Basic'),
[
'HUAWEI_APP_KEY', 'HUAWEI_APP_SECRET', 'HUAWEI_SMS_ENDPOINT'
]
],
[
this.$t('VerifySignTmpl'),
this.$t('Template'),
[
'HUAWEI_SIGN_CHANNEL_NUM', 'HUAWEI_VERIFY_SIGN_NAME', 'HUAWEI_VERIFY_TEMPLATE_CODE'
]
],
[
this.$t('Other'),
this.$t('Test'),
[
'SMS_TEST_PHONE'
]

View File

@@ -37,19 +37,19 @@ export default {
],
fields: [
[
this.$t('BasicInfo'),
this.$t('Basic'),
[
'TENCENT_SECRET_ID', 'TENCENT_SECRET_KEY', 'TENCENT_SDKAPPID'
]
],
[
this.$t('VerifySignTmpl'),
this.$t('Template'),
[
'TENCENT_VERIFY_SIGN_NAME', 'TENCENT_VERIFY_TEMPLATE_CODE'
]
],
[
this.$t('Other'),
this.$t('Test'),
[
'SMS_TEST_PHONE'
]

View File

@@ -30,7 +30,7 @@ export default {
]
],
[
this.$t('SMSProvider'), [
this.$t('Provider'), [
'ALIYUN', 'QCLOUD', 'HUAWEICLOUD', 'CMPP2', 'SMSCustom', 'SMSFileCustom'
]
]

View File

@@ -36,7 +36,7 @@
<el-table-column :label="$tc('Actions')" width="200">
<template v-slot="scope">
<el-button v-if="!scope.row.children" type="small" @click="onOpenDialog(scope.row)">
{{ $t('ChangeReceiver') }}
{{ $t('EditRecipient') }}
</el-button>
</template>
</el-table-column>
@@ -45,7 +45,7 @@
<SelectDialog
v-if="dialogVisible"
:selected-users="dialogSelectedUsers"
:title="$tc('ChangeReceiver')"
:title="$tc('EditRecipient')"
:visible.sync="dialogVisible"
@cancel="dialogVisible=false"
@submit="onDialogSelectSubmit"

View File

@@ -3,7 +3,7 @@
<GenericListPage :header-actions="headerActions" :table-config="tableConfig" />
<Dialog
:show-buttons="false"
:title="$tc('Setting')"
:title="$tc('General')"
:visible.sync="visible"
>
<GenericCreateUpdateForm v-bind="form" @submitSuccess="visible=false" />
@@ -110,7 +110,7 @@ export default {
canCreate: this.$hasPerm('orgs.add_organization'),
extraActions: [
{
title: this.$t('Setting'),
title: this.$t('Settings...'),
icon: 'el-icon-setting',
callback: () => {
this.visible = true

View File

@@ -147,11 +147,7 @@ export default {
}
},
actions: {
el: {
fixed: 'right'
},
formatterArgs: {
fixed: 'right',
hasDelete: hasDelete,
canUpdate: ({ row }) => {
return this.$hasPerm('users.change_user') &&