import { CheckCircle, Security, Smartphone } from '@mui/icons-material'
import {
Alert,
Box,
Button,
Card,
CircularProgress,
Divider,
Input,
Modal,
ModalClose,
ModalDialog,
Stack,
Typography,
} from '@mui/joy'
import QRCode from 'qrcode'
import { useEffect, useState } from 'react'
import {
ConfirmMFA,
DisableMFA,
GetMFAStatus,
RegenerateBackupCodes,
SetupMFA,
} from '../../utils/Fetcher'
const MFASettings = () => {
const [mfaEnabled, setMfaEnabled] = useState(false)
const [loading, setLoading] = useState(true)
const [setupModalOpen, setSetupModalOpen] = useState(false)
const [disableModalOpen, setDisableModalOpen] = useState(false)
const [backupCodesModalOpen, setBackupCodesModalOpen] = useState(false)
const [setupData, setSetupData] = useState(null)
const [qrCodeDataUrl, setQrCodeDataUrl] = useState('')
const [verificationCode, setVerificationCode] = useState('')
const [disableCode, setDisableCode] = useState('')
const [backupCodes, setBackupCodes] = useState([])
const [setupStep, setSetupStep] = useState(1) // 1: QR Code, 2: Verification, 3: Backup Codes
const [error, setError] = useState('')
const [success, setSuccess] = useState('')
useEffect(() => {
fetchMFAStatus()
}, [])
const fetchMFAStatus = async () => {
try {
setLoading(true)
const response = await GetMFAStatus()
if (response.ok) {
const data = await response.json()
setMfaEnabled(data.mfaEnabled)
}
} catch (error) {
console.error('Error fetching MFA status:', error)
} finally {
setLoading(false)
}
}
const generateQRCode = async url => {
try {
const qrCodeDataUrl = await QRCode.toDataURL(url, {
width: 200,
margin: 2,
})
setQrCodeDataUrl(qrCodeDataUrl)
} catch (error) {
console.error('Error generating QR code:', error)
setError('Failed to generate QR code')
}
}
const handleSetupMFA = async () => {
try {
setError('')
const response = await SetupMFA()
console.log('MFA Setup Response Status:', response.status)
console.log('MFA Setup Response:', response)
if (response.ok) {
const data = await response.json()
console.log('MFA Setup Data:', data)
// Check for either qrCode (base64 image) or qrCodeUrl (TOTP URL)
if (!data.qrCodeUrl || !data.backupCodes || !data.secret) {
console.error('Missing required MFA data:', {
hasQrCode: !!data.qrCode,
hasQrCodeUrl: !!data.qrCodeUrl,
hasSecret: !!data.secret,
})
setError('Invalid response from server. Missing QR code or secret.')
return
}
if (data.backupCodes) {
console.log('Backup Codes:', data.backupCodes)
setBackupCodes(data.backupCodes)
}
// If we have a qrCodeUrl, generate the QR code image
if (data.qrCodeUrl) {
await generateQRCode(data.qrCodeUrl)
}
setSetupData(data)
setSetupModalOpen(true)
setSetupStep(1)
} else {
// Handle different error status codes
if (response.status === 404) {
setError(
'MFA setup endpoint not found. This feature may not be available yet.',
)
} else if (response.status === 401) {
setError('Unauthorized. Please login again.')
} else if (response.status === 500) {
setError('Server error. Please try again later.')
} else {
const errorData = await response.json().catch(() => ({}))
setError(
errorData.message ||
`Failed to setup MFA (${response.status}). Please try again.`,
)
}
}
} catch (error) {
console.error('Error setting up MFA:', error)
setError('Network error. Please check your connection and try again.')
}
}
const handleConfirmMFA = async () => {
try {
setError('')
const response = await ConfirmMFA(
setupData.secret,
verificationCode,
setupData.backupCodes,
)
if (response.ok) {
setSetupStep(3)
setMfaEnabled(true)
setSuccess('MFA has been successfully enabled!')
} else {
setError('Invalid verification code. Please try again.')
}
} catch (error) {
setError('Failed to confirm MFA. Please try again.')
console.error('Error confirming MFA:', error)
}
}
const handleDisableMFA = async () => {
try {
setError('')
const response = await DisableMFA(disableCode)
if (response.ok) {
setMfaEnabled(false)
setDisableModalOpen(false)
setDisableCode('')
setSuccess('MFA has been disabled successfully!')
} else {
setError('Invalid verification code. Please try again.')
}
} catch (error) {
setError('Failed to disable MFA. Please try again.')
console.error('Error disabling MFA:', error)
}
}
const handleRegenerateBackupCodes = async () => {
try {
setError('')
const response = await RegenerateBackupCodes()
if (response.ok) {
const data = await response.json()
setBackupCodes(data.backupCodes)
setBackupCodesModalOpen(true)
setSuccess('New backup codes have been generated!')
} else {
setError('Failed to regenerate backup codes. Please try again.')
}
} catch (error) {
setError('Failed to regenerate backup codes. Please try again.')
console.error('Error regenerating backup codes:', error)
}
}
const closeSetupModal = () => {
setSetupModalOpen(false)
setSetupStep(1)
setVerificationCode('')
setSetupData(null)
setQrCodeDataUrl('')
setError('')
}
const closeDisableModal = () => {
setDisableModalOpen(false)
setDisableCode('')
setError('')
}
if (loading) {
return (