import { qrCode, recoveryCodes, secretKey } from '@/routes/two-factor'; import { computed, ref } from 'vue'; const fetchJson = async (url: string): Promise => { const response = await fetch(url, { headers: { Accept: 'application/json' }, }); if (!response.ok) { throw new Error(`Failed to fetch: ${response.status}`); } return response.json(); }; const errors = ref([]); const manualSetupKey = ref(null); const qrCodeSvg = ref(null); const recoveryCodesList = ref([]); const hasSetupData = computed( () => qrCodeSvg.value !== null && manualSetupKey.value !== null, ); export const useTwoFactorAuth = () => { const fetchQrCode = async (): Promise => { try { const { svg } = await fetchJson<{ svg: string; url: string }>( qrCode.url(), ); qrCodeSvg.value = svg; } catch { errors.value.push('Failed to fetch QR code'); qrCodeSvg.value = null; } }; const fetchSetupKey = async (): Promise => { try { const { secretKey: key } = await fetchJson<{ secretKey: string }>( secretKey.url(), ); manualSetupKey.value = key; } catch { errors.value.push('Failed to fetch a setup key'); manualSetupKey.value = null; } }; const clearSetupData = (): void => { manualSetupKey.value = null; qrCodeSvg.value = null; clearErrors(); }; const clearErrors = (): void => { errors.value = []; }; const clearTwoFactorAuthData = (): void => { clearSetupData(); clearErrors(); recoveryCodesList.value = []; }; const fetchRecoveryCodes = async (): Promise => { try { clearErrors(); recoveryCodesList.value = await fetchJson( recoveryCodes.url(), ); } catch { errors.value.push('Failed to fetch recovery codes'); recoveryCodesList.value = []; } }; const fetchSetupData = async (): Promise => { try { clearErrors(); await Promise.all([fetchQrCode(), fetchSetupKey()]); } catch { qrCodeSvg.value = null; manualSetupKey.value = null; } }; return { qrCodeSvg, manualSetupKey, recoveryCodesList, errors, hasSetupData, clearSetupData, clearErrors, clearTwoFactorAuthData, fetchQrCode, fetchSetupKey, fetchSetupData, fetchRecoveryCodes, }; };