feat: enforce SMTP configuration validation and show warning notices before enabling Email 2FA

This commit is contained in:
2026-05-21 21:55:00 +07:00
parent 4741a2dff2
commit 41bef637c9
38 changed files with 168 additions and 136 deletions
+22 -5
View File
@@ -22,6 +22,7 @@ interface SettingsProps extends PageProps {
qr_code: string | null;
secret: string | null;
email_enabled: boolean;
smtp_configured: boolean;
recovery_codes: string[];
};
}
@@ -30,7 +31,7 @@ interface SettingsProps extends PageProps {
function SectionCard({ title, description, children, delay = '0s', variant = 'default' }: { title: string; description: string; children: React.ReactNode; delay?: string; variant?: 'default' | 'danger' }) {
const isDanger = variant === 'danger';
return (
<div className={`bg-white rounded-2xl border ${isDanger ? 'border-red-200 shadow-none' : 'border-gray-100 shadow-sm'} overflow-hidden h-full flex flex-col anim-up`} style={{ animationDelay: delay }}>
<div className={`px-6 py-4 border-b ${isDanger ? 'border-red-100 bg-red-50' : 'border-gray-50 bg-gray-50/30'}`}>
@@ -198,6 +199,16 @@ export default function SettingsIndex({ twoFactor }: SettingsProps) {
};
const handleToggleEmail2FA = async (enable: boolean) => {
if (enable && !twoFactor.smtp_configured) {
Swal.fire({
icon: 'warning',
title: 'SMTP Mail Server Not Set Up',
text: 'Two-Factor Authentication via Email cannot be enabled because the system SMTP configurations are not set up yet. Please configure the SMTP settings under System Settings (or contact your Administrator) first.',
confirmButtonColor: '#3D4E4B',
});
return;
}
if (enable && twoFactor.enabled) {
const warning = await swal.confirm(
'Switch to Email 2FA?',
@@ -305,7 +316,7 @@ export default function SettingsIndex({ twoFactor }: SettingsProps) {
</form>
</SectionCard>
</div>
<div className="lg:col-span-1">
<SectionCard title="Profile Photo" description="Update your avatar" delay="0.15s">
<div className="flex flex-col items-center gap-6">
@@ -356,7 +367,7 @@ export default function SettingsIndex({ twoFactor }: SettingsProps) {
)}
{activeTab === '2fa' && (
<div className="max-w-3xl space-y-6 anim-fade">
<div className="max-w-4xl space-y-8 anim-fade">
<div className="p-5 bg-amber-50 border border-amber-200 rounded-2xl flex items-start gap-3">
<svg className="w-5 h-5 text-amber-500 mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
@@ -476,10 +487,16 @@ export default function SettingsIndex({ twoFactor }: SettingsProps) {
<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.'
{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>
{!twoFactor.smtp_configured && (
<div className="flex items-center gap-1.5 mt-2 text-[11px] font-bold text-amber-600 bg-amber-50 px-2.5 py-1 rounded-lg w-fit border border-amber-200">
<span className="text-sm"></span>
<span>SMTP Mail Server is not configured. Setup required.</span>
</div>
)}
</div>
{twoFactor.email_enabled ? (
<button onClick={() => handleToggleEmail2FA(false)} type="button"