This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Zaimki/components/MfaValidation.vue

107 lines
3.6 KiB
Vue

<template>
<section>
<Alert type="danger" :message="error"/>
<div class="card shadow">
<div class="card-body">
<p class="h4">
<Icon v="mobile"/>
<T>user.mfa.header</T>
</p>
<form @submit.prevent="validate" :disabled="saving">
<div class="input-group mb-3">
<input v-if="!recovery" type="text" class="form-control text-center" v-model="code"
placeholder="000000" autofocus required minlength="0" maxlength="6"
inputmode="numeric" pattern="[0-9]{6}" autocomplete="one-time-code"
/>
<input v-else type="text" class="form-control text-center" v-model="recoveryCode"
:placeholder="$t('user.mfa.recovery.header')" autofocus required minlength="0" maxlength="24"
autocomplete="one-time-code"
/>
<button class="btn btn-primary">
<Icon v="key"/>
<T>user.code.action</T>
</button>
</div>
</form>
</div>
<div class="card-footer small d-flex justify-content-around">
<a href="#" @click.prevent="recoverySwitch">
<Icon v="ambulance"/>
<T>user.mfa.recovery.enter</T>
</a>
<a href="#" @click.prevent="cancel">
<Icon v="sign-out"/>
<T>user.mfa.cancel</T>
</a>
</div>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
data() {
return {
code: '',
recoveryCode: '',
recovery: false,
saving: false,
error: '',
}
},
mounted() {
this.focus();
},
methods: {
async validate() {
if (this.saving) {
return;
}
this.error = '';
this.saving = true;
try {
const res = await this.$axios.$post(`/mfa/validate`, {
code: this.recovery ? this.recoveryCode : this.code,
recovery: this.recovery,
}, {
headers: {
authorization: 'Bearer ' + this.preToken,
},
});
if (res.error) {
this.error = res.error;
return;
}
this.$store.commit('setToken', res.token);
} finally {
this.saving = false;
this.code = '';
this.recoveryCode = '';
this.recovery = false;
this.focus();
}
},
cancel() {
this.$store.commit('cancelMfa');
},
recoverySwitch() {
this.recovery = !this.recovery;
this.code = '';
this.recoveryCode = '';
this.focus();
},
focus() {
this.$nextTick(() => this.$el.querySelector('input').focus());
}
},
computed: {
...mapState([
'preToken',
]),
},
};
</script>