feat: implement premium Email 2FA authentication integrated with auth flow

This commit is contained in:
2026-05-21 21:46:53 +07:00
parent a0673129ee
commit 0d083765ff
50 changed files with 543 additions and 162 deletions
+48
View File
@@ -21,6 +21,7 @@ interface SettingsProps extends PageProps {
enabled: boolean;
qr_code: string | null;
secret: string | null;
email_enabled: boolean;
recovery_codes: string[];
};
}
@@ -186,6 +187,25 @@ export default function SettingsIndex({ twoFactor }: SettingsProps) {
}
};
const handleToggleEmail2FA = async (enable: boolean) => {
const { value: password } = await Swal.fire({
title: enable ? 'Enable Email 2FA' : 'Disable Email 2FA',
text: 'Enter your password to confirm.',
input: 'password',
inputPlaceholder: 'Your current password',
showCancelButton: true,
confirmButtonText: 'Confirm',
confirmButtonColor: '#3D4E4B',
});
if (password) {
router.post(route('two-factor.email.toggle'), { password, enabled: enable }, {
preserveScroll: true,
onSuccess: () => swal.success('Success', `Email Two-Factor Authentication has been ${enable ? 'enabled' : 'disabled'} successfully.`),
onError: (errs) => swal.error('Error', errs.password || 'Incorrect password.'),
});
}
};
return (
<AuthenticatedLayout>
<Head title="Account Settings" />
@@ -426,6 +446,34 @@ export default function SettingsIndex({ twoFactor }: SettingsProps) {
</SectionCard>
</div>
)}
{/* Email 2FA Setup */}
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6 flex items-center gap-4">
<div className="w-12 h-12 rounded-xl bg-blue-50 flex items-center justify-center shrink-0">
<svg className="w-6 h-6 text-[#D4A017]" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
<div className="flex-1">
<div className="text-sm font-bold text-[#3D4E4B]">Two-Factor Authentication via Email</div>
<div className="text-xs text-gray-400 font-medium mt-0.5">
{twoFactor.email_enabled
? 'Email 2FA is active. Every login attempt will require an OTP code sent to your email.'
: 'Receive a 6-digit OTP code in your email to secure your login sessions.'}
</div>
</div>
{twoFactor.email_enabled ? (
<button onClick={() => handleToggleEmail2FA(false)} type="button"
className="h-9 px-5 text-xs font-bold text-red-500 border border-red-200 rounded-xl hover:bg-red-50 transition-all">
Disable Email 2FA
</button>
) : (
<button onClick={() => handleToggleEmail2FA(true)} type="button"
className="h-9 px-5 text-xs font-bold text-[#3D4E4B] border border-gray-200 rounded-xl hover:bg-gray-50 transition-all">
Enable Email 2FA
</button>
)}
</div>
</div>
)}