You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ha...@apache.org on 2022/11/24 03:43:42 UTC

[cloudstack] 01/03: Some improvements of messages in UI

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 <ha...@gmail.com>
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;
   }