mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-08-14 07:48:37 +02:00
Enable the Vue 3 front-end
This commit is contained in:
@ -1,9 +1,70 @@
|
||||
<script setup>
|
||||
import Form from '@/components/formElements/Form'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useBusStore } from '@/stores/bus'
|
||||
import { useNotifyStore } from '@/stores/notify'
|
||||
import { UseColorMode } from '@vueuse/components'
|
||||
import { useTwofaccounts } from '@/stores/twofaccounts'
|
||||
|
||||
const router = useRouter()
|
||||
const user = useUserStore()
|
||||
const bus = useBusStore()
|
||||
const notify = useNotifyStore()
|
||||
const twofaccounts = useTwofaccounts()
|
||||
|
||||
const qrcodeInput = ref(null)
|
||||
const qrcodeInputLabel = ref(null)
|
||||
const form = reactive(new Form({
|
||||
qrcode: null,
|
||||
inputFormat: 'fileUpload',
|
||||
}))
|
||||
|
||||
|
||||
/**
|
||||
* Upload the submitted QR code file to the backend for decoding, then route the user
|
||||
* to the Create or Import form with decoded URI to prefill the form
|
||||
*/
|
||||
function submitQrCode() {
|
||||
form.clear()
|
||||
form.qrcode = qrcodeInput.value.files[0]
|
||||
|
||||
form.upload('/api/v1/qrcode/decode', { returnError: true }).then(response => {
|
||||
if (response.data.data.slice(0, 33).toLowerCase() === "otpauth-migration://offline?data=") {
|
||||
bus.migrationUri = response.data.data
|
||||
router.push({ name: 'importAccounts' })
|
||||
}
|
||||
else {
|
||||
bus.decodedUri = response.data.data
|
||||
router.push({ name: 'createAccount' })
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.response.status !== 422) {
|
||||
notify.alert({ text: error.response.data.message })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Push user to the dedicated capture view for live scan
|
||||
*/
|
||||
function capture() {
|
||||
router.push({ name: 'capture' });
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if( user.preferences.useDirectCapture && user.preferences.defaultCaptureMode === 'upload' ) {
|
||||
qrcodeInputLabel.value.click()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- static landing UI -->
|
||||
<div class="container has-text-centered">
|
||||
<div class="columns quick-uploader">
|
||||
<!-- trailer phrase that invite to add an account -->
|
||||
<div class="column is-full quick-uploader-header" :class="{ 'is-invisible' : accountCount !== 0 }">
|
||||
<div class="column is-full quick-uploader-header" :class="{ 'is-invisible' : twofaccounts.count !== 0 }">
|
||||
{{ $t('twofaccounts.no_account_here') }}<br>
|
||||
{{ $t('twofaccounts.add_first_account') }}
|
||||
</div>
|
||||
@ -11,7 +72,7 @@
|
||||
<div class="column is-full quick-uploader-button" >
|
||||
<div class="quick-uploader-centerer">
|
||||
<!-- upload a qr code (with basic file field and backend decoding) -->
|
||||
<label role="button" tabindex="0" v-if="$root.userPreferences.useBasicQrcodeReader" class="button is-link is-medium is-rounded is-main" ref="qrcodeInputLabel" @keyup.enter="$refs.qrcodeInputLabel.click()">
|
||||
<label role="button" tabindex="0" v-if="user.preferences.useBasicQrcodeReader" class="button is-link is-medium is-rounded is-main" ref="qrcodeInputLabel" @keyup.enter="qrcodeInputLabel.click()">
|
||||
<input aria-hidden="true" tabindex="-1" class="file-input" type="file" accept="image/*" v-on:change="submitQrCode" ref="qrcodeInput">
|
||||
{{ $t('twofaccounts.forms.upload_qrcode') }}
|
||||
</label>
|
||||
@ -20,132 +81,37 @@
|
||||
{{ $t('twofaccounts.forms.scan_qrcode') }}
|
||||
</button>
|
||||
</div>
|
||||
<FieldError v-if="form.errors.hasAny('qrcode')" :error="form.errors.get('qrcode')" :field="'qrcode'" />
|
||||
</div>
|
||||
<!-- alternative methods -->
|
||||
<div class="column is-full">
|
||||
<div class="block" :class="$root.showDarkMode ? 'has-text-light':'has-text-grey-dark'">{{ $t('twofaccounts.forms.alternative_methods') }}</div>
|
||||
<UseColorMode v-slot="{ mode }">
|
||||
<div class="block" :class="mode == 'dark' ? 'has-text-light':'has-text-grey-dark'">{{ $t('twofaccounts.forms.alternative_methods') }}</div>
|
||||
</UseColorMode>
|
||||
<!-- upload a qr code -->
|
||||
<div class="block has-text-link" v-if="!$root.userPreferences.useBasicQrcodeReader">
|
||||
<label role="button" tabindex="0" class="button is-link is-outlined is-rounded" ref="qrcodeInputLabel" @keyup.enter="$refs.qrcodeInputLabel.click()">
|
||||
<div class="block has-text-link" v-if="!user.preferences.useBasicQrcodeReader">
|
||||
<label role="button" tabindex="0" class="button is-link is-outlined is-rounded" ref="qrcodeInputLabel" @keyup.enter="qrcodeInputLabel.click()">
|
||||
<input aria-hidden="true" tabindex="-1" class="file-input" type="file" accept="image/*" v-on:change="submitQrCode" ref="qrcodeInput">
|
||||
{{ $t('twofaccounts.forms.upload_qrcode') }}
|
||||
</label>
|
||||
</div>
|
||||
<!-- link to advanced form -->
|
||||
<div v-if="showAdvancedFormButton" class="block has-text-link">
|
||||
<router-link class="button is-link is-outlined is-rounded" :to="{ name: 'createAccount' }" >
|
||||
<div class="block has-text-link">
|
||||
<RouterLink class="button is-link is-outlined is-rounded" :to="{ name: 'createAccount' }" >
|
||||
{{ $t('twofaccounts.forms.use_advanced_form') }}
|
||||
</router-link>
|
||||
</RouterLink>
|
||||
</div>
|
||||
<!-- link to import view -->
|
||||
<div v-if="showImportButton" class="block has-text-link">
|
||||
<router-link id="btnImport" class="button is-link is-outlined is-rounded" :to="{ name: 'importAccounts' }" >
|
||||
<div class="block has-text-link">
|
||||
<RouterLink id="btnImport" class="button is-link is-outlined is-rounded" :to="{ name: 'importAccounts' }" >
|
||||
{{ $t('twofaccounts.import.import') }}
|
||||
</router-link>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Footer -->
|
||||
<vue-footer :showButtons="true" >
|
||||
<!-- back button -->
|
||||
<p class="control" v-if="accountCount > 0">
|
||||
<router-link id="lnkBack" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" :to="{ name: returnToView }" >
|
||||
{{ $t('commons.back') }}
|
||||
</router-link>
|
||||
</p>
|
||||
</vue-footer>
|
||||
<VueFooter :showButtons="true" >
|
||||
<ButtonBackCloseCancel :returnTo="{ name: 'accounts' }" action="back" v-if="!twofaccounts.isEmpty" />
|
||||
</VueFooter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
/**
|
||||
* Start view
|
||||
*
|
||||
* route: '/start'
|
||||
*
|
||||
* Offer the user all available possibilities for capturing an account :
|
||||
* - By sending the user to the live scanner
|
||||
* - By decoding a QR code submitted with a form 'File' field
|
||||
* - By sending the user to the advanced form
|
||||
*
|
||||
*/
|
||||
|
||||
import Form from './../components/Form'
|
||||
|
||||
export default {
|
||||
name: 'Start',
|
||||
|
||||
data(){
|
||||
return {
|
||||
accountCount: null,
|
||||
form: new Form(),
|
||||
alternativeMethod: null,
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
showAdvancedFormButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showImportButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
returnToView: {
|
||||
type: String,
|
||||
default: 'accounts'
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
this.axios.get('api/v1/twofaccounts/count').then(response => {
|
||||
this.accountCount = response.data.count
|
||||
})
|
||||
},
|
||||
|
||||
created() {
|
||||
|
||||
this.$nextTick(() => {
|
||||
if( this.$root.userPreferences.useDirectCapture && this.$root.userPreferences.defaultCaptureMode === 'upload' ) {
|
||||
this.$refs.qrcodeInputLabel.click()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* Upload the submitted QR code file to the backend for decoding, then route the user
|
||||
* to the Create or Import form with decoded URI to prefill the form
|
||||
*/
|
||||
submitQrCode() {
|
||||
|
||||
let imgdata = new FormData();
|
||||
imgdata.append('qrcode', this.$refs.qrcodeInput.files[0]);
|
||||
imgdata.append('inputFormat', 'fileUpload');
|
||||
|
||||
this.form.upload('/api/v1/qrcode/decode', imgdata, {returnError: true}).then(response => {
|
||||
if( response.data.data.slice(0, 33).toLowerCase() === "otpauth-migration://offline?data=" ) {
|
||||
this.$router.push({ name: 'importAccounts', params: { migrationUri: response.data.data } });
|
||||
}
|
||||
else this.$router.push({ name: 'createAccount', params: { decodedUri: response.data.data } });
|
||||
})
|
||||
.catch(error => {
|
||||
this.$notify({type: 'is-danger', text: this.$t(error.response.data.message) })
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Push user to the dedicated capture view for live scan
|
||||
*/
|
||||
capture() {
|
||||
this.$router.push({ name: 'capture' });
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
Reference in New Issue
Block a user