Skip to content

Commit

Permalink
Merge pull request #3450 from jumpserver/dev
Browse files Browse the repository at this point in the history
v3.8.0
  • Loading branch information
BaiJiangJie authored Oct 19, 2023
2 parents b54a954 + 3a66e83 commit 5fb70d2
Show file tree
Hide file tree
Showing 50 changed files with 661 additions and 412 deletions.
20 changes: 7 additions & 13 deletions src/components/Apps/AccountListTable/ViewSecret.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
<template>
<div>
<div v-if="mfaDialogVisible">
<UserConfirmDialog
:url="url"
@UserConfirmCancel="exit"
@UserConfirmDone="getAuthInfo"
/>
</div>
<Dialog
:destroy-on-close="true"
:show-cancel="false"
Expand Down Expand Up @@ -67,7 +60,6 @@
<script>
import Dialog from '@/components/Dialog/index.vue'
import PasswordHistoryDialog from './PasswordHistoryDialog.vue'
import UserConfirmDialog from '@/components/Apps/UserConfirmDialog/index.vue'
import { ShowKeyCopyFormatter } from '@/components/Table/TableFormatters'
import { encryptPassword } from '@/utils/crypto'
Expand All @@ -76,7 +68,6 @@ export default {
components: {
Dialog,
PasswordHistoryDialog,
UserConfirmDialog,
ShowKeyCopyFormatter
},
props: {
Expand Down Expand Up @@ -128,7 +119,10 @@ export default {
const url = `/api/v1/accounts/account-secrets/${this.account.id}/histories/?limit=1`
this.$axios.get(url, { disableFlashErrorMsg: true }).then(resp => {
this.versions = resp.count
this.showSecretDialog()
})
} else {
this.showSecretDialog()
}
},
methods: {
Expand All @@ -146,10 +140,10 @@ export default {
this.$message.success(this.$tc('common.updateSuccessMsg'))
})
},
getAuthInfo() {
this.$axios.get(this.url, { disableFlashErrorMsg: true }).then(resp => {
this.secretInfo = resp
this.sshKeyFingerprint = resp?.spec_info?.ssh_key_fingerprint || '-'
showSecretDialog() {
return this.$axios.get(this.url, { disableFlashErrorMsg: true }).then((res) => {
this.secretInfo = res
this.sshKeyFingerprint = res?.spec_info?.ssh_key_fingerprint || '-'
this.showSecret = true
})
},
Expand Down
1 change: 0 additions & 1 deletion src/components/Apps/AutomationParams/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ export default {
},
async mounted() {
await this.getUrlMeta()
await this.handleFieldChange()
},
methods: {
async getUrlMeta() {
Expand Down
218 changes: 105 additions & 113 deletions src/components/Apps/UserConfirmDialog/index.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
<template>
<Dialog
:destroy-on-close="true"
:close-on-click-modal="false"
:destory-on-close="true"
:show-cancel="false"
:show-confirm="false"
:title="title"
:visible.sync="visible"
:width="'36%'"
class="dialog-content"
v-bind="$attrs"
width="600px"
@confirm="visible = false"
v-on="$listeners"
>
<div v-if="ConfirmType === 'relogin'">
<div v-if="confirmTypeRequired === 'relogin'">
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24">
<el-alert
:closable="false"
:title="$tc('auth.ReLoginTitle')"
center
style="margin-bottom: 20px;"
type="info"
type="error"
/>
</el-col>
</el-row>
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24">
<el-button
size="mini"
style="width: 100%; line-height:20px;"
type="primary"
@click="logOut"
>
<el-button class="confirm-btn" size="mini" type="primary" @click="logout">
{{ this.$t('auth.ReLogin') }}
</el-button>
</el-col>
Expand All @@ -39,14 +35,13 @@
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24" :span="24" class="add">
<el-select
v-model="Select"
:disabled="ConfirmType === 'password'"
v-model="subTypeSelected"
style="width: 100%; margin-bottom: 20px;"
@change="helpText(Select)"
@change="handleSubTypeChange"
>
<el-option
v-for="(item, i) of Content"
:key="i"
v-for="item of subTypeChoices"
:key="item.name"
:disabled="item.disabled"
:label="item.display_name"
:value="item.name"
Expand All @@ -56,28 +51,23 @@
</el-row>
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24" style="display: flex; margin-bottom: 20px;">
<el-input v-model="SecretKey" :placeholder="HelpText" :show-password="showPassword" />
<span v-if="Select === 'sms'" style="margin: -1px 0 0 20px;">
<el-input v-model="secretValue" :placeholder="inputPlaceholder" :show-password="showPassword" />
<span v-if="subTypeSelected === 'sms'" style="margin: -1px 0 0 20px;">
<el-button
:disabled="smsBtndisabled"
:disabled="smsBtnDisabled"
size="mini"
style="line-height:20px; float: right;"
type="primary"
@click="sendChallengeCode"
@click="sendSMSCode"
>
{{ smsBtnText }}
</el-button>
</span>
</el-col>
</el-row>
<el-row :gutter="24" style="margin: 0 auto;">
<el-row :gutter="24" style="margin: 10px auto;">
<el-col :md="24" :sm="24">
<el-button
size="mini"
style="width: 100%; line-height:20px;"
type="primary"
@click="userConfirm"
>
<el-button class="confirm-btn" size="mini" type="primary" @click="handleConfirm">
{{ this.$t('common.Confirm') }}
</el-button>
</el-col>
Expand All @@ -96,125 +86,116 @@ export default {
props: {
url: {
type: String,
default: () => ''
default: ''
},
handler: {
type: Function,
default: null
}
},
data() {
return {
title: '',
title: this.$t('common.CurrentUserVerify'),
smsWidth: 0,
Select: '',
Level: null,
HelpText: '',
smsBtnText: '',
smsBtndisabled: false,
ConfirmType: '',
Content: null,
SecretKey: '',
visible: false
subTypeSelected: '',
inputPlaceholder: '',
smsBtnText: this.$t('common.SendVerificationCode'),
smsBtnDisabled: false,
confirmTypeRequired: '',
subTypeChoices: [],
secretValue: '',
visible: false,
callback: null,
cancel: null,
processing: false
}
},
computed: {
showPassword() {
if (this.ConfirmType === 'password') {
return true
}
return false
}
},
watch: {
visible(val) {
if (!val) {
this.$emit('UserConfirmCancel', true)
}
return this.confirmTypeRequired === 'password'
}
},
mounted() {
this.smsBtnText = this.$t('common.SendVerificationCode')
this.$axios.get(`${this.url}`, { disableFlashErrorMsg: true }).then(
() => { this.$emit('UserConfirmDone', true) }).catch((err) => {
const confirm_type = err.response.data.code
this.$axios.get('/api/v1/authentication/confirm/', { params: { confirm_type: confirm_type }}).then((data) => {
this.ConfirmType = data.confirm_type
this.Content = data.content
if (this.ConfirmType === 'relogin') {
this.$axios.post(
`/api/v1/authentication/confirm/`,
{
confirm_type: this.ConfirmType,
secret_key: ''
},
{ disableFlashErrorMsg: true },
).then(() => { this.$emit('UserConfirmDone', true) }).catch(() => {
// const onRecvCallback = _.debounce(this.performConfirm, 500)
this.$eventBus.$on('showConfirmDialog', this.performConfirm)
},
methods: {
handleSubTypeChange(val) {
this.inputPlaceholder = this.subTypeChoices.filter(item => item.name === val)[0]?.placeholder
this.smsWidth = val === 'sms' ? 6 : 0
},
performConfirm({ response, callback, cancel }) {
if (this.processing || this.visible) {
return
}
this.processing = true
this.callback = callback
this.cancel = cancel
this.$log.debug('perform confirm action')
const confirmType = response.data?.code
const confirmUrl = '/api/v1/authentication/confirm/'
this.$axios.get(confirmUrl, { params: { confirm_type: confirmType }}).then((data) => {
this.confirmTypeRequired = data.confirm_type
if (this.confirmTypeRequired === 'relogin') {
this.$axios.post(confirmUrl, { 'confirm_type': 'relogin', 'secret_key': 'x' }).then(() => {
this.callback()
this.visible = false
}).catch(() => {
this.title = this.$t('auth.NeedReLogin')
this.visible = true
})
return
}
if (this.ConfirmType === 'mfa') {
this.Select = this.Content.filter(item => !item.disabled)[0].name
if (this.Select === 'sms') {
this.smsWidth = 6
}
this.HelpText = this.Content.filter(item => !item.disabled)[0].placeholder
} else if (this.ConfirmType === 'password') {
this.Select = this.$t('setting.password')
this.HelpText = this.$t('common.PasswordRequireForSecurity')
this.Content = [{ 'name': 'password' }]
}
this.title = this.$t('common.CurrentUserVerify')
this.subTypeChoices = data.content
const defaultSubType = this.subTypeChoices.filter(item => !item.disabled)[0]
this.subTypeSelected = defaultSubType.name
this.inputPlaceholder = defaultSubType.placeholder
this.visible = true
}).catch(() => {
this.$emit('AuthMFAError', true)
}).catch((err) => {
const data = err.response?.data
const msg = data?.error || data?.detail || data?.msg || this.$t('common.GetConfirmTypeFailed')
this.$message.error(msg)
this.cancel(err)
}).finally(() => {
this.processing = false
})
})
},
methods: {
helpText(val) {
this.HelpText = this.Content.filter(item => item.name === val)[0]?.placeholder
if (val === 'sms') {
this.smsWidth = 6
} else {
this.smsWidth = 0
}
},
logOut() {
logout() {
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${this.$route.fullPath}`
},
sendChallengeCode() {
this.$axios.post(
`/api/v1/authentication/mfa/select/`, {
type: 'sms'
}
).then(res => {
this.$message.success(this.$t('common.VerificationCodeSent'))
sendSMSCode() {
this.$axios.post(`/api/v1/authentication/mfa/select/`, { type: 'sms' }).then(res => {
this.$message.success(this.$tc('common.VerificationCodeSent'))
let time = 60
const interval = setInterval(() => {
const originText = this.smsBtnText
this.smsBtnText = this.$t('common.Pending') + `: ${time}`
this.smsBtndisabled = true
this.smsBtnDisabled = true
time -= 1
if (time === 0) {
this.smsBtnText = this.$t('common.SendVerificationCode')
this.smsBtndisabled = false
this.smsBtnText = originText
this.smsBtnDisabled = false
clearInterval(interval)
}
}, 1000)
})
},
userConfirm() {
if (this.Select === 'otp' && this.SecretKey.length !== 6) {
return this.$message.error(this.$t('common.MFAErrorMsg'))
handleConfirm() {
if (this.confirmTypeRequired === 'relogin') {
return this.logout()
}
this.$axios.post(
`/api/v1/authentication/confirm/`, {
confirm_type: this.ConfirmType,
mfa_type: this.ConfirmType === 'password' ? undefined : this.Select,
secret_key: this.SecretKey
}
).then(res => {
this.$emit('UserConfirmDone', true)
if (this.subTypeSelected === 'otp' && this.secretValue.length !== 6) {
return this.$message.error(this.$tc('common.MFAErrorMsg'))
}
const data = {
confirm_type: this.confirmTypeRequired,
mfa_type: this.confirmTypeRequired === 'mfa' ? this.subTypeSelected : '',
secret_key: this.secretValue
}
this.$axios.post(`/api/v1/authentication/confirm/`, data).then(res => {
this.callback()
this.visible = false
})
}
}
Expand All @@ -228,5 +209,16 @@ export default {
.dialog-content >>> .el-dialog {
padding: 8px;
.el-dialog__body {
padding-top: 30px;
padding-bottom: 30px;
}
}
.confirm-btn {
width: 100%;
line-height: 20px;
}
</style>
Loading

0 comments on commit 5fb70d2

Please sign in to comment.