aboutsummaryrefslogtreecommitdiff
path: root/src/components/user_settings/mfa.js
blob: 2acee86295cb2e7249cd0fd8f743d140a82d0b18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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