Merge pull request #2043 from jumpserver/dev

v2.26.0-rc1
This commit is contained in:
Jiangjie.Bai
2022-09-08 15:46:44 +08:00
committed by GitHub
24 changed files with 355 additions and 89 deletions

View File

@@ -38,7 +38,7 @@
"krry-transfer": "^1.7.3",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"lodash": "^4.17.15",
"lodash": "^4.17.21",
"lodash.clonedeep": "^4.5.0",
"lodash.frompairs": "^4.0.1",
"lodash.get": "^4.4.2",
@@ -50,8 +50,8 @@
"lodash.set": "^4.3.2",
"lodash.topairs": "^4.3.0",
"lodash.values": "^4.3.0",
"moment": "^2.29.1",
"moment-parseformat": "^3.0.0",
"moment": "^2.29.4",
"moment-parseformat": "^4.0.0",
"normalize.css": "7.0.0",
"npm": "^7.8.0",
"nprogress": "0.2.0",

View File

@@ -45,3 +45,20 @@ export const JsonRequired = {
}
}
}
export const JsonRequiredUserNameMapped = {
required: true,
trigger: 'change',
validator: (rule, value, callback) => {
try {
JSON.parse(value)
const hasUserName = _.map(JSON.parse(value), (value) => value)
if (!hasUserName.includes('username')) {
callback(new Error(i18n.t('common.requiredHasUserNameMapped')))
}
callback()
} catch (e) {
callback(new Error(i18n.t('common.InvalidJson')))
}
}
}

View File

@@ -50,7 +50,7 @@ export default {
const reader = new FileReader()
reader.onload = function() {
let result = this.result
if (vm.toFormat === 'object') {
if (vm.toFormat === 'object' && vm.fileName.endsWith('.json')) {
result = JSON.parse(result)
}
vm.$emit('input', result)

View File

@@ -267,6 +267,12 @@
"IPLoginLimit": "IP login limit",
"Setting": "Setting",
"Certificate": "Certificate",
"CACertificate": "CA Certificate",
"ClientCertificate": "Client certificate",
"CertificateKey": "Certificate key file",
"AllowInvalidCert": "Allow invalid cert",
"UseSSL": "Use SSL/TLS",
"SecretKey": "Secret key",
"Scope": "Type",
"Builtin": "Builtin",
"DateCreated": "Date created",
@@ -408,6 +414,7 @@
"disableSelected": "Disable selected",
"disableSuccessMsg": "Disable success",
"fieldRequiredError": "This field is required",
"requiredHasUserNameMapped": "The mapping of the username field must be included, such as {'uid': 'username'}",
"getErrorMsg": "Get failed",
"fileType": "File type",
"Status": "Status",
@@ -424,6 +431,7 @@
"downloadImportTemplateMsg": "Download import template",
"downloadUpdateTemplateMsg": "Download update template",
"onlyCSVFilesTips": "Only csv supported",
"ImportFail": "Import fail",
"updateSuccessMsg": "Update success, total: {count}",
"dragUploadFileInfo": "Drag file here or click here to upload",
"uploadCsvLth10MHelpText": "csv/xlsx files with a size less than 10M",
@@ -771,7 +779,7 @@
"OperateLog": "Operation Logs",
"PasswordChangeLog": "Password Update Logs",
"Perms": "Permissions",
"PersonalInformationImprovement": "PersonalInformationImprovement",
"PersonalInformationImprovement": "Personal information improvement",
"PlatformCreate": "Platform create",
"PlatformDetail": "Platform detail",
"PlatformList": "Platforms",
@@ -925,6 +933,9 @@
"SMS": "SMS",
"AlibabaCloud": "Alibaba cloud",
"TencentCloud": "Tencent cloud",
"HuaweiCloud": "Huawei cloud",
"SignChannelNum": "Signature Channel Number",
"AppEndpoint": "App access address",
"CMPP2": "CMPP v2.0",
"VerifySignTmpl": "Verification code template",
"Radius": "Radius",
@@ -1407,9 +1418,11 @@
"IPNetworkSegment": "Ip Network Segment",
"Aliyun": "Ali Cloud",
"Qcloud": "Tencent Cloud",
"QcloudLighthouse": "Tencent Cloud(Lighthouse)",
"QingyunPrivatecloud": "Qingyun Private Cloud",
"HuaweiPrivatecloud": "Huawei Private Cloud",
"OpenStack": "OpenStack",
"CTYunPrivate": "CTYun Private Cloud",
"GCP": "Google Cloud Platform",
"FC": "Fusion Compute",
"LAN": "LAN",

View File

@@ -272,6 +272,12 @@
"IPLoginLimit": "IPログイン制限",
"Setting": "設定",
"Certificate": "証明書",
"CACertificate": "CA 証明書",
"ClientCertificate": "クライアント証明書",
"CertificateKey": "証明書秘密鍵ファイル",
"AllowInvalidCert": "証明書チェックを無視する",
"UseSSL": "使う SSL/TLS",
"SecretKey": "鍵",
"Scope": "カテゴリ",
"Builtin": "内蔵",
"DateCreated": "作成日",
@@ -417,6 +423,7 @@
"disableSelected": "選択した無効",
"disableSuccessMsg": "成功を無効にする",
"fieldRequiredError": "このフィールドは必須項目です",
"requiredHasUserNameMapped": "usernameフィールドのマッピングを含める必要があります, {'uid':'username'}など",
"getErrorMsg": "の取得に失敗しました",
"MFAErrorMsg": "MFAエラーです。チェックしてください",
"Total": "合計",
@@ -435,6 +442,7 @@
"downloadImportTemplateMsg": "作成テンプレートのダウンロード",
"downloadUpdateTemplateMsg": "更新テンプレートのダウンロード",
"onlyCSVFilesTips": "Csvファイルのインポートのみサポート",
"ImportFail": "インポートに失敗しました",
"updateSuccessMsg": "更新のインポートに成功しました。合計:{count}",
"uploadCsvLth10MHelpText": "Csv/xlsxのみアップロードでき、10m以下です",
"dragUploadFileInfo": "ここにファイルをドラッグするか、ここをクリックしてアップロードしてください",
@@ -944,6 +952,9 @@
"Feature": "機能",
"AlibabaCloud": "Alibaba cloud",
"TencentCloud": "テンセント雲",
"HuaweiCloud": "ファーウェイ雲",
"SignChannelNum": "サインパス番号",
"AppEndpoint": "アクセスアドレスを適用する",
"CMPP2": "CMPP v2.0",
"Radius": "Radius",
"VerifySignTmpl": "認証コードメールテンプレート",
@@ -1450,9 +1461,11 @@
"IPNetworkSegment": "IPネットワークセグメント",
"Aliyun": "Alibaba cloud",
"Qcloud": "テンセント雲",
"QcloudLighthouse": "テンセント雲(軽量アプリケーションサーバー)",
"QingyunPrivatecloud": "青雲プライベートクラウド",
"HuaweiPrivatecloud": "ファーウェイプライベートクラウド",
"OpenStack": "OpenStack",
"CTYunPrivate": "天翼プライベート・クラウド",
"GCP": "Googleクラウド",
"FC": "Fusion Compute",
"LAN": "ローカルエリアネットワーク",

View File

@@ -272,6 +272,12 @@
"IPLoginLimit": "IP 登录限制",
"Setting": "设置",
"Certificate": "证书",
"CACertificate": "CA 证书",
"ClientCertificate": "客户端证书",
"CertificateKey": "证书秘钥文件",
"AllowInvalidCert": "忽略证书检查",
"UseSSL": "使用 SSL/TLS",
"SecretKey": "密钥",
"Scope": "类别",
"Builtin": "内置",
"DateCreated": "创建日期",
@@ -417,6 +423,7 @@
"disableSelected": "禁用所选",
"disableSuccessMsg": "禁用成功",
"fieldRequiredError": "这个字段是必填项",
"requiredHasUserNameMapped": "必须包含 username 字段的映射,如 { 'uid': 'username' }",
"getErrorMsg": "获取失败",
"MFAErrorMsg": "MFA错误请检查",
"Total": "总共",
@@ -435,6 +442,7 @@
"downloadImportTemplateMsg": "下载创建模板",
"downloadUpdateTemplateMsg": "下载更新模板",
"onlyCSVFilesTips": "仅支持csv文件导入",
"ImportFail": "导入失败",
"updateSuccessMsg": "导入更新成功,总共:{count}",
"uploadCsvLth10MHelpText": "只能上传 csv/xlsx, 且不超过 10M",
"dragUploadFileInfo": "将文件拖到此处,或点击此处上传",
@@ -945,6 +953,9 @@
"Feature": "功能",
"AlibabaCloud": "阿里云",
"TencentCloud": "腾讯云",
"HuaweiCloud": "华为云",
"SignChannelNum": "签名通道号",
"AppEndpoint": "应用接入地址",
"CMPP2": "CMPP v2.0",
"Radius": "Radius",
"VerifySignTmpl": "验证码短信模板",
@@ -1451,8 +1462,10 @@
"IPNetworkSegment": "IP网段",
"Aliyun": "阿里云",
"Qcloud": "腾讯云",
"QcloudLighthouse": "腾讯云(轻量应用服务器)",
"QingyunPrivatecloud": "青云私有云",
"HuaweiPrivatecloud": "华为私有云",
"CTYunPrivate": "天翼私有云",
"OpenStack": "OpenStack",
"GCP": "谷歌云",
"FC": "Fusion Compute",

View File

@@ -233,6 +233,10 @@ export default {
encryptedFields: {
type: Array,
default: () => ['password', 'token', 'private_key']
},
needGetObjectDetail: {
type: Boolean,
default: true
}
},
data() {
@@ -312,7 +316,7 @@ export default {
},
async getFormValue() {
const cloneFrom = this.$route.query['clone_from']
if (!this.isUpdateMethod() && !cloneFrom) {
if ((!this.isUpdateMethod() && !cloneFrom) || !this.needGetObjectDetail) {
return Object.assign(this.form, this.initial)
}
let object = this.object

View File

@@ -97,6 +97,7 @@ export default {
getDefaultFormSetting() {
const vm = this
return {
needGetObjectDetail: false,
submitMethod: () => 'patch',
cleanFormValue: (value) => {
const filterValue = {}

View File

@@ -72,6 +72,9 @@ const mutations = {
},
ADD_WORKBENCH_ORGS(state, org) {
state.workbenchOrgs.push(org)
},
SET_IS_FIRST_LOGIN(state, flag) {
state.profile.is_first_login = flag
}
}
@@ -140,6 +143,9 @@ const actions = {
const usingOrgs = mapper[viewName] || state.consoleOrgs
Vue.$log.debug('Set using orgs: ', viewName, usingOrgs)
commit('SET_USING_ORGS', usingOrgs)
},
ifFirstLogin({ commit }, flag) {
commit('SET_IS_FIRST_LOGIN', flag)
}
}

View File

@@ -5,6 +5,7 @@
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import { getDatabaseTypeFieldsMap } from '@/views/applications/DatabaseApp/const'
import { UploadKey } from '@/components'
export default {
components: {
GenericCreateUpdatePage
@@ -36,6 +37,29 @@ export default {
fieldsMeta: {
host: {
type: 'input'
},
use_ssl: {
label: this.$t('common.UseSSL'),
component: 'el-switch'
},
allow_invalid_cert: {
label: this.$t('common.AllowInvalidCert'),
hidden: (form) => { return !form.use_ssl }
},
ca_cert: {
label: this.$t('common.CACertificate'),
hidden: (form) => { return !form.use_ssl },
component: UploadKey
},
client_cert: {
label: this.$t('common.ClientCertificate'),
hidden: (form) => { return !form.use_ssl },
component: UploadKey
},
cert_key: {
label: this.$t('common.CertificateKey'),
hidden: (form) => { return !form.use_ssl },
component: UploadKey
}
}
}

View File

@@ -1,10 +1,16 @@
import { ORACLE } from '../const'
import { ORACLE, MONGODB, REDIS } from '../const'
export function getDatabaseTypeFieldsMap(type) {
const baseParams = ['host', 'port', 'database']
const tlsParams = ['use_ssl', 'allow_invalid_cert', 'ca_cert']
switch (type) {
case ORACLE:
return ['host', 'port', 'database', 'version']
return baseParams.concat(['version'])
case REDIS:
return baseParams.concat(tlsParams.concat(['client_cert', 'cert_key']))
case MONGODB:
return baseParams.concat(tlsParams.concat(['cert_key']))
default:
return ['host', 'port', 'database']
return baseParams
}
}

View File

@@ -92,24 +92,27 @@ export const DATABASE = [
}
]
const MONGODB_ITEM = {
name: MONGODB,
title: i18n.t(`applications.applicationsType.${MONGODB}`),
type: 'primary',
category: DATABASE_CATEGORY,
group: i18n.t('applications.NoSQLProtocol')
}
const REDIS_ITEM = {
name: REDIS,
title: i18n.t(`applications.applicationsType.${REDIS}`),
type: 'primary',
category: DATABASE_CATEGORY,
has: true
}
export const KV_DATABASE = [
{
name: REDIS,
title: i18n.t(`applications.applicationsType.${REDIS}`),
type: 'primary',
category: DATABASE_CATEGORY,
has: true,
group: i18n.t('applications.NoSQLProtocol')
},
{
name: MONGODB,
title: i18n.t(`applications.applicationsType.${MONGODB}`),
type: 'primary',
category: DATABASE_CATEGORY
}
MONGODB_ITEM, REDIS_ITEM
]
export const AppPlanDatabase = DATABASE
export const AppPlanDatabase = [...DATABASE, MONGODB_ITEM]
export const KUBERNETES = 'k8s'
export const CLOUD_CATEGORY = 'cloud'

View File

@@ -22,7 +22,7 @@ export default {
const accountProviderAttrs = ACCOUNT_PROVIDER_ATTRS_MAP[accountProvider]
function setFieldAttrs() {
const fieldsObject = {}
const updateNotRequiredFields = ['access_key_secret', 'client_secret', 'password', 'sc_password', 'oc_password']
const updateNotRequiredFields = ['access_key_secret', 'client_secret', 'password', 'sc_password', 'oc_password', 'cert_file', 'key_file']
for (const item of accountProviderAttrs?.attrs) {
fieldsObject[item] = {
rules: updateNotRequiredFields.includes(item) && vm.$route.params.id ? [] : [Required]
@@ -61,6 +61,20 @@ export default {
toFormat: 'object'
}
},
cert_file: {
label: this.$t('common.Certificate'),
component: UploadKey,
el: {
toFormat: 'object'
}
},
key_file: {
label: this.$t('common.SecretKey'),
component: UploadKey,
el: {
toFormat: 'object'
}
},
password: {
rules: this.$route.params.id ? [] : [Required]
}
@@ -91,13 +105,17 @@ export default {
const attrs = values.attrs
for (const item of encryptedFields) {
const value = attrs[item]
if (value) {
attrs[item] = encryptPassword(value)
if (!value) {
continue
}
attrs[item] = encryptPassword(value)
}
const toListFields = ['ip_group']
for (const item of toListFields) {
let value = attrs[item]
if (!value) {
continue
}
value = value?.split(',') || []
value = value.filter((value, index) => { if (value) return true })
attrs[item] = value

View File

@@ -4,7 +4,7 @@
<script type="text/jsx">
import GenericListTable from '@/layout/components/GenericListTable'
import { ACCOUNT_PROVIDER_ATTRS_MAP, aliyun, aws_china, aws_international, huaweicloud, qcloud, azure, azure_international, vmware, nutanix, qingcloud_private, huaweicloud_private, openstack, gcp, baiducloud, jdcloud, fc, lan } from '../const'
import { ACCOUNT_PROVIDER_ATTRS_MAP, aliyun, aws_china, aws_international, huaweicloud, qcloud, qcloud_lighthouse, azure, azure_international, vmware, nutanix, qingcloud_private, huaweicloud_private, ctyun_private, openstack, gcp, baiducloud, jdcloud, fc, lan } from '../const'
export default {
name: 'AccountList',
@@ -82,6 +82,10 @@ export default {
type: 'primary',
can: true
},
{
name: qcloud_lighthouse,
title: ACCOUNT_PROVIDER_ATTRS_MAP[qcloud_lighthouse].title
},
{
name: huaweicloud,
title: ACCOUNT_PROVIDER_ATTRS_MAP[huaweicloud].title
@@ -127,6 +131,10 @@ export default {
name: huaweicloud_private,
title: ACCOUNT_PROVIDER_ATTRS_MAP[huaweicloud_private].title
},
{
name: ctyun_private,
title: ACCOUNT_PROVIDER_ATTRS_MAP[ctyun_private].title
},
{
name: openstack,
title: ACCOUNT_PROVIDER_ATTRS_MAP[openstack].title

View File

@@ -92,6 +92,7 @@ export default {
component: Select2,
el: {
multiple: true,
allowCreate: true,
value: [],
ajax: {
url: '/api/v1/xpack/cloud/regions/',

View File

@@ -1,21 +1,24 @@
import i18n from '@/i18n/i18n'
export const gcp = 'gcp'
export const aliyun = 'aliyun'
export const baiducloud = 'baiducloud'
export const jdcloud = 'jdcloud'
export const aws_international = 'aws_international'
export const aws_china = 'aws_china'
export const huaweicloud = 'huaweicloud'
export const qcloud = 'qcloud'
export const qcloud_lighthouse = 'qcloud_lighthouse'
export const azure = 'azure'
export const azure_international = 'azure_international'
export const vmware = 'vmware'
export const nutanix = 'nutanix'
export const qingcloud_private = 'qingcloud_private'
export const huaweicloud_private = 'huaweicloud_private'
export const ctyun_private = 'ctyun_private'
export const openstack = 'openstack'
export const gcp = 'gcp'
export const nutanix = 'nutanix'
export const vmware = 'vmware'
export const fc = 'fc'
export const baiducloud = 'baiducloud'
export const jdcloud = 'jdcloud'
export const lan = 'lan'
export const ACCOUNT_PROVIDER_ATTRS_MAP = {
@@ -54,6 +57,11 @@ export const ACCOUNT_PROVIDER_ATTRS_MAP = {
title: i18n.t('xpack.Cloud.Qcloud'),
attrs: ['access_key_id', 'access_key_secret']
},
[qcloud_lighthouse]: {
name: qcloud_lighthouse,
title: i18n.t('xpack.Cloud.QcloudLighthouse'),
attrs: ['access_key_id', 'access_key_secret']
},
[azure]: {
name: azure,
title: i18n.t('xpack.Cloud.Azure'),
@@ -64,6 +72,11 @@ export const ACCOUNT_PROVIDER_ATTRS_MAP = {
title: i18n.t('xpack.Cloud.Azure_Int'),
attrs: ['client_id', 'client_secret', 'tenant_id', 'subscription_id']
},
[gcp]: {
name: gcp,
title: i18n.t('xpack.Cloud.GCP'),
attrs: ['service_account_key']
},
[vmware]: {
name: vmware,
title: 'VMware',
@@ -89,16 +102,16 @@ export const ACCOUNT_PROVIDER_ATTRS_MAP = {
title: i18n.t('xpack.Cloud.OpenStack'),
attrs: ['auth_url', 'user_domain_name', 'username', 'password']
},
[gcp]: {
name: gcp,
title: i18n.t('xpack.Cloud.GCP'),
attrs: ['service_account_key']
},
[fc]: {
name: fc,
title: i18n.t('xpack.Cloud.FC'),
attrs: ['api_endpoint', 'username', 'password']
},
[ctyun_private]: {
name: ctyun_private,
title: i18n.t('xpack.Cloud.CTYunPrivate'),
attrs: ['access_key_id', 'access_key_secret', 'api_endpoint', 'cert_file', 'key_file']
},
[lan]: {
name: lan,
title: i18n.t('xpack.Cloud.LAN'),

View File

@@ -78,6 +78,7 @@ export default {
},
onPerformSuccess() {
this.$message.success(this.$t('common.updateSuccessMsg'))
this.$store.dispatch('users/ifFirstLogin', false)
setTimeout(() => this.$router.push({ name: 'ProfileInfo' }), 100)
},
submitMethod() {

View File

@@ -8,7 +8,7 @@
<script>
import BaseAuth from './Base'
import { JsonRequired } from '@/components/DataForm/rules'
import { JsonRequiredUserNameMapped } from '@/components/DataForm/rules'
import { JsonEditor } from '@/components/FormFields'
export default {
@@ -25,16 +25,14 @@ export default {
'AUTH_CAS', 'CAS_SERVER_URL', 'CAS_ROOT_PROXIED_AS', 'CAS_VERSION'
]],
[this.$t('common.Other'), [
'CAS_LOGOUT_COMPLETELY', 'CAS_USERNAME_ATTRIBUTE',
'CAS_APPLY_ATTRIBUTES_TO_USER', 'CAS_RENAME_ATTRIBUTES',
'CAS_CREATE_USER'
'CAS_LOGOUT_COMPLETELY', 'CAS_RENAME_ATTRIBUTES', 'CAS_CREATE_USER'
]]
],
fieldsMeta: {
CAS_RENAME_ATTRIBUTES: {
component: JsonEditor,
label: this.$t('setting.authUserAttrMap'),
rules: [JsonRequired]
rules: [JsonRequiredUserNameMapped]
}
},
submitMethod: () => 'patch',
@@ -43,9 +41,18 @@ export default {
return obj
},
cleanFormValue(data) {
if (data['CAS_RENAME_ATTRIBUTES']) {
data['CAS_RENAME_ATTRIBUTES'] = JSON.parse(data['CAS_RENAME_ATTRIBUTES'])
let userNameAttribute = ''
const renameAttributes = JSON.parse(data['CAS_RENAME_ATTRIBUTES'])
if (renameAttributes) {
data['CAS_RENAME_ATTRIBUTES'] = renameAttributes
}
for (const key in renameAttributes) {
if (renameAttributes[key] === 'username') {
userNameAttribute = key
}
}
data['CAS_USERNAME_ATTRIBUTE'] = userNameAttribute
data['CAS_APPLY_ATTRIBUTES_TO_USER'] = true
return data
}
}

View File

@@ -36,9 +36,11 @@ export default {
'AUTH_OAUTH2_SCOPE',
'AUTH_OAUTH2_PROVIDER_AUTHORIZATION_ENDPOINT',
'AUTH_OAUTH2_ACCESS_TOKEN_ENDPOINT',
'AUTH_OAUTH2_PROVIDER_USERINFO_ENDPOINT'
'AUTH_OAUTH2_PROVIDER_USERINFO_ENDPOINT',
'AUTH_OAUTH2_PROVIDER_END_SESSION_ENDPOINT'
]],
[this.$t('common.Other'), [
'AUTH_OAUTH2_LOGOUT_COMPLETELY',
'AUTH_OAUTH2_ALWAYS_UPDATE_USER',
'AUTH_OAUTH2_USER_ATTR_MAP'
]]

View File

@@ -28,6 +28,7 @@
import ListTable from '@/components/ListTable'
import Dialog from '@/components/Dialog'
import { importLdapUser, refreshLdapUserCache, startLdapUserCache } from '@/api/settings'
import { getErrorResponseMsg } from '@/utils/common'
export default {
name: 'ImportDialog',
@@ -103,7 +104,12 @@ export default {
importLdapUser(data).then(res => {
this.$message.success(res.msg)
// eslint-disable-next-line no-return-assign
}).finally(() => this.dialogLdapUserImportLoginStatus = false)
}).catch(error => {
const errorMessage = getErrorResponseMsg(error) || this.$t('common.imExport.ImportFail')
this.$message.error(errorMessage)
}).finally(() => {
this.dialogLdapUserImportLoginStatus = false
})
}
},
importAllUserClick() {

View File

@@ -0,0 +1,87 @@
<template>
<BaseSMS :title="$t('setting.HuaweiCloud')" :config="$data" />
</template>
<script>
import BaseSMS from './Base'
import { UpdateToken } from '@/components/FormFields'
export default {
name: 'SMSHuawei',
components: {
BaseSMS
},
data() {
const vm = this
return {
url: `/api/v1/settings/setting/?category=huawei`,
hasDetailInMsg: false,
visible: false,
moreButtons: [
{
title: this.$t('common.Test'),
loading: false,
callback: function(value, form, btn) {
btn.loading = true
vm.$axios.post(
`/api/v1/settings/sms/huawei/testing/`,
value
).then(res => {
vm.$message.success(res['msg'])
}).catch(() => {
vm.$log.error('err occur')
}).finally(() => { btn.loading = false })
}
}
],
fields: [
[
this.$t('common.BasicInfo'),
[
'HUAWEI_APP_KEY', 'HUAWEI_APP_SECRET', 'HUAWEI_SMS_ENDPOINT'
]
],
[
this.$t('setting.VerifySignTmpl'),
[
'HUAWEI_SIGN_CHANNEL_NUM', 'HUAWEI_VERIFY_SIGN_NAME', 'HUAWEI_VERIFY_TEMPLATE_CODE'
]
],
[
this.$t('common.Other'),
[
'SMS_TEST_PHONE'
]
]
],
fieldsMeta: {
HUAWEI_VERIFY_SIGN_TMPL: {
fields: ['SIGN_NAME', 'TEMPLATE_CODE'],
fieldsMeta: {
}
},
HUAWEI_APP_SECRET: {
component: UpdateToken
},
HUAWEI_SIGN_CHANNEL_NUM: {
label: this.$t('setting.SignChannelNum')
},
HUAWEI_SMS_ENDPOINT: {
label: this.$t('setting.AppEndpoint')
}
},
submitMethod() {
return 'put'
}
}
},
computed: {
},
methods: {
}
}
</script>
<style scoped>
</style>

View File

@@ -6,6 +6,7 @@
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import SMSAlibaba from './SMSAlibaba'
import SMSTencent from './SMSTencent'
import SMSHuawei from './SMSHuawei'
import CMPP2 from './CMPP2'
export default {
@@ -24,7 +25,7 @@ export default {
],
[
this.$t('setting.SMSProvider'), [
'ALIYUN', 'QCLOUD', 'CMPP2'
'ALIYUN', 'QCLOUD', 'HUAWEICLOUD', 'CMPP2'
]
]
],
@@ -43,6 +44,13 @@ export default {
return form['SMS_BACKEND'] !== 'tencent'
}
},
HUAWEICLOUD: {
label: this.$t('setting.HuaweiCloud'),
component: SMSHuawei,
hidden: (form) => {
return form['SMS_BACKEND'] !== 'huawei'
}
},
CMPP2: {
label: this.$t('setting.CMPP2'),
component: CMPP2,

View File

@@ -1,27 +1,38 @@
<template>
<Page v-bind="$attrs">
<IBox>
<div>
<el-form ref="testForm" label-width="20%" :model="testData" :rules="testRules">
<el-form-item :label="$t('setting.basicTools')">
<el-radio-group v-model="testData.tool_type" @change="changeToolType">
<el-radio v-for="t in tools" :key="t" :label="t" />
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('setting.destinationIP')" prop="dest_addr">
<el-input v-model="testData.dest_addr" :placeholder="$t('setting.destinationIP')" />
</el-form-item>
<el-form-item v-if="testData.tool_type=='Telnet'" :label="$t('setting.testPort')" prop="port_num">
<el-input v-model="testData.port_num" :placeholder="$t('setting.testPort')" />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="isTesting" @click="submitTest">{{ $t('setting.testTools') }}</el-button>
</el-form-item>
<el-form-item>
<el-input v-model="testResp" type="textarea" :readonly="true" :rows="8" :placeholder="$t('setting.testHelpText')" />
</el-form-item>
</el-form>
</div>
<el-form ref="testForm" label-width="20%" :model="testData" :rules="testRules">
<el-form-item :label="$t('setting.basicTools')">
<el-radio-group v-model="testData.tool_type" @change="changeToolType">
<el-radio v-for="t in tools" :key="t" :label="t" />
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('setting.destinationIP')" prop="dest_addr">
<el-input v-model="testData.dest_addr" :placeholder="$t('setting.destinationIP')" />
</el-form-item>
<el-form-item v-if="testData.tool_type=='Telnet'" :label="$t('setting.testPort')" prop="port_num">
<el-input v-model="testData.port_num" :placeholder="$t('setting.testPort')" />
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="small"
:loading="isTesting"
@click="submitTest"
>
{{ $t('setting.testTools') }}
</el-button>
</el-form-item>
<el-form-item>
<el-input
v-model="testResp"
type="textarea"
:readonly="true"
:rows="8"
:placeholder="$t('setting.testHelpText')"
/>
</el-form-item>
</el-form>
</IBox>
</Page>
</template>
@@ -95,20 +106,19 @@ export default {
}
</script>
<style scoped>
.el-form ::v-deep .el-form-item {
margin-bottom: 12px;
}
.el-form ::v-deep .el-form-item__content {
width: 75%;
}
.el-form ::v-deep .el-form-item__label {
padding: 0 30px 0 0;
}
.el-form ::v-deep .el-form-item__error {
<style lang="scss" scoped>
.el-form {
&>>> .el-form-item {
margin-bottom: 12px;
}
&>>> .el-form-item__content {
width: 75%;
}
&>>> .el-form-item__label {
padding: 0 30px 0 0;
}
&>>> .el-form-item__error {
position: inherit;
}
}
</style>

View File

@@ -6883,7 +6883,7 @@ lodash@4.17.11:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0:
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0:
version "4.17.21"
resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.21.tgz?cache=0&sync_timestamp=1613835817439&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=
@@ -7381,16 +7381,21 @@ mockjs@1.0.1-beta3:
dependencies:
commander "*"
moment-parseformat@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/moment-parseformat/-/moment-parseformat-3.0.0.tgz#3a1dc438b4bc073b7e93cc298cfb6c5daac26dba"
integrity sha512-dVgXe6b6DLnv4CHG7a1zUe5mSXaIZ3c6lSHm/EKeVeQI2/4pwe0VRde8OyoCE1Ro2lKT5P6uT9JElF7KDLV+jw==
moment-parseformat@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/moment-parseformat/-/moment-parseformat-4.0.0.tgz#44cffc3b3be3b3d033475869fbfa9066abb66cb0"
integrity sha512-0V4ICKnI1npglqrMSDK2y8WxOdN79DkMoIexzY3P+jr2wNfbB4J81BgjFfHsj18wBsV7FdKCWyCHcezzH0xlyg==
moment@^2.19.2, moment@^2.29.1:
moment@^2.19.2:
version "2.29.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.2.tgz#00910c60b20843bcba52d37d58c628b47b1f20e4"
integrity sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==
moment@^2.29.4:
version "2.29.4"
resolved "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"