Merge pull request #2097 from jumpserver/dev

v2.27.0-rc1
This commit is contained in:
Jiangjie.Bai
2022-10-13 15:14:40 +08:00
committed by GitHub
41 changed files with 167 additions and 89 deletions

View File

@@ -1,23 +1,23 @@
FROM node:10 as stage-build
FROM node:14.16 as stage-build
ARG TARGETARCH
ARG VERSION
ENV VERSION=$VERSION
ARG NPM_REGISTRY="https://registry.npmmirror.com"
ENV NPM_REGISTY=$NPM_REGISTRY
ARG SASS_BINARY_SITE="https://npmmirror.com/mirrors/node-sass"
ENV SASS_BINARY_SITE=$SASS_BINARY_SITE
WORKDIR /data
RUN npm config set sass_binary_site=${SASS_BINARY_SITE}
RUN npm config set registry ${NPM_REGISTRY}
RUN yarn config set registry ${NPM_REGISTRY}
COPY package.json yarn.lock /data/
RUN yarn install
RUN npm rebuild node-sass
RUN set -ex \
&& npm config set registry ${NPM_REGISTRY} \
&& yarn config set registry ${NPM_REGISTRY} \
&& yarn config set cache-folder /root/.cache/yarn/lina
ARG VERSION
ENV VERSION=$VERSION
ADD . /data
RUN cd utils && bash -xieu build.sh build
RUN --mount=type=cache,target=/root/.cache/yarn \
sed -i "s@Version <strong>.*</strong>@Version <strong>${VERSION}</strong>@g" src/layout/components/Footer/index.vue \
&& yarn install \
&& yarn build
FROM nginx:alpine
COPY --from=stage-build /data/release/lina /opt/lina
COPY --from=stage-build /data/lina /opt/lina
COPY nginx.conf /etc/nginx/conf.d/default.conf

View File

@@ -7,6 +7,7 @@
"scripts": {
"dev": "vue-cli-service serve",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --mode staging",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
@@ -32,7 +33,7 @@
"element-ui": "2.13.2",
"eslint-plugin-html": "^6.0.0",
"install": "^0.13.0",
"jquery": "^3.5.0",
"jquery": "^3.6.1",
"js-cookie": "2.2.0",
"jsencrypt": "^3.2.1",
"krry-transfer": "^1.7.3",

View File

@@ -1,12 +1,19 @@
<template>
<div id="app">
<router-view />
<router-view v-if="isRouterAlive" />
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'App'
name: 'App',
computed: {
...mapState({
isRouterAlive: state => state.common.isRouterAlive
})
}
}
</script>

View File

@@ -15,6 +15,16 @@ export default [
permissions: []
}
},
{
path: '/ops/ansible/task/:id/log/',
component: () => import('@/views/ops/CeleryTaskLog'),
name: 'AnsibleTaskLog',
hidden: true,
meta: {
title: i18n.t('route.CeleryTaskLog'),
permissions: []
}
},
{
path: '/ops/task/task/:id/log/',
component: () => import('@/views/ops/CeleryTaskLog'),

View File

@@ -1,6 +1,8 @@
import empty from '@/layout/empty'
import i18n from '@/i18n/i18n'
const activateMenu = '/console/assets/assets'
export default [
{
path: 'cloud',
@@ -20,7 +22,7 @@ export default [
hidden: true,
meta: {
title: i18n.t('xpack.Cloud.CloudSync'),
activeMenu: '/console/assets/assets'
activeMenu: activateMenu
}
},
{
@@ -71,6 +73,7 @@ export default [
hidden: true,
meta: {
title: i18n.t('xpack.Cloud.AccountDetail'),
activeMenu: activateMenu,
permissions: ['xpack.view_account']
}
}
@@ -121,7 +124,8 @@ export default [
name: 'SyncInstanceTaskDetail',
hidden: true,
meta: {
title: i18n.t('xpack.Cloud.SyncInstanceTaskDetail')
title: i18n.t('xpack.Cloud.SyncInstanceTaskDetail'),
activeMenu: activateMenu
}
}
]

View File

@@ -2,7 +2,8 @@ import { optionUrlMeta } from '@/api/common'
const getDefaultState = () => {
return {
metaMap: {}
metaMap: {},
isRouterAlive: true
}
}
@@ -11,6 +12,12 @@ const state = getDefaultState()
const mutations = {
SET_URL_META: (state, { url, meta }) => {
state.metaMap[url] = meta
},
reload: (state) => {
state.isRouterAlive = false
setTimeout(() => {
state.isRouterAlive = true
}, 0)
}
}

View File

@@ -302,3 +302,8 @@ export function groupedDropdownToCascader(group) {
export { BASE_URL }
export function openWindow(url, name = '', iWidth = 900, iHeight = 600) {
var iTop = (window.screen.height - 30 - iHeight) / 2
var iLeft = (window.screen.width - 10 - iWidth) / 2
window.open(url, name, 'height=' + iHeight + ',width=' + iWidth + ',top=' + iTop + ',left=' + iLeft)
}

View File

@@ -1,8 +1,10 @@
import store from '@/store'
import { constantRoutes } from '@/router'
import { openWindow } from './common'
export function openTaskPage(taskId) {
window.open(`/#/ops/celery/task/${taskId}/log/`, '', 'width=900,height=600')
export function openTaskPage(taskId, taskType) {
taskType = taskType || 'celery'
openWindow(`/#/ops/${taskType}/task/${taskId}/log/?type=${taskType}`)
}
export function checkPermission(permsRequired, permsAll) {

View File

@@ -1,4 +1,2 @@
import $ from 'jquery'
window.$ = $
window.jQuery = $
import $ from 'jquery/dist/jquery.min.js'
export default $

View File

@@ -30,7 +30,7 @@ async function changeOrg(org) {
if (index !== -1) {
location.href = path.substring(0, index)
}
setTimeout(() => location.reload(), 400)
setTimeout(() => store.commit('common/reload'), 400)
}
}

View File

@@ -98,7 +98,7 @@ export default {
that.iHasObjects = [...that.iHasObjects, ...objects]
that.$refs.select2.clearSelected()
this.$message.success(this.$t('common.updateSuccessMsg'))
window.location.reload()
this.$store.commit('common/reload')
this.$refs.listTable.$refs.ListTable.reloadTable()
}
}

View File

@@ -93,7 +93,7 @@ export default {
onAddSuccess: (items, that) => {
this.$log.debug('AssetSelect value', that.assets)
this.$message.success(this.$t('common.updateSuccessMsg'))
window.location.reload()
this.$store.commit('common/reload')
}
},
nodeRelationConfig: {
@@ -120,7 +120,7 @@ export default {
that.iHasObjects = [...that.iHasObjects, ...objects]
that.$refs.select2.clearSelected()
this.$message.success(this.$t('common.updateSuccessMsg'))
window.location.reload()
this.$store.commit('common/reload')
},
performDelete: (item) => {
const data = {

View File

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

View File

@@ -38,6 +38,7 @@ export default {
},
tableConfig: {
url: `/api/v1/xpack/cloud/sync-instance-tasks/${this.object.id}/instances/`,
hasSelection: false,
columns: [
'instance_id',
{

View File

@@ -58,10 +58,7 @@ export default {
formatter: DetailFormatter,
formatterArgs: {
permissions: 'xpack.view_syncinstancedetail',
route: 'SyncInstanceTaskDetail',
routeQuery: {
activeTab: 'detail'
}
route: 'SyncInstanceTaskDetail'
}
},
history_count: {

View File

@@ -15,7 +15,7 @@ export default {
},
fields: [
[this.$t('common.Basic'), ['name']],
[this.$t('common.Correlation'), ['users', 'user_groups', 'assets', 'applications', 'system_users']],
[this.$t('common.Correlation'), ['users', 'user_groups', 'nodes', 'assets', 'applications', 'system_users']],
[this.$t('common.Other'), ['is_active', 'comment']]
],
fieldsMeta: {
@@ -36,6 +36,17 @@ export default {
url: '/api/v1/users/groups/'
}
},
nodes: {
el: {
value: [],
ajax: {
url: '/api/v1/assets/nodes/',
transformOption: (item) => {
return { label: item.full_value, value: item.id }
}
}
}
},
assets: {
type: 'assetSelect',
component: AssetSelect,

View File

@@ -6,6 +6,7 @@
import ListTable from '@/components/ListTable'
import { ActionsFormatter } from '@/components/TableFormatters'
import { toSafeLocalDateStr } from '@/utils/common'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'AdhocExecutionHistory',
@@ -86,6 +87,14 @@ export default {
callback: function({ row, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: row.id }})
}
},
{
name: 'log',
title: this.$t('ops.output'),
type: 'info',
callback: function({ row }) {
openTaskPage(row.id, 'ansible')
}
}
]
}

View File

@@ -15,7 +15,6 @@ import DetailCard from '@/components/DetailCard'
import { toSafeLocalDateStr } from '@/utils/common'
import RunInfoCard from '../../RunInfoCard'
import { toLastFailureDisplay, toLastSucessDisplay } from '../business'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'HistoryExecutionDetail',
@@ -72,17 +71,6 @@ export default {
{
key: this.$t('ops.isSuccess'),
value: this.object.is_success
},
{
key: this.$t('ops.output'),
value: this.object.id,
formatter: function(row, value) {
const onClick = function() {
openTaskPage(value, 'ansible')
}
const title = this.$t('common.View')
return <a onClick={onClick} >{ title }</a>
}
}
]
}

View File

@@ -108,7 +108,7 @@ export default {
openTaskPage(value, 'ansible')
}
const title = this.$t('common.View')
return <a onClick={onClick} >{ title }</a>
return <a class='text-link' onClick={onClick} >{ title }</a>
}
}
]

View File

@@ -6,6 +6,7 @@
import ListTable from '@/components/ListTable'
import { DetailFormatter } from '@/components/TableFormatters'
import { toSafeLocalDateStr } from '@/utils/common'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'TaskHistory',
@@ -95,6 +96,14 @@ export default {
callback: function({ row, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: row.id }})
}
},
{
name: 'log',
title: this.$t('ops.output'),
type: 'info',
callback: function({ row }) {
openTaskPage(row.id, 'ansible')
}
}
]
}

View File

@@ -93,7 +93,7 @@ export default {
this.$message.success(this.$t('common.updateSuccessMsg'))
this.$refs.ListTable.reloadTable()
that.$refs.assetSelect.$refs.select2.clearSelected()
window.location.reload()
this.$store.commit('common/reload')
}
},
nodeRelationConfig: {

View File

@@ -37,7 +37,8 @@ import DetailCard from '@/components/DetailCard'
import QuickActions from '@/components/QuickActions'
import UserConfirmDialog from '@/components/UserConfirmDialog'
import { toSafeLocalDateStr } from '@/utils/common'
import store from '@/store'
import { getProfile } from '@/api/users'
import { mapState } from 'vuex'
export default {
name: 'ProfileInfo',
@@ -47,14 +48,9 @@ export default {
QuickActions,
UserConfirmDialog
},
props: {
object: {
type: Object,
default: () => store.state.users.profile
}
},
data() {
return {
object: this.userProfile || {},
url: `/api/v1/users/profile/`,
showPasswordDialog: false,
currentEdit: '',
@@ -160,7 +156,7 @@ export default {
attrs: {
disabled: true,
name: 'site_msg',
model: this.object.receive_backends.indexOf('site_msg') !== -1
model: this.object?.receive_backends.indexOf('site_msg') !== -1
},
callbacks: {
change: this.updateUserReceiveBackends
@@ -171,7 +167,7 @@ export default {
type: 'switcher',
attrs: {
name: 'email',
model: this.object.receive_backends.indexOf('email') !== -1
model: this.object?.receive_backends.indexOf('email') !== -1
},
callbacks: {
change: this.updateUserReceiveBackends
@@ -182,7 +178,7 @@ export default {
type: 'switcher',
attrs: {
name: 'wecom',
model: this.object.receive_backends.indexOf('wecom') !== -1
model: this.object?.receive_backends.indexOf('wecom') !== -1
},
has: this.$store.getters.publicSettings.AUTH_WECOM,
callbacks: {
@@ -194,7 +190,7 @@ export default {
type: 'switcher',
attrs: {
name: 'dingtalk',
model: this.object.receive_backends.indexOf('dingtalk') !== -1
model: this.object?.receive_backends.indexOf('dingtalk') !== -1
},
has: this.$store.getters.publicSettings.AUTH_DINGTALK,
callbacks: {
@@ -206,7 +202,7 @@ export default {
type: 'switcher',
attrs: {
name: 'feishu',
model: this.object.receive_backends.indexOf('feishu') !== -1
model: this.object?.receive_backends.indexOf('feishu') !== -1
},
has: this.$store.getters.publicSettings.AUTH_FEISHU,
callbacks: {
@@ -217,6 +213,9 @@ export default {
}
},
computed: {
...mapState({
userProfile: state => state.users.profile
}),
detailCardItems() {
return [
{
@@ -299,6 +298,12 @@ export default {
return url
}
},
created() {
getProfile().then(res => {
this.object = res
this.$store.commit('users/SET_PROFILE', res)
})
},
methods: {
updateUserReceiveBackends(val) {
this.$axios.patch(

View File

@@ -49,7 +49,7 @@ export default {
const msg = vm.$t('sessions.TerminateTaskSendSuccessMsg')
vm.$message.success(msg)
window.setTimeout(function() {
window.location.reload()
this.$store.commit('common/reload')
}, 50000)
})
}

View File

@@ -175,7 +175,7 @@ export default {
}).then(() => {
restoreInterface().then(res => {
this.$message.success(res.success)
location.reload()
this.$store.commit('common/reload')
})
})
}.bind(this)
@@ -221,7 +221,7 @@ export default {
}
}
updateInterface(form).then(res => {
location.reload()
this.$store.commit('common/reload')
})
}
}

View File

@@ -140,6 +140,7 @@ export default {
window.open(url, '_blank')
},
importLicense() {
const vm = this
if (this.licenseFile['file'] === undefined) {
return
}
@@ -148,7 +149,7 @@ export default {
importLicense(formData).then(res => {
if (res.status) {
this.$message.success(res.msg)
setTimeout(() => location.reload(), 500)
setTimeout(() => vm.$store.commit('common/reload'), 500)
} else {
this.$message.error(res.msg)
}

View File

@@ -60,6 +60,7 @@ export default {
actions: {
prop: 'id',
formatterArgs: {
canUpdate: this.$hasPerm('orgs.change_organization'),
canDelete: function({ row }) {
return !row.is_default && vm.$hasPerm('orgs.delete_organization')
},

View File

@@ -12,7 +12,7 @@
v-on="$listeners"
@confirm="onConfirm()"
>
<GenericCreateUpdateForm v-bind="iConfig" @submitSuccess="submitSuccess" />
<GenericCreateUpdateForm ref="form" v-bind="iConfig" @submitSuccess="submitSuccess" />
</Dialog>
</div>
</template>
@@ -52,6 +52,16 @@ export default {
submitSuccess(res) {
this.$emit('input', !!res[this.enableField])
this.visible = false
},
testPerformError(error) {
const data = error.response.data
for (const key of Object.keys(data)) {
let value = data[key]
if (value instanceof Array) {
value = value.join(';')
}
this.$refs.form.$refs.form.setFieldError(key, value)
}
}
}
}

View File

@@ -1,5 +1,5 @@
<template>
<BaseSMS :title="$t('setting.CMPP2')" :config="$data" />
<BaseSMS ref="baseSms" :title="$t('setting.CMPP2')" :config="$data" />
</template>
<script>
@@ -28,8 +28,9 @@ export default {
value
).then(res => {
vm.$message.success(res['msg'])
}).catch(() => {
}).catch((error) => {
vm.$log.error('err occur')
vm.$refs.baseSms.testPerformError(error)
}).finally(() => { btn.loading = false })
}
}

View File

@@ -1,5 +1,5 @@
<template>
<BaseSMS :title="$t('setting.AlibabaCloud')" :config="$data" />
<BaseSMS ref="baseSms" :title="$t('setting.AlibabaCloud')" :config="$data" />
</template>
<script>
@@ -28,8 +28,9 @@ export default {
value
).then(res => {
vm.$message.success(res['msg'])
}).catch(() => {
}).catch((error) => {
vm.$log.error('err occur')
vm.$refs.baseSms.testPerformError(error)
}).finally(() => { btn.loading = false })
}
}

View File

@@ -1,5 +1,5 @@
<template>
<BaseSMS :title="$t('setting.HuaweiCloud')" :config="$data" />
<BaseSMS ref="baseSms" :title="$t('setting.HuaweiCloud')" :config="$data" />
</template>
<script>
@@ -28,8 +28,9 @@ export default {
value
).then(res => {
vm.$message.success(res['msg'])
}).catch(() => {
}).catch((error) => {
vm.$log.error('err occur')
vm.$refs.baseSms.testPerformError(error)
}).finally(() => { btn.loading = false })
}
}

View File

@@ -1,5 +1,5 @@
<template>
<BaseSMS :title="$t('setting.TencentCloud')" :config="$data" />
<BaseSMS ref="baseSms" :title="$t('setting.TencentCloud')" :config="$data" />
</template>
<script>
@@ -28,8 +28,9 @@ export default {
value
).then(res => {
vm.$message.success(res['msg'])
}).catch(() => {
}).catch((error) => {
vm.$log.error('err occur')
vm.$refs.baseSms.testPerformError(error)
}).finally(() => { btn.loading = false })
}
}

View File

@@ -23,13 +23,15 @@ export default {
this.$t('applications.port'),
[
'http_port', 'https_port', 'ssh_port', 'rdp_port',
'mysql_port', 'mariadb_port', 'postgresql_port', 'redis_port',
'oracle_11g_port', 'oracle_12c_port'
'magnus_listen_port_range'
]
],
[this.$t('common.Other'), ['comment']]
],
fieldsMeta: {
magnus_listen_port_range: {
disabled: true
}
},
hasDetailInMsg: false
}

View File

@@ -20,17 +20,15 @@ export default {
url: '/api/v1/terminal/endpoints/',
columns: [
'name', 'host',
'http_port', 'https_port', 'ssh_port',
'rdp_port', 'mysql_port', 'mariadb_port',
'postgresql_port', 'redis_port',
'oracle_11g_port', 'oracle_12c_port',
'http_port', 'https_port', 'ssh_port', 'rdp_port',
'magnus_listen_port_range',
'date_created', 'comment', 'actions'
],
columnsShow: {
min: ['name', 'actions'],
default: [
'name', 'host', 'actions',
'http_port', 'https_port', 'ssh_port', 'rdp_port'
'http_port', 'https_port', 'ssh_port', 'rdp_port', 'magnus_listen_port_range'
]
},
columnsMeta: {
@@ -39,9 +37,10 @@ export default {
},
actions: {
formatterArgs: {
canUpdate: this.$hasPerm('terminal.change_endpoint'),
updateRoute: 'EndpointUpdate',
cloneRoute: 'EndpointCreate',
canDelete: ({ row }) => row.id !== '00000000-0000-0000-0000-000000000001'
canDelete: ({ row }) => row.id !== '00000000-0000-0000-0000-000000000001' && this.$hasPerm('terminal.delete_endpoint')
}
}
}

View File

@@ -38,6 +38,7 @@ export default {
},
actions: {
formatterArgs: {
canUpdate: this.$hasPerm('terminal.change_endpointrule'),
updateRoute: 'EndpointRuleUpdate',
cloneRoute: 'EndpointRuleCreate'
}

View File

@@ -236,7 +236,7 @@ export default {
return toSafeLocalDateStr(dataStr)
},
reloadPage() {
window.location.reload()
this.$store.commit('common/reload')
},
handleApprove() {
if (this.object.approval_step === this.object.process_map.length) {

View File

@@ -244,7 +244,7 @@ export default {
return toSafeLocalDateStr(dataStr)
},
reloadPage() {
window.location.reload()
this.$store.commit('common/reload')
},
handleApprove() {
if (this.object.approval_step === this.object.process_map.length) {

View File

@@ -88,7 +88,7 @@ export default {
return toSafeLocalDateStr(dataStr)
},
reloadPage() {
window.location.reload()
this.$store.commit('common/reload')
}
}
}

View File

@@ -199,7 +199,7 @@ export default {
)
},
reloadPage() {
window.location.reload()
this.$store.commit('common/reload')
}
}

View File

@@ -14,7 +14,9 @@ export default {
},
data() {
return {
initial: {},
initial: {
need_update_password: true
},
user: {
'can_public_key_auth': false
},

View File

@@ -115,6 +115,7 @@ export default {
actions: {
formatterArgs: {
hasDelete: hasDelete,
canUpdate: this.$hasPerm('users.change_user'),
extraActions: [
{
title: this.$t('users.Remove'),

View File

@@ -6290,11 +6290,16 @@ jest@^23.6.0:
import-local "^1.0.0"
jest-cli "^23.6.0"
jquery@>=1.4.4, jquery@^3.5.0:
jquery@>=1.4.4:
version "3.5.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.0.tgz#9980b97d9e4194611c36530e7dc46a58d7340fc9"
integrity sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ==
jquery@^3.6.1:
version "3.6.1"
resolved "https://registry.npmmirror.com/jquery/-/jquery-3.6.1.tgz#fab0408f8b45fc19f956205773b62b292c147a16"
integrity sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==
js-base64@^2.1.9:
version "2.5.2"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209"