Merge pull request #1242 from jumpserver/dev

v2.17.0 rc4
This commit is contained in:
Jiangjie.Bai
2021-12-15 22:04:42 +08:00
committed by GitHub
21 changed files with 180 additions and 50 deletions

View File

@@ -58,6 +58,7 @@
"vue-cookie": "^1.1.4",
"vue-echarts": "^5.0.0-beta.0",
"vue-i18n": "^8.15.5",
"vue-json-editor": "^1.4.3",
"vue-moment": "^4.1.0",
"vue-password-strength-meter": "^1.7.2",
"vue-router": "3.0.6",

View File

@@ -0,0 +1,73 @@
<template>
<div class="json-editor">
<JsonEditor
v-model="resultInfo"
:show-btns="false"
:mode="'code'"
@json-change="onJsonChange"
@json-save="onJsonSave"
@has-error="onError"
/>
</div>
</template>
<script>
import JsonEditor from 'vue-json-editor'
export default {
components: { JsonEditor },
props: {
value: {
type: String,
default: () => ''
}
},
data() {
return {
hasJsonFlag: true, // json是否验证通过
resultInfo: {}
}
},
created() {
this.resultInfo = JSON.parse(this.value)
},
methods: {
// 数据改变
onJsonChange(value) {
this.onJsonSave(value)
},
// 保存
onJsonSave(value) {
this.resultInfo = value
this.hasJsonFlag = true
setTimeout(() => {
this.$emit('change', JSON.stringify(this.resultInfo))
}, 500)
},
onError: _.debounce(function(value) {
this.$message.error(this.$t('common.FormatError'))
}, 1100)
}
}
</script>
<style lang="scss" scoped>
.json-editor {
&>>> .jsoneditor {
border: 1px solid #e5e6e7;
}
&>>> .jsoneditor-compact {
display: none;
}
&>>> .jsoneditor-modes {
display: none;
}
&>>> .jsoneditor-poweredBy {
display: none;
}
&>>> .jsoneditor-menu {
background: #1ab394;
border-bottom: 1px solid #1ab394;
}
}
</style>

View File

@@ -8,6 +8,7 @@ import UploadKey from './UploadKey'
import UserPassword from './UserPassword'
import WeekCronSelect from './WeekCronSelect'
import UpdateToken from './UpdateToken'
import JsonEditor from './JsonEditor'
export default {
DatetimeRangePicker,
@@ -19,7 +20,8 @@ export default {
UploadField,
UserPassword,
WeekCronSelect,
UpdateToken
UpdateToken,
JsonEditor
}
export {
@@ -32,5 +34,6 @@ export {
UploadField,
UserPassword,
WeekCronSelect,
UpdateToken
UpdateToken,
JsonEditor
}

View File

@@ -138,6 +138,7 @@
"Disk": "硬盘",
"AdDomain": "AD域名",
"AdDomainHelpText": "提供给域用户登录的AD域名",
"SetAdDomainNoDisabled": "如果设置了AD域名不能修改",
"Domain": "网域",
"DomainDetail": "网域详情",
"DomainHelpMessage": "网域功能是为了解决部分环境混合云无法直接连接而新增的功能原理是通过网关服务器进行跳转登录。JMS => 网域网关 => 目标资产",
@@ -445,6 +446,7 @@
"lastCannotBeDeleteMsg": "最后一项,不能被删除",
"InvalidJson": "不是合法 JSON",
"time_period": "时段",
"FormatError": "格式错误",
"WeekCronSelect": {
"Monday": "星期一",
"Tuesday": "星期二",
@@ -916,6 +918,9 @@
"authSAML2MetadataUrl": "IDP metadata URL",
"authSAML2AdvancedSettings": "高级配置",
"IdpMetadataHelpText": "IDP metadata URL 和 IDP metadata XML参数二选一即可IDP metadata URL的优先级高",
"IdpMetadataUrlHelpText": "从远端地址中加载 IDP Metadata",
"authSAMLKeyHelpText": "SP 证书和密钥 是用来和 IDP 加密通信的",
"authSAMLCertHelpText": "上传证书密钥后保存, 然后查看 SP Metadata",
"authCASAttrMap": "用户属性映射",
"SignaturesAndTemplates": "Signatures and Templates",
"unselectedUser": "没有选择用户",
@@ -1046,6 +1051,9 @@
"PermissionName": "授权规则名称",
"Accept": "同意",
"AssignedMe": "待我审批",
"FlowSetUp": "流程设置",
"ApprovalProcess": "审批流程",
"LevelApproval": "级审批",
"Assignee": "处理人",
"Assignees": "待处理人",
"Close": "关闭",

View File

@@ -18,9 +18,9 @@
"username_group":"Username group",
"hostname_group":"Hostname group",
"asset_ip_group": "Asset ip group",
"system_users_name_group": "Systemusers name group",
"system_users_protocol_group": "Systemusers protocol group",
"system_users_username_group": "systemusers username group",
"system_users_name_group": "Systemuser name",
"system_users_protocol_group": "Systemuser protocol",
"system_users_username_group": "systemuser username",
"apply_login_asset": "Apply login asset",
"apply_login_system_user": "Apply login system user",
"apply_login_user": "Apply login user",
@@ -136,6 +136,7 @@
"Disk": "Disk",
"AdDomain": "AD Domain",
"AdDomainHelpText": "AD domain provided to domain users for login",
"SetAdDomainNoDisabled": "If AD domain is set, it cannot be modified",
"Domain": "Domain",
"DomainDetail": "Domain detail",
"DomainHelpMessage": "The domain function is added to address the fact that some environments (such as the hybrid cloud) cannot be connected directly by jumping on the gateway server.\nJMS => Domain gateway => Target assets",
@@ -468,6 +469,7 @@
"failedConditions": "cron expression error"
},
"Cycle": "Cycle",
"FormatError": "Format error",
"WeekCronSelect": {
"Monday": "Monday",
"Tuesday": "Tuesday",
@@ -893,6 +895,9 @@
"authSAML2Xml": "IDP metadata XML",
"authSAML2MetadataUrl": "IDP metadata URL",
"IdpMetadataHelpText": "Choose one of IDP metadata URL and IDP metadata XML parameters. IDP metadata URL has high priority",
"IdpMetadataUrlHelpText": "Load IDP Metadata from remote url",
"authSAMLKeyHelpText": "SP cert and private key, using communicate with IDP",
"authSAMLCertHelpText": "After upload cert and private key, View SP Metadata",
"authSAML2AdvancedSettings": "Advanced Settings",
"unselectedUser": "Unselected user",
"auto": "Auto",
@@ -1008,6 +1013,9 @@
"PermissionName": "Permission name",
"Accept": "Accept",
"AssignedMe": "Assigned me",
"FlowSetUp": "Flow set up",
"ApprovalProcess": "Approval process",
"LevelApproval": "Level approval",
"Assignee": "Assignee",
"RequestPerm":"Request Perm",
"AssignedInfo":"Assigned Info",
@@ -1252,6 +1260,7 @@
"NodeAmount": "Node",
"PasswordLength": "Password length",
"PasswordStrategy": "Password strategy",
"SecretKeyStrategy": "Secret key strategy",
"RegularlyPerform": "Regularly perform",
"Result": "Result",
"Retry": "Retry",
@@ -1259,6 +1268,7 @@
"TaskList": "Task list",
"TimeDelta": "Time delta",
"Timer": "Timer",
"TimerPeriod": "Timer period",
"Username": "Username"
},
"Cloud": {

View File

@@ -1,3 +1,3 @@
export function openTaskPage(taskId) {
window.open(`/#/ops/celery/task/${taskId}/log/`, '', 'width=900,height=600')
export function openTaskPage(taskId, type = '') {
window.open(`/#/ops/celery/task/${taskId}/log/?type=${type}`, '', 'width=900,height=600')
}

View File

@@ -68,6 +68,9 @@ export default {
hasImport: false,
hasBulkDelete: true,
createRoute: 'DatabaseAppCreate',
searchConfig: {
exclude: ['category', 'type']
},
moreCreates: {
callback: (item) => {
vm.$router.push({ name: 'DatabaseAppCreate', query: { type: item.name.toLowerCase() }})

View File

@@ -56,7 +56,10 @@ export default {
hasExport: false,
hasImport: false,
hasBulkDelete: true,
createRoute: 'KubernetesAppCreate'
createRoute: 'KubernetesAppCreate',
searchConfig: {
exclude: ['category', 'type']
}
}
}
}

View File

@@ -66,6 +66,9 @@ export default {
hasExport: false,
hasImport: false,
// createRoute: 'RemoteAppCreate',
searchConfig: {
exclude: ['category', 'type']
},
moreCreates: {
dropdown: this.getCreateAppType(),
callback: (app) => {

View File

@@ -121,7 +121,7 @@ function getFields() {
disabled: false
},
hidden: form => {
if (form.login_mode === 'manual' || form.type === 'admin') {
if (form.login_mode === 'manual' || form.type === 'admin' || (form.ad_domain && form.ad_domain !== '')) {
this.fieldsMeta.auto_push.el.disabled = true
} else {
this.fieldsMeta.auto_push.el.disabled = false
@@ -133,7 +133,8 @@ function getFields() {
updateForm({ auto_generate_key: value })
}
}
}
},
helpText: this.$t('assets.SetAdDomainNoDisabled')
}
const update_password = {

View File

@@ -7,7 +7,7 @@
<el-col :span="8">
<QuickActions type="primary" :actions="quickActions" />
<AssetRelationCard ref="assetSelect" type="primary" style="margin-top: 15px" v-bind="assetRelationConfig" />
<RelationCard type="info" style="margin-top: 15px" v-bind="nodeRelationConfig" />
<RelationCard ref="nodeRelation" type="info" style="margin-top: 15px" v-bind="nodeRelationConfig" />
</el-col>
</el-row>
</div>
@@ -182,6 +182,12 @@ export default {
const objectId = this.object.id
const relationUrl = `/api/v1/assets/system-users-nodes-relations/?systemuser=${objectId}&node=${itemId}`
return this.$axios.delete(relationUrl)
},
onAddSuccess: (objects, that) => {
that.iHasObjects = [...that.iHasObjects, ...objects]
vm.$refs.nodeRelation.$refs.select2.clearSelected()
this.$message.success(this.$t('common.updateSuccessMsg'))
vm.$refs.ListTable.reloadTable()
}
},
assetRelationConfig: {

View File

@@ -68,7 +68,7 @@ export default {
hasCreate: false,
createRoute: 'SystemUserCreate',
searchConfig: {
exclude: ['type']
exclude: ['type', 'protocol']
},
moreCreates: {
callback: (option) => {

View File

@@ -78,7 +78,7 @@ export default {
value: this.object.id,
formatter: function(row, value) {
const onClick = function() {
openTaskPage(value)
openTaskPage(value, 'ansible')
}
const title = this.$t('common.View')
return <a onClick={onClick} >{ title }</a>

View File

@@ -102,7 +102,7 @@ export default {
value: this.object.latest_execution.id,
formatter: function(row, value) {
const onClick = function() {
openTaskPage(value)
openTaskPage(value, 'ansible')
}
const title = this.$t('common.View')
return <a onClick={onClick} >{ title }</a>

View File

@@ -11,6 +11,8 @@
<script>
import BaseAuth from './Base'
import { JsonRequired } from '@/components/DataForm/rules'
import { JsonEditor } from '@/components/FormFields'
export default {
name: 'Cas',
components: {
@@ -36,10 +38,7 @@ export default {
],
fieldsMeta: {
CAS_RENAME_ATTRIBUTES: {
component: 'el-input',
el: {
type: 'textarea'
},
component: JsonEditor,
label: this.$t('setting.authUserAttrMap'),
rules: [JsonRequired]
}

View File

@@ -12,6 +12,8 @@
import BaseAuth from './Base'
import { JsonRequired } from '@/components/DataForm/rules'
import { UploadKey } from '@/components'
import { JsonEditor } from '@/components/FormFields'
export default {
name: 'SAML2',
components: {
@@ -29,8 +31,14 @@ export default {
url: '/api/v1/settings/setting/?category=saml2',
fields: [
[this.$t('common.Basic'), ['AUTH_SAML2']],
[this.$t('common.Params'), ['SAML2_IDP_METADATA_URL', 'SAML2_IDP_METADATA_XML', 'SAML2_SP_ADVANCED_SETTINGS']],
[this.$t('common.Certificate'), ['SAML2_SP_CERT_CONTENT', 'SAML2_SP_KEY_CONTENT']],
[this.$t('common.Certificate'), [
'SAML2_SP_KEY_CONTENT',
'SAML2_SP_CERT_CONTENT'
]],
[this.$t('common.Params'), [
'SAML2_IDP_METADATA_URL', 'SAML2_IDP_METADATA_XML',
'SAML2_SP_ADVANCED_SETTINGS'
]],
[this.$t('common.Other'), [
'SAML2_LOGOUT_COMPLETELY', 'AUTH_SAML2_ALWAYS_UPDATE_USER',
'SAML2_RENAME_ATTRIBUTES'
@@ -43,36 +51,32 @@ export default {
SAML2_IDP_METADATA_URL: {
component: 'el-input',
label: this.$t('setting.authSAML2MetadataUrl'),
helpText: this.$t('setting.IdpMetadataHelpText')
helpText: this.$t('setting.IdpMetadataUrlHelpText')
},
SAML2_IDP_METADATA_XML: {
component: 'el-input',
el: {
type: 'textarea',
rows: 8
rows: 4
},
label: this.$t('setting.authSAML2Xml')
label: this.$t('setting.authSAML2Xml'),
helpText: this.$t('setting.IdpMetadataHelpText')
},
SAML2_SP_ADVANCED_SETTINGS: {
component: 'el-input',
el: {
type: 'textarea',
rows: 3
},
component: JsonEditor,
label: this.$t('setting.authSAML2AdvancedSettings'),
rules: [JsonRequired]
},
SAML2_SP_CERT_CONTENT: {
component: UploadKey
},
SAML2_SP_KEY_CONTENT: {
component: UploadKey
component: UploadKey,
helpText: this.$t('setting.authSAMLKeyHelpText')
},
SAML2_SP_CERT_CONTENT: {
component: UploadKey,
helpText: this.$t('setting.authSAMLCertHelpText') + ' <a href="/core/auth/saml2/metadata/" target="_blank">查看</a>'
},
SAML2_RENAME_ATTRIBUTES: {
component: 'el-input',
el: {
type: 'textarea'
},
component: JsonEditor,
label: this.$t('setting.authUserAttrMap'),
rules: [JsonRequired],
helpText: this.$t('setting.authUserAttrMapHelpText')

View File

@@ -13,7 +13,7 @@ import TestLoginDialog from './TestLoginDialog'
import { IBox } from '@/components'
import rules from '@/components/DataForm/rules'
import { JsonRequired } from '@/components/DataForm/rules'
import { UpdateToken } from '@/components/FormFields'
import { UpdateToken, JsonEditor } from '@/components/FormFields'
export default {
name: 'Ldap',
@@ -62,10 +62,7 @@ export default {
]
},
AUTH_LDAP_USER_ATTR_MAP: {
component: 'el-input',
el: {
type: 'textarea'
},
component: JsonEditor,
label: this.$t('setting.authLdapUserAttrMap'),
rules: [JsonRequired]
}

View File

@@ -22,7 +22,7 @@ export default {
disabled: true
},
rules: {
label: '审批流程',
label: this.$t('tickets.ApprovalProcess'),
component: FlowRuleField,
el: {
level: 1

View File

@@ -4,7 +4,7 @@
<div v-for="(item, i) of approveData" :key="i" style="margin-bottom: 10px">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>{{ i + 1 + '级审批' }}</span>
<span>{{ i + 1 + ' ' + vm.$t('tickets.LevelApproval') }}</span>
</div>
<el-radio-group v-model="item.strategy" @change="onChange()">
<el-radio label="super_admin">{{ vm.$t('tickets.SuperAdmin') }}</el-radio>

View File

@@ -46,7 +46,7 @@ export default {
name: 'AssignedTicketList'
},
{
title: '流程设置',
title: this.$t('tickets.FlowSetUp'),
icon: 'fa-gear',
name: 'TicketFlow',
hidden: () => {

View File

@@ -5,6 +5,7 @@
import ListTable from '@/components/ListTable'
import { DetailFormatter } from '@/components/TableFormatters'
import { toSafeLocalDateStr } from '@/utils/common'
import { APPROVE, REJECT, CLOSED } from './const'
export default {
name: 'TicketListTable',
components: {
@@ -105,14 +106,32 @@ export default {
hasCreate: false,
hasBulkDelete: false,
searchConfig: {
default: {
status: {
key: 'status',
exclude: ['state'],
options: [
{
value: 'state',
label: this.$t('tickets.action'),
value: 'open',
valueLabel: this.$t('tickets.Pending')
children: [
{
default: true,
value: 'open',
label: this.$t('tickets.Pending')
},
{
value: APPROVE,
label: this.$t('tickets.Approved')
},
{
value: REJECT,
label: this.$t('tickets.Rejected')
},
{
value: CLOSED,
label: this.$t('tickets.Closed')
}
]
}
}
]
},
createTitle: this.$t('common.RequestTickets'),
hasMoreActions: false,