mfa.js (4331B)
1 import RecoveryCodes from './mfa_backup_codes.vue' 2 import TOTP from './mfa_totp.vue' 3 import Confirm from './confirm.vue' 4 import VueQrcode from '@chenfengyuan/vue-qrcode' 5 import { mapState } from 'vuex' 6 7 const Mfa = { 8 data: () => ({ 9 settings: { // current settings of MFA 10 available: false, 11 enabled: false, 12 totp: false 13 }, 14 setupState: { // setup mfa 15 state: '', // state of setup. '' -> 'getBackupCodes' -> 'setupOTP' -> 'complete' 16 setupOTPState: '' // state of setup otp. '' -> 'prepare' -> 'confirm' -> 'complete' 17 }, 18 backupCodes: { 19 getNewCodes: false, 20 inProgress: false, // progress of fetch codes 21 codes: [] 22 }, 23 otpSettings: { // pre-setup setting of OTP. secret key, qrcode url. 24 provisioning_uri: '', 25 key: '' 26 }, 27 currentPassword: null, 28 otpConfirmToken: null, 29 error: null, 30 readyInit: false 31 }), 32 components: { 33 'recovery-codes': RecoveryCodes, 34 'totp-item': TOTP, 35 'qrcode': VueQrcode, 36 'confirm': Confirm 37 }, 38 computed: { 39 canSetupOTP () { 40 return ( 41 (this.setupInProgress && this.backupCodesPrepared) || 42 this.settings.enabled 43 ) && !this.settings.totp && !this.setupOTPInProgress 44 }, 45 setupInProgress () { 46 return this.setupState.state !== '' && this.setupState.state !== 'complete' 47 }, 48 setupOTPInProgress () { 49 return this.setupState.state === 'setupOTP' && !this.completedOTP 50 }, 51 prepareOTP () { 52 return this.setupState.setupOTPState === 'prepare' 53 }, 54 confirmOTP () { 55 return this.setupState.setupOTPState === 'confirm' 56 }, 57 completedOTP () { 58 return this.setupState.setupOTPState === 'completed' 59 }, 60 backupCodesPrepared () { 61 return !this.backupCodes.inProgress && this.backupCodes.codes.length > 0 62 }, 63 confirmNewBackupCodes () { 64 return this.backupCodes.getNewCodes 65 }, 66 ...mapState({ 67 backendInteractor: (state) => state.api.backendInteractor 68 }) 69 }, 70 71 methods: { 72 activateOTP () { 73 if (!this.settings.enabled) { 74 this.setupState.state = 'getBackupcodes' 75 this.fetchBackupCodes() 76 } 77 }, 78 fetchBackupCodes () { 79 this.backupCodes.inProgress = true 80 this.backupCodes.codes = [] 81 82 return this.backendInteractor.generateMfaBackupCodes() 83 .then((res) => { 84 this.backupCodes.codes = res.codes 85 this.backupCodes.inProgress = false 86 }) 87 }, 88 getBackupCodes () { // get a new backup codes 89 this.backupCodes.getNewCodes = true 90 }, 91 confirmBackupCodes () { // confirm getting new backup codes 92 this.fetchBackupCodes().then((res) => { 93 this.backupCodes.getNewCodes = false 94 }) 95 }, 96 cancelBackupCodes () { // cancel confirm form of new backup codes 97 this.backupCodes.getNewCodes = false 98 }, 99 100 // Setup OTP 101 setupOTP () { // prepare setup OTP 102 this.setupState.state = 'setupOTP' 103 this.setupState.setupOTPState = 'prepare' 104 this.backendInteractor.mfaSetupOTP() 105 .then((res) => { 106 this.otpSettings = res 107 this.setupState.setupOTPState = 'confirm' 108 }) 109 }, 110 doConfirmOTP () { // handler confirm enable OTP 111 this.error = null 112 this.backendInteractor.mfaConfirmOTP({ 113 token: this.otpConfirmToken, 114 password: this.currentPassword 115 }) 116 .then((res) => { 117 if (res.error) { 118 this.error = res.error 119 return 120 } 121 this.completeSetup() 122 }) 123 }, 124 125 completeSetup () { 126 this.setupState.setupOTPState = 'complete' 127 this.setupState.state = 'complete' 128 this.currentPassword = null 129 this.error = null 130 this.fetchSettings() 131 }, 132 cancelSetup () { // cancel setup 133 this.setupState.setupOTPState = '' 134 this.setupState.state = '' 135 this.currentPassword = null 136 this.error = null 137 }, 138 // end Setup OTP 139 140 // fetch settings from server 141 async fetchSettings () { 142 let result = await this.backendInteractor.settingsMFA() 143 if (result.error) return 144 this.settings = result.settings 145 this.settings.available = true 146 return result 147 } 148 }, 149 mounted () { 150 this.fetchSettings().then(() => { 151 this.readyInit = true 152 }) 153 } 154 } 155 export default Mfa