import React, { useState } from "react"; import { Icon } from "@iconify/react"; import { userApi } from "../../api/userApi"; import { useNotification } from "../../hooks/useNotification"; import { Modal } from "../common/Modal"; interface TwoFactorSetupProps { twoFactorEnabled: boolean; onStatusChange: () => void; } export const TwoFactorSetup: React.FC = ({ twoFactorEnabled, onStatusChange, }) => { const { showNotification } = useNotification(); const [isLoading, setIsLoading] = useState(false); const [setupData, setSetupData] = useState<{ secret: string; qrCode: string; } | null>(null); const [verificationCode, setVerificationCode] = useState(""); const [backupCodes, setBackupCodes] = useState(null); const [showDisableModal, setShowDisableModal] = useState(false); const [disablePassword, setDisablePassword] = useState(""); const [isDisabling, setIsDisabling] = useState(false); const [showBackupCodesModal, setShowBackupCodesModal] = useState(false); const [isGeneratingBackupCodes, setIsGeneratingBackupCodes] = useState(false); const handleSetup = async () => { setIsLoading(true); try { const data = await userApi.setup2FA(); setSetupData({ secret: data.secret, qrCode: data.qrCode, }); setVerificationCode(""); } catch (error: any) { console.error("Ошибка настройки 2FA:", error); showNotification( error.response?.data?.error || "Ошибка настройки 2FA", "error" ); } finally { setIsLoading(false); } }; const handleEnable = async () => { if (!setupData || !verificationCode.trim()) { showNotification("Введите код подтверждения", "warning"); return; } if (verificationCode.trim().length !== 6) { showNotification("Код должен содержать 6 цифр", "warning"); return; } setIsLoading(true); try { const response = await userApi.enable2FA(setupData.secret, verificationCode.trim()); setBackupCodes(response.backupCodes); setShowBackupCodesModal(true); setSetupData(null); setVerificationCode(""); onStatusChange(); showNotification("2FA успешно включена", "success"); } catch (error: any) { console.error("Ошибка включения 2FA:", error); showNotification( error.response?.data?.error || "Ошибка включения 2FA", "error" ); } finally { setIsLoading(false); } }; const handleDisable = async () => { if (!disablePassword.trim()) { showNotification("Введите пароль", "warning"); return; } setIsDisabling(true); try { await userApi.disable2FA(disablePassword); setShowDisableModal(false); setDisablePassword(""); onStatusChange(); showNotification("2FA успешно отключена", "success"); } catch (error: any) { console.error("Ошибка отключения 2FA:", error); showNotification( error.response?.data?.error || "Ошибка отключения 2FA", "error" ); } finally { setIsDisabling(false); } }; const handleGenerateBackupCodes = async () => { setIsGeneratingBackupCodes(true); try { const response = await userApi.generateBackupCodes(); setBackupCodes(response.backupCodes); setShowBackupCodesModal(true); showNotification("Резервные коды успешно сгенерированы", "success"); } catch (error: any) { console.error("Ошибка генерации резервных кодов:", error); showNotification( error.response?.data?.error || "Ошибка генерации резервных кодов", "error" ); } finally { setIsGeneratingBackupCodes(false); } }; const copyToClipboard = (text: string) => { navigator.clipboard.writeText(text); showNotification("Скопировано в буфер обмена", "success"); }; return (

Двухфакторная аутентификация

Двухфакторная аутентификация добавляет дополнительный уровень безопасности к вашему аккаунту. Используйте приложение-аутентификатор (Google Authenticator, Microsoft Authenticator и т.д.) для генерации кодов.

{!twoFactorEnabled ? (
{!setupData ? (
) : (

Шаг 1: Отсканируйте QR-код

Откройте приложение-аутентификатор на вашем телефоне и отсканируйте этот QR-код:

QR Code

Или введите секретный ключ вручную:

{setupData.secret}

Шаг 2: Введите код подтверждения

Введите 6-значный код из приложения-аутентификатора:

{ const value = e.target.value.replace(/\D/g, "").slice(0, 6); setVerificationCode(value); }} maxLength={6} style={{ textAlign: "center", fontSize: "24px", letterSpacing: "8px", fontFamily: "monospace", }} />
)}
) : (
2FA включена

Двухфакторная аутентификация активна для вашего аккаунта.

)} {/* Модальное окно для отключения 2FA */} { setShowDisableModal(false); setDisablePassword(""); }} onConfirm={handleDisable} title="Отключение двухфакторной аутентификации" message={ <>

Вы уверены, что хотите отключить двухфакторную аутентификацию? Это снизит безопасность вашего аккаунта.

setDisablePassword(e.target.value)} onKeyPress={(e) => { if (e.key === "Enter" && !isDisabling && disablePassword.trim()) { handleDisable(); } }} />
} confirmText={isDisabling ? "Отключение..." : "Отключить"} cancelText="Отмена" confirmType="danger" /> {/* Модальное окно для показа резервных кодов */} setShowBackupCodesModal(false)} onConfirm={() => setShowBackupCodesModal(false)} title="Резервные коды" message={ <>

⚠️ ВАЖНО: Сохраните эти коды в безопасном месте!

Если вы потеряете доступ к приложению-аутентификатору, вы сможете использовать эти резервные коды для входа. Каждый код можно использовать только один раз.

{backupCodes && (
{backupCodes.map((code, index) => ( {code} ))}
)}

Совет: Распечатайте эти коды или сохраните их в менеджере паролей.

} confirmText="Я сохранил коды" cancelText={null} confirmType="primary" />
); };