confirm token in 2fa challenge

This commit is contained in:
Čarodej
2022-04-05 09:52:49 +02:00
parent 9f783fcd95
commit 10d8b592ea
13 changed files with 127 additions and 66 deletions

View File

@@ -68,7 +68,7 @@ export default {
data() {
return {
isLoading: false,
password: '',
password: undefined,
args: undefined,
}
},

View File

@@ -1,6 +1,6 @@
<template>
<PopupWrapper name="two-factor-qr-setup">
<PopupHeader :title="$t('confirm_your_password')" icon="edit" />
<PopupHeader :title="$t('set_up_2fa_app')" icon="edit" />
<PopupContent>
<div v-if="qrCode" class="flex justify-center">
@@ -10,27 +10,42 @@
<InfoBox style="margin-bottom: 0">
<p v-html="$t('popup_2fa.help')"></p>
</InfoBox>
<ValidationObserver @submit.prevent="confirm2FaSetup" ref="codeForm" v-slot="{ invalid }" tag="form" class="mt-5">
<ValidationProvider tag="div" mode="passive" name="Code" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('confirm')" :error="errors[0]" :is-last="true">
<input
v-model="code"
:class="{ '!border-rose-600': errors[0] }"
type="text"
ref="input"
class="focus-border-theme input-dark"
:placeholder="$t('paste_code_from_2fa_app')"
/>
</AppInputText>
</ValidationProvider>
</ValidationObserver>
</PopupContent>
<PopupActions>
<ButtonBase class="w-full" @click.native="closeQrCodePopup" :button-style="closeQrButtonStyle">
{{ closeQrButtonText }}
<ButtonBase @click.native="confirm2FaSetup" class="w-full" button-style="theme" :loading="isLoading">
{{ $t('confirm_your_code') }}
</ButtonBase>
</PopupActions>
</PopupWrapper>
</template>
<script>
import AppInputText from '../Admin/AppInputText'
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
import { required } from 'vee-validate/dist/rules'
import ButtonBase from '../FilesView/ButtonBase'
import AppInputText from '../Admin/AppInputText'
import PopupWrapper from './Popup/PopupWrapper'
import PopupActions from './Popup/PopupActions'
import PopupContent from './Popup/PopupContent'
import PopupHeader from './Popup/PopupHeader'
import ButtonBase from '../FilesView/ButtonBase'
import InfoBox from './Forms/InfoBox'
import { required } from 'vee-validate/dist/rules'
import { mapGetters } from 'vuex'
import { events } from '../../bus'
import axios from 'axios'
@@ -48,31 +63,49 @@ export default {
required,
InfoBox,
},
computed: {
...mapGetters(['user']),
closeQrButtonText() {
return this.isConfirmedClose ? this.$t('popup_2fa.disappear_qr') : this.$t('awesome_iam_done')
},
closeQrButtonStyle() {
return this.isConfirmedClose ? 'danger' : 'theme'
},
},
data() {
return {
qrCode: undefined,
isLoading: false,
qrCode: '',
isConfirmedClose: false,
code: undefined
}
},
methods: {
async confirm2FaSetup() {
// Validate fields
const isValid = await this.$refs.codeForm.validate()
if (!isValid) return
this.isLoading = true
axios
.post('/user/confirmed-two-factor-authentication', {code: this.code})
.then(() => {
this.$store.commit('CHANGE_TWO_FACTOR_AUTHENTICATION_STATE', true)
this.$closePopup()
events.$emit('toaster', {
type: 'success',
message: this.$t('popup_2fa.toaster_enabled'),
})
})
.catch((error) => {
if (error.response.status === 422) {
this.$refs.codeForm.setErrors({
'Code': error.response.data.errors['code'][0],
})
}
})
.finally(() => this.isLoading = false)
},
enable() {
axios
.post('/user/two-factor-authentication')
.then(() => {
this.$store.commit('CHANGE_TWO_FACTOR_AUTHENTICATION_STATE', true)
this.getQrCode()
})
.then(() => {
this.getQrCode()
})
.catch(() => {
this.$isSomethingWrong()
})
@@ -87,28 +120,12 @@ export default {
this.$isSomethingWrong()
})
},
closeQrCodePopup() {
if (!this.isConfirmedClose) {
this.isConfirmedClose = true
} else {
events.$emit('toaster', {
type: 'success',
message: this.$t('popup_2fa.toaster_enabled'),
})
this.qrCode = undefined
this.isConfirmedClose = false
this.$closePopup()
}
},
},
created() {
// Show popup
events.$on('popup:open', (args) => {
if (args.name !== 'two-factor-qr-setup') return
this.enable()
this.enable()
})
},
}

View File

@@ -135,7 +135,7 @@ const actions = {
const mutations = {
CHANGE_TWO_FACTOR_AUTHENTICATION_STATE(state, condition) {
state.user.data.attributes.two_factor_authentication = condition
state.user.data.attributes.two_factor_confirmed_at = condition
},
RETRIEVE_USER(state, user) {
state.user = user

View File

@@ -8,18 +8,18 @@
<AppInputSwitch
:title="$t('popup_2fa.switch_title')"
:description="$t('popup_2fa.switch_info')"
:is-last="!user.data.attributes.two_factor_authentication"
:is-last="!user.data.attributes.two_factor_confirmed_at"
>
<SwitchInput
@click.native="toggle2Fa"
:is-disabled="true"
v-model="user.data.attributes.two_factor_authentication"
v-model="user.data.attributes.two_factor_confirmed_at"
class="switch"
:state="user.data.attributes.two_factor_authentication"
:state="user.data.attributes.two_factor_confirmed_at"
/>
</AppInputSwitch>
<AppInputButton
v-if="user && user.data.attributes.two_factor_authentication"
v-if="user && user.data.attributes.two_factor_confirmed_at"
:title="$t('show_recovery_codes')"
:description="$t('popup_2fa.codes_info')"
:is-last="true"
@@ -184,7 +184,7 @@ export default {
},
methods: {
toggle2Fa() {
this.user.data.attributes.two_factor_authentication ? this.disable2faPopup() : this.enable2faPopup()
this.user.data.attributes.two_factor_confirmed_at ? this.disable2faPopup() : this.enable2faPopup()
},
async resetPassword() {
// Validate fields