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