diff options
Diffstat (limited to 'src/components/user_settings/mfa.js')
| -rw-r--r-- | src/components/user_settings/mfa.js | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/components/user_settings/mfa.js b/src/components/user_settings/mfa.js new file mode 100644 index 00000000..2acee862 --- /dev/null +++ b/src/components/user_settings/mfa.js @@ -0,0 +1,152 @@ +import RecoveryCodes from './mfa_backup_codes.vue' +import TOTP from './mfa_totp.vue' +import Confirm from './confirm.vue' +import VueQrcode from '@chenfengyuan/vue-qrcode' +import { mapState } from 'vuex' + +const Mfa = { + data: () => ({ + settings: { // current settings of MFA + enabled: false, + totp: false + }, + setupState: { // setup mfa + state: '', // state of setup. '' -> 'getBackupCodes' -> 'setupOTP' -> 'complete' + setupOTPState: '' // state of setup otp. '' -> 'prepare' -> 'confirm' -> 'complete' + }, + backupCodes: { + getNewCodes: false, + inProgress: false, // progress of fetch codes + codes: [] + }, + otpSettings: { // pre-setup setting of OTP. secret key, qrcode url. + provisioning_uri: '', + key: '' + }, + currentPassword: null, + otpConfirmToken: null, + error: null, + readyInit: false + }), + components: { + 'recovery-codes': RecoveryCodes, + 'totp-item': TOTP, + 'qrcode': VueQrcode, + 'confirm': Confirm + }, + computed: { + canSetupOTP () { + return ( + (this.setupInProgress && this.backupCodesPrepared) || + this.settings.enabled + ) && !this.settings.totp && !this.setupOTPInProgress + }, + setupInProgress () { + return this.setupState.state !== '' && this.setupState.state !== 'complete' + }, + setupOTPInProgress () { + return this.setupState.state === 'setupOTP' && !this.completedOTP + }, + prepareOTP () { + return this.setupState.setupOTPState === 'prepare' + }, + confirmOTP () { + return this.setupState.setupOTPState === 'confirm' + }, + completedOTP () { + return this.setupState.setupOTPState === 'completed' + }, + backupCodesPrepared () { + return !this.backupCodes.inProgress && this.backupCodes.codes.length > 0 + }, + confirmNewBackupCodes () { + return this.backupCodes.getNewCodes + }, + ...mapState({ + backendInteractor: (state) => state.api.backendInteractor + }) + }, + + methods: { + activateOTP () { + if (!this.settings.enabled) { + this.setupState.state = 'getBackupcodes' + this.fetchBackupCodes() + } + }, + fetchBackupCodes () { + this.backupCodes.inProgress = true + this.backupCodes.codes = [] + + return this.backendInteractor.generateMfaBackupCodes() + .then((res) => { + this.backupCodes.codes = res.codes + this.backupCodes.inProgress = false + }) + }, + getBackupCodes () { // get a new backup codes + this.backupCodes.getNewCodes = true + }, + confirmBackupCodes () { // confirm getting new backup codes + this.fetchBackupCodes().then((res) => { + this.backupCodes.getNewCodes = false + }) + }, + cancelBackupCodes () { // cancel confirm form of new backup codes + this.backupCodes.getNewCodes = false + }, + + // Setup OTP + setupOTP () { // prepare setup OTP + this.setupState.state = 'setupOTP' + this.setupState.setupOTPState = 'prepare' + this.backendInteractor.mfaSetupOTP() + .then((res) => { + this.otpSettings = res + this.setupState.setupOTPState = 'confirm' + }) + }, + doConfirmOTP () { // handler confirm enable OTP + this.error = null + this.backendInteractor.mfaConfirmOTP({ + token: this.otpConfirmToken, + password: this.currentPassword + }) + .then((res) => { + if (res.error) { + this.error = res.error + return + } + this.completeSetup() + }) + }, + + completeSetup () { + this.setupState.setupOTPState = 'complete' + this.setupState.state = 'complete' + this.currentPassword = null + this.error = null + this.fetchSettings() + }, + cancelSetup () { // cancel setup + this.setupState.setupOTPState = '' + this.setupState.state = '' + this.currentPassword = null + this.error = null + }, + // end Setup OTP + + // fetch settings from server + async fetchSettings () { + let result = await this.backendInteractor.fetchSettingsMFA() + this.settings = result.settings + return result + } + }, + mounted () { + this.fetchSettings().then(() => { + this.readyInit = true + }) + } +} +export default Mfa |
