浏览代码

Show actions instead of error when QR code is not a valid otp auth uri

Bubka 3 年之前
父节点
当前提交
3edacf0824

+ 13 - 0
resources/js/mixins.js

@@ -25,6 +25,19 @@ Vue.mixin({
                 this.$notify({ clean: true })
                 this.$notify({ clean: true })
                 this.$router.push({ name: 'accounts' })
                 this.$router.push({ name: 'accounts' })
             }
             }
+        },
+
+        isUrl: function (url) {
+            var strRegex = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/
+            var re = new RegExp(strRegex)
+
+            return re.test(url)
+        },
+
+        openInBrowser(uri) {
+            const a = document.createElement('a')
+            a.setAttribute('href', uri)
+            a.dispatchEvent(new MouseEvent("click", {'view': window, 'bubbles': true, 'cancelable': true}))
         }
         }
     }
     }
 
 

+ 53 - 6
resources/js/views/twofaccounts/Create.vue

@@ -131,6 +131,26 @@
                 </otp-displayer>
                 </otp-displayer>
             </modal>
             </modal>
         </form-wrapper>
         </form-wrapper>
+        <!-- alternatives -->
+        <modal v-model="showAlternatives">
+            <div class="too-bad"></div>
+            <div class="block">
+                {{ $t('errors.data_of_qrcode_is_not_valid_URI') }}
+            </div>
+            <div class="block has-text-light mb-6" v-html="uri"></div>
+            <!-- Copy to clipboard -->
+            <div class="block has-text-link">
+                <label class="button is-link is-outlined is-rounded" v-clipboard="() => uri" v-clipboard:success="clipboardSuccessHandler">
+                    {{ $t('commons.copy_to_clipboard') }}
+                </label>
+            </div>
+            <!-- Open in browser -->
+            <div class="block has-text-link" v-if="isUrl(uri)" @click="openInBrowser(uri)">
+                <label class="button is-link is-outlined is-rounded">
+                    {{ $t('commons.open_in_browser') }}
+                </label>
+            </div>
+        </modal>
     </div>
     </div>
 </template>
 </template>
 
 
@@ -163,7 +183,9 @@
                 showQuickForm: false,
                 showQuickForm: false,
                 showAdvancedForm: false,
                 showAdvancedForm: false,
                 ShowTwofaccountInModal : false,
                 ShowTwofaccountInModal : false,
+                showAlternatives : false,
                 tempIcon: '',
                 tempIcon: '',
+                uri: '',
                 form: new Form({
                 form: new Form({
                     service: '',
                     service: '',
                     account: '',
                     account: '',
@@ -212,9 +234,10 @@
 
 
         mounted: function () {
         mounted: function () {
             if( this.$route.params.decodedUri ) {
             if( this.$route.params.decodedUri ) {
+                this.uri = this.$route.params.decodedUri
 
 
                 // the Start view provided an uri so we parse it and prefill the quick form
                 // the Start view provided an uri so we parse it and prefill the quick form
-                this.axios.post('/api/v1/twofaccounts/preview', { uri: this.$route.params.decodedUri }).then(response => {
+                this.axios.post('/api/v1/twofaccounts/preview', { uri: this.uri }).then(response => {
 
 
                     this.form.fill(response.data)
                     this.form.fill(response.data)
                     this.tempIcon = response.data.icon ? response.data.icon : null
                     this.tempIcon = response.data.icon ? response.data.icon : null
@@ -222,19 +245,22 @@
                 })
                 })
                 .catch(error => {
                 .catch(error => {
                     if( error.response.status === 422 ) {
                     if( error.response.status === 422 ) {
-
-                        this.$router.push({ name: 'genericError', params: { err: this.$t('errors.cannot_create_otp_with_those_parameters') } });
+                        if( error.response.data.errors.uri ) {
+                            this.showAlternatives = true
+                            this.showAdvancedForm = true
+                        }
                     }
                     }
                 });
                 });
-
             } else {
             } else {
                 this.showAdvancedForm = true
                 this.showAdvancedForm = true
             }
             }
 
 
-            // stop TOTP generation on modal close
             this.$on('modalClose', function() {
             this.$on('modalClose', function() {
+                this.showAlternatives = false;
 
 
-                this.$refs.AdvancedFormOtpDisplayer.stopLoop()
+                if( this.showAdvancedForm ) {
+                    this.$refs.AdvancedFormOtpDisplayer.stopLoop()
+                }
             });
             });
         },
         },
 
 
@@ -283,6 +309,7 @@
 
 
                 // First we get the uri encoded in the qrcode
                 // First we get the uri encoded in the qrcode
                 const { data } = await this.form.upload('/api/v1/qrcode/decode', imgdata)
                 const { data } = await this.form.upload('/api/v1/qrcode/decode', imgdata)
+                this.uri = data.data
 
 
                 // Then the otp described by the uri
                 // Then the otp described by the uri
                 this.axios.post('/api/v1/twofaccounts/preview', { uri: data.data }).then(response => {
                 this.axios.post('/api/v1/twofaccounts/preview', { uri: data.data }).then(response => {
@@ -290,6 +317,13 @@
                     this.form.secretIsBase32Encoded = 1
                     this.form.secretIsBase32Encoded = 1
                     this.tempIcon = response.data.icon ? response.data.icon : null
                     this.tempIcon = response.data.icon ? response.data.icon : null
                 })
                 })
+                .catch(error => {
+                    if( error.response.status === 422 ) {
+                        if( error.response.data.errors.uri ) {
+                            this.showAlternatives = true
+                        }
+                    }
+                });
             },
             },
 
 
             async uploadIcon(event) {
             async uploadIcon(event) {
@@ -320,6 +354,19 @@
                 // is acceptable (and HOTP counter can be edited by the way)
                 // is acceptable (and HOTP counter can be edited by the way)
                 this.form.counter = payload.nextHotpCounter
                 this.form.counter = payload.nextHotpCounter
             },
             },
+
+            clipboardSuccessHandler ({ value, event }) {
+
+                if(this.$root.appSettings.kickUserAfter == -1) {
+                    this.appLogout()
+                }
+
+                this.$notify({ type: 'is-success', text: this.$t('commons.copied_to_clipboard') })
+            },
+
+            clipboardErrorHandler ({ value, event }) {
+                console.log('error', value)
+            }
             
             
         },
         },
 
 

+ 1 - 0
resources/lang/en/commons.php

@@ -38,4 +38,5 @@ return [
     'reload' => 'Reload',
     'reload' => 'Reload',
     'some_data_have_changed' => 'Some data have changed. You should',
     'some_data_have_changed' => 'Some data have changed. You should',
     'generate' => 'Generate',
     'generate' => 'Generate',
+    'open_in_browser' => 'Open in browser',
 ];
 ];

+ 1 - 1
resources/lang/en/errors.php

@@ -22,7 +22,7 @@ return [
     'Unable_to_decrypt_uri' => 'Unable to decrypt uri',
     'Unable_to_decrypt_uri' => 'Unable to decrypt uri',
     'not_a_supported_otp_type' => 'This OTP format is not currently supported',
     'not_a_supported_otp_type' => 'This OTP format is not currently supported',
     'cannot_create_otp_without_secret' => 'Cannot create an OTP without a secret',
     'cannot_create_otp_without_secret' => 'Cannot create an OTP without a secret',
-    'cannot_create_otp_with_those_parameters' => 'Cannot create an OTP with those parameters',
+    'data_of_qrcode_is_not_valid_URI' => 'The data of this QR code is not a valid OTP Auth URI:',
     'wrong_current_password' => 'Wrong current password, nothing has changed',
     'wrong_current_password' => 'Wrong current password, nothing has changed',
     'error_during_encryption' => 'Encryption failed, your database remains unprotected.',
     'error_during_encryption' => 'Encryption failed, your database remains unprotected.',
     'error_during_decryption' => 'Decryption failed, your database is still protected. This is mainly caused by an integrity issue of encrypted data for one or more accounts.',
     'error_during_decryption' => 'Decryption failed, your database is still protected. This is mainly caused by an integrity issue of encrypted data for one or more accounts.',

文件差异内容过多而无法显示
+ 0 - 0
resources/sass/app.scss


部分文件因为文件数量过多而无法显示