This is an automated email from the ASF dual-hosted git repository. harikrishna pushed a commit to branch 2FA in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 1fbf35312717b8e72e5f6626bfe8e30095581e81 Author: Harikrishna Patnala <[email protected]> AuthorDate: Thu Nov 24 00:14:56 2022 +0530 Some improvements of messages in UI --- ui/public/locales/en.json | 21 ++-- ui/src/config/section/user.js | 2 +- ui/src/views/iam/RegisterTwoFactorAuth.vue | 171 +++++++++++++++++------------ 3 files changed, 115 insertions(+), 79 deletions(-) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 3031569654e..7f085b22490 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -137,8 +137,7 @@ "label.action.reboot.systemvm": "Reboot system VM", "label.action.recover.volume": "Recover volume", "label.action.recurring.snapshot": "Recurring snapshots", -"label.action.register.2FA.user.auth": "Register user Two Factor Authentication", -"label.action.disable.2FA.user.auth": "Disable user Two Factor Authentication", +"label.action.disable.2FA.user.auth": "Disable User Two Factor Authentication", "label.action.register.iso": "Register ISO", "label.action.register.template": "Register template from URL", "label.action.release.ip": "Release IP", @@ -153,6 +152,7 @@ "label.action.router.health.checks": "Get health checks result", "label.action.run.diagnostics": "Run diagnostics", "label.action.secure.host": "Provision host security keys", +"label.action.setup.2FA.user.auth": "Setup User Two Factor Authentication", "label.action.start.instance": "Start instance", "label.action.start.router": "Start router", "label.action.start.systemvm": "Start system VM", @@ -678,7 +678,8 @@ "label.endipv6": "IPv6 end IP", "label.endpoint": "Endpoint", "label.endport": "End port", -"label.enter.code": "Enter authentication code to verify", +"label.enter.code": "Enter 2FA code to verify", +"label.enter.static.pin": "Enter static pin to verify", "label.enter.token": "Enter token", "label.error": "Error", "label.error.caught": "Error caught", @@ -1738,7 +1739,8 @@ "label.transportzoneuuid": "Transport zone UUID", "label.try.again": "Try again", "label.tuesday": "Tuesday", -"label.two.factor.secret": "Your Two-factor secret", +"label.two.factor.authentication.secret.key": "Your Two factor authentication secret key", +"label.two.factor.authentication.static.pin": "Your Two factor authentication static pin", "label.two.factor.authentication": "Two Factor Authentication", "label.type": "Type", "label.type.id": "Type ID", @@ -1947,7 +1949,7 @@ "message.action.destroy.instance.with.backups": "Please confirm that you want to destroy the instance. There may be backups associated with the instance which will not be deleted.", "message.action.destroy.systemvm": "Please confirm that you want to destroy the System VM.", "message.action.destroy.volume": "Please confirm that you want to destroy the volume.", -"message.action.disable.2FA.user.auth": "Please confirm that you want to disable user Two factor authentication.", +"message.action.disable.2FA.user.auth": "Please confirm that you want to disable user two factor authentication.", "message.action.disable.cluster": "Please confirm that you want to disable this cluster.", "message.action.disable.physical.network": "Please confirm that you want to disable this physical network.", "message.action.disable.pod": "Please confirm that you want to disable this pod.", @@ -2586,10 +2588,11 @@ "message.template.type.change.warning": "WARNING: Changing the template type to SYSTEM will disable further changes to the template.", "message.tooltip.reserved.system.netmask": "The network prefix that defines the pod subnet. Uses CIDR notation.", "message.traffic.type.to.basic.zone": "traffic type to basic zone", -"message.two.fa.auth": "Open the two-factor authentication app on your mobile device to view your authentication code", -"message.two.fa.auth.register.account": "Open the two-factor authentication application and scan the QR code add the user account", -"message.two.fa.static.pin.part1": "If you can't scan the QR code, ", -"message.two.fa.static.pin.part2": "Click here to view the secret code", +"message.two.fa.auth": "Open the two factor authentication application on your device to view your authentication code", +"message.two.fa.register.account": "1. Open the authenticator application on your device <br>2. Scan the below QR code to add the user <br>3. If you cannot scan the QR code, enter the setup key manually <br>4. Verification of the 2FA code is mandatory to complete the 2FA setup", +"message.two.fa.staticpin": "1. Use the generated static pin as 2FA code for two factor authentication<br>2. Verification of the 2FA code is mandatory to complete the 2FA setup", +"message.two.fa.view.setup.key": "Click here to view the setup key", +"message.two.fa.view.static.pin": "Click here to view the static pin", "message.update.ipaddress.processing": "Updating IP Address...", "message.update.resource.count": "Please confirm that you want to update resource counts for this account.", "message.update.resource.count.domain": "Please confirm that you want to update resource counts for this domain.", diff --git a/ui/src/config/section/user.js b/ui/src/config/section/user.js index c7fe2a7606d..5936f387dd6 100644 --- a/ui/src/config/section/user.js +++ b/ui/src/config/section/user.js @@ -109,7 +109,7 @@ export default { { api: 'setupUserTwoFactorAuthentication', icon: 'scan-outlined', - label: 'label.action.register.2FA.user.auth', + label: 'label.action.setup.2FA.user.auth', dataView: true, popup: true, show: (record, store) => { diff --git a/ui/src/views/iam/RegisterTwoFactorAuth.vue b/ui/src/views/iam/RegisterTwoFactorAuth.vue index 388e7fa3173..5887789256e 100644 --- a/ui/src/views/iam/RegisterTwoFactorAuth.vue +++ b/ui/src/views/iam/RegisterTwoFactorAuth.vue @@ -17,67 +17,72 @@ <template> <div style="width:500px;height=500px"> - <h3> {{ $t('label.select.2fa.provider') }} </h3> - <a-form - :rules="rules" - layout="vertical"> - <div class="form-layout" v-ctrl-enter="submitPin"> - <a-select - v-model:value="selectedProvider" - optionFilterProp="label" - :filterOption="(input, option) => { - return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0 - }" - style="width: 100%" - @change="val => { handleSelectChange(val) }"> - <a-select-option - v-for="(opt) in providers" - :key="opt.name" - :disabled="opt.enabled === false"> - {{ opt.name }} - </a-select-option> - </a-select> - </div> - <div v-if="show2FAdetails"> - <div v-if="selectedProvider === 'google'"> - <br /> - <div> {{ $t('message.two.fa.auth.register.account') }} </div> - <vue-qrious - class="center-align" - :value="googleUrl" - @change="onDataUrlChange" - /> - </div> - <div v-else-if="selectedProvider === 'staticpin'"> - <div> <a @click="setup2FAProvider"> {{ $t('message.two.fa.static.pin.part2') }}</a></div> - </div> - <div v-else-if="selectedProvider !== null && selectedProvider !== 'staticpin'"> - <div> {{ $t('message.two.fa.static.pin.part1') }} <a @click="setup2FAProvider"> {{ $t('message.two.fa.static.pin.part2') }}</a></div> - </div> - <div v-if="selectedProvider"> - <br /> - <h3> {{ $t('label.enter.code') }} </h3> - <a-form @finish="submitPin" v-ctrl-enter="submitPin" class="container"> - <a-input v-model:value="code" /> - <div :span="24"> - <a-button ref="submit" type="primary" @click="submitPin">{{ $t('label.ok') }}</a-button> - </div> - </a-form> + <h3> {{ $t('label.select.2fa.provider') }} </h3> + <a-form + :rules="rules" + @close="onCloseModalDisable2FA()" + layout="vertical"> + <div class="form-layout form-align" v-ctrl-enter="submitPin"> + <a-select + v-model:value="selectedProvider" + optionFilterProp="label" + :filterOption="(input, option) => { + return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0 + }" + style="width: 100%" + @change="val => { handleSelectChange(val) }"> + <a-select-option + v-for="(opt) in providers" + :key="opt.name" + :disabled="opt.enabled === false"> + {{ opt.name }} + </a-select-option> + </a-select> + <div :span="24" v-if="selectedProvider"> + <a-button ref="submit" type="primary" @click="setup2FAProvider">{{ $t('label.setup') }}</a-button> + </div> </div> + <div v-if="show2FAdetails"> + <div v-if="selectedProvider !== 'staticpin'"> + <br /> + <p v-html="$t('message.two.fa.register.account')"></p> + <vue-qrious + class="center-align" + :value="googleUrl" + @change="onDataUrlChange" + /> + <div style="text-align: center"> <a @click="showConfiguredPin"> {{ $t('message.two.fa.view.setup.key') }}</a></div> + </div> + <div v-if="selectedProvider === 'staticpin'"> + <br> + <p v-html="$t('message.two.fa.staticpin')"></p> + <br> + <div> <a @click="showConfiguredPin"> {{ $t('message.two.fa.view.static.pin') }}</a></div> + </div> + <div v-if="selectedProvider"> + <br /> + <h3> {{ $t('label.enter.code') }} </h3> + <a-form @finish="submitPin" v-ctrl-enter="submitPin" class="container"> + <a-input v-model:value="code" /> + <div :span="24"> + <a-button ref="submit" type="primary" @click="submitPin">{{ $t('label.ok') }}</a-button> + </div> + </a-form> + </div> - <a-modal - v-if="showPin" - :visible="showPin" - :title="$t('label.two.factor.secret')" - :closable="true" - :footer="null" - @cancel="onCloseModal" - centered - width="450px"> - <div> {{ pin }} </div> - </a-modal> - </div> - </a-form> + <a-modal + v-if="showPin" + :visible="showPin" + :title="$t(selectedProvider === 'staticpin'? 'label.two.factor.authentication.static.pin' : 'label.two.factor.authentication.secret.key')" + :closable="true" + :footer="null" + @cancel="onCloseModal" + centered + width="450px"> + <div> {{ pin }} </div> + </a-modal> + </div> + </a-form> </div> </template> <script> @@ -103,6 +108,7 @@ export default { code: '', showPin: false, show2FAdetails: false, + twoFAenabled: false, providers: [], selectedProvider: null } @@ -116,18 +122,35 @@ export default { }, handleSelectChange (val) { this.selectedProvider = val - this.setup2FAProvider() }, setup2FAProvider () { - api('setupUserTwoFactorAuthentication', { provider: this.selectedProvider }).then(response => { - console.log(response) - this.pin = response.setupusertwofactorauthenticationresponse.setup2fa.secretcode - if (this.selectedProvider === 'google') { - this.username = response.setupusertwofactorauthenticationresponse.setup2fa.username - this.googleUrl = 'otpauth://totp/CloudStack:' + this.username + '?secret=' + this.pin + '&issuer=CloudStack' - } - this.showPin = true - this.show2FAdetails = true + if (!this.twoFAenabled) { + api('setupUserTwoFactorAuthentication', { provider: this.selectedProvider }).then(response => { + console.log(response) + this.pin = response.setupusertwofactorauthenticationresponse.setup2fa.secretcode + if (this.selectedProvider === 'google') { + this.username = response.setupusertwofactorauthenticationresponse.setup2fa.username + this.googleUrl = 'otpauth://totp/CloudStack:' + this.username + '?secret=' + this.pin + '&issuer=CloudStack' + this.showPin = false + } + if (this.selectedProvider === 'staticpin') { + this.showPin = true + } + this.show2FAdetails = true + this.twoFAenabled = true + }).catch(error => { + this.$notification.error({ + message: this.$t('message.request.failed'), + description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message + }) + }) + } + }, + disable2FAProvider () { + api('setupUserTwoFactorAuthentication', { enable: false }).then(response => { + this.showPin = false + this.show2FAdetails = false + this.twoFAenabled = false }).catch(error => { this.$notification.error({ message: this.$t('message.request.failed'), @@ -158,8 +181,14 @@ export default { closeAction () { this.$emit('close-action') }, + showConfiguredPin () { + this.showPin = true + }, onCloseModal () { this.showPin = false + }, + onCloseModalDisable2FA () { + this.disable2FAProvider() } } } @@ -171,6 +200,10 @@ export default { margin-left: auto; margin-right: auto; } + .form-align { + display: flex; + flex-direction: row; + } .container { display: flex; }
