diff --git a/src/components/user_settings/mfa.js b/src/components/user_settings/mfa.js index 43c39921d4..4ba9a564c9 100644 --- a/src/components/user_settings/mfa.js +++ b/src/components/user_settings/mfa.js @@ -1,131 +1,134 @@ import RecoveryCodes from './mfa_backup_codes.vue' - +import TOTP from './mfa_totp.vue' const Mfa = { data () { return { - settings: {}, // current settings of MFA + 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: { + inProgress: false, // progress of fetch codes + codes: [] + }, currentPassword: null, otpConfirmToken: null, - backup_codes: [], otpSettings: {}, // pre-setup setting of OTP. secret key, qrcode url. - performSetup: null, // step of setup. null -> getBackupCodes -> readyBackupCodes - performSetupOTP: null, // steps of setup otp. null -> init -> confirm - disableMethod: null, // disable method MFA - performGenerateNewCodes: false, - disableError: null, - confirmOTPError: null, + error: null, readyInit: false } }, - components: {'recovery-codes': RecoveryCodes}, + components: {'recovery-codes': RecoveryCodes, 'totp-item': TOTP}, computed: { canEnable () { - return !this.settings.enabled && this.performSetup === null - }, - showBackupCodes () { - return this.waitBackupCodes || this.readyBackupCodes - }, - waitBackupCodes () { - return this.performSetup === 'getBackupCodes' - }, - readyBackupCodes () { - return this.performSetup === 'readyBackupCodes' + return !this.settings.enabled && !this.setupInProgress }, canSetupOTP () { return ( - this.readyBackupCodes || this.settings.enabled + (this.setupInProgress && this.backupCodesPrepared) || + this.settings.enabled ) && this.settings.totp === false }, waitPreSetupOTP () { return this.performSetupOTP === null || this.performSetupOTP === 'init' + }, + disableOTP () { + return this.disableMethod === 'otp' + }, + setupInProgress () { + return this.setupState.state !== '' && this.setupState.state !== 'complete' + }, + prepareOTP () { + return this.setupState.setupOTPState === 'prepare' + }, + confirmOTP () { + return this.setupState.setupOTPState === 'confirm' + }, + backupCodesPrepared () { + return this.backupCodes.inProgress === false && this.backupCodes.codes.length > 0 } }, + methods: { enableMFA () { - this.performSetup = 'getBackupCodes' - this.backupCodes().then((codes) => { - this.backup_codes = codes - this.performSetup = 'readyBackupCodes' + this.setupState.state = 'getBackupcodes' + this.$nextTick(() => { + this.startFetchBackupCodes() + this.$store.state.api.backendInteractor.generateMfaBackupCodes() + .then((res) => this.setBackupCodes(res.codes)) + .then((res) => { this.setupState.state = 'setupOTP' }) }) }, // gets New Backup codes - getBackupCodes () { - this.performGenerateNewCodes = true - this.backupCodes().then((codes) => { - this.backup_codes = codes - this.performGenerateNewCodes = false + getNewBackupCodes () { + this.$nextTick(() => { + this.startFetchBackupCodes() + this.$store.state.api.backendInteractor.generateMfaBackupCodes().then( + (res) => this.setBackupCodes(res.codes) + ) }) }, - - backupCodes () { - return new Promise((resolve, reject) => { - this.$store.state.api.backendInteractor.generateMfaBackupCodes({}) - .then((res) => { resolve(res.codes) }) - }) + startFetchBackupCodes () { + this.backupCodes.inProgress = true + this.backupCodes.codes = [] + }, + setBackupCodes (codes) { + this.backupCodes.codes = codes + this.backupCodes.inProgress = false }, // Setup OTP - setupOTP () { - this.performSetupOTP = 'init' + setupOTP () { // prepare setup OTP + this.setupState.setupOTPState = 'prepare' this.$store.state.api.backendInteractor.mfaSetupOTP({}) .then((res) => { this.otpSettings = res - this.performSetupOTP = 'confirm' + this.setupState.setupOTPState = 'confirm' }) }, - confirmOTP () { - this.confirmOTPError = null + doConfirmOTP () { // handler confirm enable OTP + this.error = null this.$store.state.api.backendInteractor.mfaConfirmOTP({ token: this.otpConfirmToken, password: this.currentPassword }) .then((res) => { if (res.error) { - this.confirmOTPError = res.error + this.error = res.error return } - this.performSetup = null - this.currentPassword = null - this.fetchSettings(true) + this.completeSetup() }) }, + + completeSetup () { + this.setupState.setupOTPState = 'complete' + this.setupState.state = 'complete' + this.currentPassword = null + this.fetchSettings() + }, + // end Setup OTP - // disable OTP - handleDisableOTP () { - this.disableError = null - this.$store.state.api.backendInteractor.mfaDisableOTP({ - password: this.currentPassword - }) - .then((res) => { - if (res.error) { - this.disableError = res.error - return - } - this.disableMethod = null - this.currentPassword = null - this.fetchSettings(true) - }) - }, - // end disable OTP - // fetch settings from server - fetchSettings (force) { - if (force || this.settings.enabled === undefined) { - this.$store.state.api.backendInteractor.fetchSettingsMFA({}) - .then((res) => { - this.settings = res.settings - if (!this.readyInit) { - this.readyInit = true - } - }) - } + fetchSettings () { + this.$store.state.api.backendInteractor.fetchSettingsMFA() + .then((res) => { + this.settings = res.settings + if (!this.readyInit) { + this.readyInit = true + } + }) } // end fetch settings }, mounted () { - this.fetchSettings(true) + this.fetchSettings() } } export default Mfa diff --git a/src/components/user_settings/mfa.vue b/src/components/user_settings/mfa.vue index 3dd275c1c4..f86d3d868e 100644 --- a/src/components/user_settings/mfa.vue +++ b/src/components/user_settings/mfa.vue @@ -8,21 +8,19 @@ -
{{$t('settings.mfa.recovery_codes_warning')}}
-{{$t('settings.mfa.recovery_codes_warning')}}
+