perf: confirm 优化

This commit is contained in:
feng626
2022-06-20 17:05:00 +08:00
committed by Jiangjie.Bai
parent bb91fbb327
commit f5c7abcbd8
7 changed files with 186 additions and 48 deletions

View File

@@ -1,6 +1,7 @@
<template> <template>
<div> <div>
<UserConfirmDialog <UserConfirmDialog
:url="url"
@UserConfirmDone="getAuthInfo" @UserConfirmDone="getAuthInfo"
@UserConfirmCancel="exit" @UserConfirmCancel="exit"
/> />
@@ -57,13 +58,13 @@ export default {
return { return {
dialogTitle: this.$t('common.ViewSecret'), dialogTitle: this.$t('common.ViewSecret'),
authInfo: {}, authInfo: {},
showAuthInfo: false showAuthInfo: false,
url: `/api/v1/assets/account-secrets/${this.account.id}/`
} }
}, },
methods: { methods: {
getAuthInfo() { getAuthInfo() {
const url = `/api/v1/assets/account-secrets/${this.account.id}/` this.$axios.get(this.url, { disableFlashErrorMsg: true }).then(resp => {
this.$axios.get(url, { disableFlashErrorMsg: true }).then(resp => {
this.authInfo = resp this.authInfo = resp
this.showAuthInfo = true this.showAuthInfo = true
}) })

View File

@@ -1,6 +1,7 @@
<template> <template>
<div> <div>
<UserConfirmDialog <UserConfirmDialog
:url="url"
@UserConfirmDone="getAuthInfo" @UserConfirmDone="getAuthInfo"
@UserConfirmCancel="exit" @UserConfirmCancel="exit"
/> />
@@ -54,13 +55,13 @@ export default {
return { return {
dialogTitle: this.$t('common.ViewSecret'), dialogTitle: this.$t('common.ViewSecret'),
authInfo: {}, authInfo: {},
showAuthInfo: false showAuthInfo: false,
url: `/api/v1/applications/account-secrets/${this.account.id}/`
} }
}, },
methods: { methods: {
getAuthInfo() { getAuthInfo() {
const url = `/api/v1/applications/account-secrets/${this.account.id}/` this.$axios.get(this.url, { disableFlashErrorMsg: true }).then(resp => {
this.$axios.get(url, { disableFlashErrorMsg: true }).then(resp => {
this.authInfo = resp this.authInfo = resp
this.showAuthInfo = true this.showAuthInfo = true
}) })

View File

@@ -1,28 +1,88 @@
<template> <template>
<Dialog <Dialog
:title="$t('common.CurrentUserVerify')" :title="title"
:width="'50'" :width="'36%'"
:show-confirm="false" :show-confirm="false"
:show-cancel="false" :show-cancel="false"
:visible.sync="visible" :visible.sync="visible"
:destroy-on-close="true" :destroy-on-close="true"
v-bind="$attrs" v-bind="$attrs"
class="dialog-content"
v-on="$listeners" v-on="$listeners"
> >
<el-row :gutter="20"> <div v-if="ConfirmType === 'relogin'">
<el-col :md="4" :sm="24"> <el-row :gutter="24" style="margin: 0 auto;">
<div style="line-height: 34px;text-align: center">{{ Label }}</div> <el-col :md="24" :sm="24">
</el-col> <el-alert
<el-col :md="14" :sm="24"> :title="this.$t('auth.ReLoginTitle')"
<el-input v-model="SecretKey" :show-password="showPassword" /> type="info"
<span class="help-tips help-block">{{ HelpText }}</span> center
</el-col> :closable="false"
<el-col :md="4" :sm="24"> style="margin-bottom: 20px;"
<el-button size="mini" type="primary" style="line-height:20px " @click="userConfirm"> />
{{ this.$t('common.Confirm') }} </el-col>
</el-button> </el-row>
</el-col> <el-row :gutter="24" style="margin: 0 auto;">
</el-row> <el-col :md="24" :sm="24">
<el-button
size="mini"
type="primary"
style="width: 100%; line-height:20px;"
@click="logOut"
>
{{ this.$t('auth.ReLogin') }}
</el-button>
</el-col>
</el-row>
</div>
<div v-else>
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :span="24" :md="24" :sm="24" class="add">
<el-select
v-model="Select"
:disabled="ConfirmType === 'password'"
style="width: 100%; margin-bottom: 20px;"
@change="helpText(Select)"
>
<el-option
v-for="(item, i) of Content"
:key="i"
:label="item.display_name"
:value="item.name"
:disabled="item.disabled"
/>
</el-select>
</el-col>
</el-row>
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24 - smsWidth" :sm="24">
<el-input v-model="SecretKey" :show-password="showPassword" :placeholder="HelpText" style="margin-bottom: 20px;" />
</el-col>
<el-col v-if="Select === 'sms'" :md="smsWidth" :sm="24">
<el-button
size="mini"
type="primary"
style="line-height:20px; float: right;"
:disabled="smsBtndisabled"
@click="sendChallengeCode"
>
{{ smsBtnText }}
</el-button>
</el-col>
</el-row>
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24">
<el-button
size="mini"
type="primary"
style="width: 100%; line-height:20px;"
@click="userConfirm"
>
{{ this.$t('common.Confirm') }}
</el-button>
</el-col>
</el-row>
</div>
</Dialog> </Dialog>
</template> </template>
<script> <script>
@@ -33,11 +93,23 @@ export default {
components: { components: {
Dialog Dialog
}, },
props: {
url: {
type: String,
default: () => ''
}
},
data() { data() {
return { return {
Label: '', title: '',
smsWidth: 0,
Select: '',
Level: null,
HelpText: '', HelpText: '',
smsBtnText: '',
smsBtndisabled: false,
ConfirmType: '', ConfirmType: '',
Content: null,
SecretKey: '', SecretKey: '',
visible: false visible: false
} }
@@ -59,37 +131,72 @@ export default {
} }
}, },
mounted() { mounted() {
this.$axios.get('/api/v1/authentication/confirm/', { disableFlashErrorMsg: true }).then(() => { this.smsBtnText = this.$t('common.SendVerificationCode')
this.$emit('UserConfirmDone', true) this.$axios.get(`${this.url}`, { disableFlashErrorMsg: true }).then(
}).catch(err => { () => { this.$emit('UserConfirmDone', true) }).catch((err) => {
this.$log.debug('Verify otp code error: ', err) const confirm_type = err.response.data.code
const backends = err.response.data.backends this.$axios.get('/api/v1/authentication/confirm/', { params: { confirm_type: confirm_type }}).then((data) => {
backends.sort((a, b) => b.level - a.level) this.ConfirmType = data.confirm_type
this.ConfirmType = backends[0].name this.Content = data.content
if (this.ConfirmType === 'relogin') { if (this.ConfirmType === 'relogin') {
this.visible = false this.title = this.$t('auth.NeedReLogin')
return this.$message.error(this.$t('auth.ReLoginErr')) this.visible = true
} return
}
if (this.ConfirmType === 'mfa') { if (this.ConfirmType === 'mfa') {
this.Label = 'MFA' this.Select = this.Content.filter(item => !item.disabled)[0].name
this.HelpText = this.$t('common.MFARequireForSecurity') 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.visible = true this.visible = true
} else if (this.ConfirmType === 'password') { })
this.Label = this.$t('setting.password')
this.HelpText = this.$t('common.PasswordRequireForSecurity')
this.visible = true
}
}) })
}, },
methods: { 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() {
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'))
let time = 60
const interval = setInterval(() => {
this.smsBtnText = this.$t('common.Pending') + `: ${time}`
this.smsBtndisabled = true
time -= 1
if (time === 0) {
this.smsBtnText = this.$t('common.SendVerificationCode')
this.smsBtndisabled = false
clearInterval(interval)
}
}, 1000)
})
},
userConfirm() { userConfirm() {
if (this.ConfirmType === 'mfa' && this.SecretKey.length !== 6) { if (this.Select === 'otp' && this.SecretKey.length !== 6) {
return this.$message.error(this.$tc('common.MFAErrorMsg')) return this.$message.error(this.$t('common.MFAErrorMsg'))
} }
this.$axios.post( this.$axios.post(
`/api/v1/authentication/confirm/`, { `/api/v1/authentication/confirm/`, {
confirm_type: this.ConfirmType, confirm_type: this.ConfirmType,
mfa_type: this.ConfirmType === 'password' ? undefined : this.Select,
secret_key: this.SecretKey secret_key: this.SecretKey
} }
).then(res => { ).then(res => {
@@ -100,6 +207,12 @@ export default {
} }
</script> </script>
<style scoped> <style lang="scss" scoped>
.dialog-content >>> .el-dialog__footer{
padding: 0;
}
.dialog-content >>> .el-dialog{
padding: 8px;
}
</style> </style>

View File

@@ -247,9 +247,13 @@
"auth": { "auth": {
"LoginRequiredMsg": "You account has logout, Please login again", "LoginRequiredMsg": "You account has logout, Please login again",
"ReLogin": "Re-Login", "ReLogin": "Re-Login",
"ReLoginTitle": "The current three-party login user (cas/saml) is not bound to MFA and does not support password verification. Please login again",
"NeedReLogin": "Need Re-Login",
"ReLoginErr": "Login time has exceeded 5 minutes, please login again" "ReLoginErr": "Login time has exceeded 5 minutes, please login again"
}, },
"common": { "common": {
"VerificationCodeSent": "The verification code has been sent",
"SendVerificationCode": "Send verification code",
"ChangeViewHelpText": "Click to change view", "ChangeViewHelpText": "Click to change view",
"Component": "component", "Component": "component",
"PrivateCloud": "Private cloud", "PrivateCloud": "Private cloud",

View File

@@ -252,9 +252,13 @@
"auth": { "auth": {
"LoginRequiredMsg": "アカウントが終了しました。ログインし直してください", "LoginRequiredMsg": "アカウントが終了しました。ログインし直してください",
"ReLogin": "再ログイン", "ReLogin": "再ログイン",
"ReLoginTitle": "現在、サードパーティのログインユーザーCAS/SAMLは、MFAをバインドしておらず、パスワードチェックをサポートしていません。再ログインしてください。",
"NeedReLogin": "再ログインが必要です",
"ReLoginErr": "ログイン時間が 5 分を超えました。もう一度ログインしてください" "ReLoginErr": "ログイン時間が 5 分を超えました。もう一度ログインしてください"
}, },
"common": { "common": {
"VerificationCodeSent": "検証コードが送信されました",
"SendVerificationCode": "認証コードの送信",
"ChangeViewHelpText": "クリックしてさまざまなビューにアクセス", "ChangeViewHelpText": "クリックしてさまざまなビューにアクセス",
"Component": "コンポーネント", "Component": "コンポーネント",
"PrivateCloud": "プライベートクラウド", "PrivateCloud": "プライベートクラウド",

View File

@@ -252,9 +252,13 @@
"auth": { "auth": {
"LoginRequiredMsg": "账号已退出,请重新登录", "LoginRequiredMsg": "账号已退出,请重新登录",
"ReLogin": "重新登录", "ReLogin": "重新登录",
"ReLoginTitle": "当前三方登录用户CAS/SAML未绑定 MFA 且不支持密码校验,请重新登录。",
"NeedReLogin": "需要重新登录",
"ReLoginErr": "登录时长已超过 5 分钟,请重新登录" "ReLoginErr": "登录时长已超过 5 分钟,请重新登录"
}, },
"common": { "common": {
"VerificationCodeSent": "验证码已发送",
"SendVerificationCode": "发送验证码",
"ChangeViewHelpText": "点击切换不同视图", "ChangeViewHelpText": "点击切换不同视图",
"Component": "组件", "Component": "组件",
"PrivateCloud": "私有云", "PrivateCloud": "私有云",

View File

@@ -2,6 +2,7 @@
<Page v-bind="$attrs"> <Page v-bind="$attrs">
<UserConfirmDialog <UserConfirmDialog
v-if="showPasswordDialog" v-if="showPasswordDialog"
:url="confirmUrl"
:visible.sync="showPasswordDialog" :visible.sync="showPasswordDialog"
@UserConfirmDone="verifyDone" @UserConfirmDone="verifyDone"
@UserConfirmCancel="exit" @UserConfirmCancel="exit"
@@ -284,6 +285,15 @@ export default {
key: this.$t('users.Comment') key: this.$t('users.Comment')
} }
] ]
},
confirmUrl() {
let url = ''
if (!this.object[`is_${this.currentEdit}_bound`]) {
url = `/core/auth/${this.currentEdit}/qr/bind/?redirect_url=${this.$route.fullPath}`
} else {
url = `/api/v1/authentication/${this.currentEdit}/qr/unbind/`
}
return url
} }
}, },
methods: { methods: {
@@ -309,10 +319,11 @@ export default {
return backendList return backendList
}, },
verifyDone() { verifyDone() {
const url = this.confirmUrl
if (!this.object[`is_${this.currentEdit}_bound`]) { if (!this.object[`is_${this.currentEdit}_bound`]) {
window.location.href = `/core/auth/${this.currentEdit}/qr/bind/?redirect_url=${this.$route.fullPath}` window.location.href = url
} else { } else {
this.$axios.post(`/api/v1/authentication/${this.currentEdit}/qr/unbind/`).then(res => { this.$axios.post(url).then(res => {
this.$message.success(this.$t('common.updateSuccessMsg')) this.$message.success(this.$t('common.updateSuccessMsg'))
this.$store.dispatch('users/getProfile') this.$store.dispatch('users/getProfile')
}) })