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 07:31:59 UTC

[cloudstack] 02/02: Added Disable 2FA on form closure

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 9e1aea878b75f22dbcd97eab1d57f0ecb0460248
Author: Harikrishna Patnala <ha...@gmail.com>
AuthorDate: Thu Nov 24 12:57:51 2022 +0530

    Added Disable 2FA on form closure
---
 ui/src/views/AutogenView.vue               |   8 +-
 ui/src/views/dashboard/VerifyTwoFa.vue     | 172 +++++++++++++++++++++++++++++
 ui/src/views/iam/RegisterTwoFactorAuth.vue |  21 ++--
 3 files changed, 191 insertions(+), 10 deletions(-)

diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue
index 85c90e6c3a6..5450191dc8b 100644
--- a/ui/src/views/AutogenView.vue
+++ b/ui/src/views/AutogenView.vue
@@ -117,7 +117,7 @@
           :maskClosable="false"
           :cancelText="$t('label.cancel')"
           style="top: 20px;"
-          @cancel="closeAction"
+          @cancel="cancelAction"
           :confirmLoading="actionLoading"
           :footer="null"
           centered
@@ -161,7 +161,7 @@
         :ok-button-props="getOkProps()"
         :cancel-button-props="getCancelProps()"
         :confirmLoading="actionLoading"
-        @cancel="closeAction"
+        @cancel="cancelAction"
         centered
       >
         <template #title>
@@ -992,6 +992,10 @@ export default {
       this.showAction = false
       this.currentAction = {}
     },
+    cancelAction () {
+      eventBus.emit('action-closing', { action: this.currentAction })
+      this.closeAction()
+    },
     onRowSelectionChange (selection) {
       this.selectedRowKeys = selection
       if (selection?.length > 0) {
diff --git a/ui/src/views/dashboard/VerifyTwoFa.vue b/ui/src/views/dashboard/VerifyTwoFa.vue
new file mode 100644
index 00000000000..acbd87170a5
--- /dev/null
+++ b/ui/src/views/dashboard/VerifyTwoFa.vue
@@ -0,0 +1,172 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+<template>
+  <a-form>
+    <img
+      v-if="$config.banner"
+      :style="{
+        width: $config.theme['@banner-width'],
+        height: $config.theme['@banner-height']
+      }"
+      :src="$config.banner"
+      class="user-layout-logo"
+      alt="logo">
+    <h1 style="text-align: center; font-size: 24px; color: gray"> {{ $t('label.two.factor.authentication') }} </h1>
+    <br />
+    <br />
+    <a-form
+      :ref="formRef"
+      :model="form"
+      :rules="rules"
+      @finish="handleSubmit"
+      layout="vertical">
+      <a-form-item name="code" ref="code">
+        <a-input
+          class="center-align"
+          style="width: 400px"
+          v-model:value="form.code"
+          placeholder="xxxxxxx" />
+      </a-form-item>
+      <div :span="24" class="center-align top-padding">
+          <a-button
+            :loading="loading"
+            ref="submit"
+            type="primary"
+            class="center-align"
+            @click="handleSubmit">{{ $t('label.verify') }}
+          </a-button>
+        </div>
+      <p style="text-align: center" v-html="$t('message.two.fa.auth')"></p>
+    </a-form>
+  </a-form>
+</template>
+<script>
+
+import { api } from '@/api'
+import { ref, reactive, toRaw } from 'vue'
+
+export default {
+  name: 'TwoFa',
+  data () {
+    return {
+      twoFAresponse: false
+    }
+  },
+  created () {
+    this.initForm()
+  },
+  methods: {
+    initForm () {
+      this.formRef = ref()
+      this.form = reactive({})
+      this.rules = reactive({
+        code: [{ required: true, message: this.$t('message.error.authentication.code') }]
+      })
+    },
+    handleSubmit () {
+      this.formRef.value.validate().then(() => {
+        const values = toRaw(this.form)
+        api('validateUserTwoFactorAuthenticationCode', { '2facode': values.code }).then(response => {
+          this.twoFAresponse = true
+          if (this.twoFAresponse) {
+            this.$notification.destroy()
+            this.$store.commit('SET_COUNT_NOTIFY', 0)
+            this.$store.commit('SET_LOGIN_FLAG', true)
+            this.$router.push({ path: '/dashboard' }).catch(() => {})
+
+            this.$message.success({
+              content: `${this.$t('label.action.enable.two.factor.authentication')}`,
+              duration: 2
+            })
+            this.$emit('refresh-data')
+          }
+          console.log(response)
+        }).catch(error => {
+          this.$notification.error({
+            message: this.$t('message.request.failed'),
+            description: (error.response && error.response.headers && error.response.headers['x-description']) || error.message
+          })
+        })
+      })
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+  .center-align {
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+  }
+  .top-padding {
+    padding-top: 35px;
+  }
+  .note {
+    text-align: center;
+    color: grey;
+    padding-top: 10px;
+  }
+
+  .user-layout {
+    height: 100%;
+
+    &-container {
+      padding: 3rem 0;
+      width: 100%;
+
+      @media (min-height:600px) {
+        padding: 0;
+        position: relative;
+        top: 50%;
+        transform: translateY(-50%);
+        margin-top: -50px;
+      }
+    }
+
+    &-logo {
+      border-style: none;
+      margin: 0 auto 2rem;
+      display: block;
+
+      .mobile & {
+        max-width: 300px;
+        margin-bottom: 1rem;
+      }
+    }
+
+    &-footer {
+      display: flex;
+      flex-direction: column;
+      position: absolute;
+      bottom: 20px;
+      text-align: center;
+      width: 100%;
+
+      @media (max-height: 600px) {
+        position: relative;
+        margin-top: 50px;
+      }
+
+      label {
+        width: 368px;
+        font-weight: 500;
+        margin: 0 auto;
+      }
+    }
+  }
+</style>
diff --git a/ui/src/views/iam/RegisterTwoFactorAuth.vue b/ui/src/views/iam/RegisterTwoFactorAuth.vue
index c99bab05ff3..122c484eec7 100644
--- a/ui/src/views/iam/RegisterTwoFactorAuth.vue
+++ b/ui/src/views/iam/RegisterTwoFactorAuth.vue
@@ -20,7 +20,6 @@
     <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
@@ -42,7 +41,7 @@
           <a-button ref="submit" type="primary" @click="setup2FAProvider">{{ $t('label.setup') }}</a-button>
         </div>
       </div>
-      <div v-if="show2FAdetails">
+      <div v-if="twoFAenabled">
         <div v-if="selectedProvider !== 'staticpin'">
           <br />
           <p v-html="$t('message.two.fa.register.account')"></p>
@@ -89,6 +88,7 @@
 
 import { api } from '@/api'
 import VueQrious from 'vue-qrious'
+import eventBus from '@/config/eventBus'
 export default {
   name: 'RegisterTwoFactorAuth',
   props: {
@@ -107,8 +107,8 @@ export default {
       pin: '',
       code: '',
       showPin: false,
-      show2FAdetails: false,
       twoFAenabled: false,
+      twoFAverified: false,
       providers: [],
       selectedProvider: null
     }
@@ -116,6 +116,13 @@ export default {
   mounted () {
     this.list2FAProviders()
   },
+  created () {
+    eventBus.on('action-closing', (args) => {
+      if (args.action.api === 'setupUserTwoFactorAuthentication' && this.twoFAenabled && !this.twoFAverified) {
+        this.disable2FAProvider()
+      }
+    })
+  },
   methods: {
     onDataUrlChange (dataUrl) {
       this.dataUrl = dataUrl
@@ -136,8 +143,8 @@ export default {
           if (this.selectedProvider === 'staticpin') {
             this.showPin = true
           }
-          this.show2FAdetails = true
           this.twoFAenabled = true
+          this.twoFAverified = false
         }).catch(error => {
           this.$notification.error({
             message: this.$t('message.request.failed'),
@@ -149,8 +156,8 @@ export default {
     disable2FAProvider () {
       api('setupUserTwoFactorAuthentication', { enable: false }).then(response => {
         this.showPin = false
-        this.show2FAdetails = false
         this.twoFAenabled = false
+        this.twoFAverified = false
       }).catch(error => {
         this.$notification.error({
           message: this.$t('message.request.failed'),
@@ -169,6 +176,7 @@ export default {
           content: `${this.$t('label.action.enable.two.factor.authentication')}`,
           duration: 2
         })
+        this.twoFAverified = true
         this.$emit('refresh-data')
       }).catch(error => {
         this.$notification.error({
@@ -186,9 +194,6 @@ export default {
     },
     onCloseModal () {
       this.showPin = false
-    },
-    onCloseModalDisable2FA () {
-      this.disable2FAProvider()
     }
   }
 }