From 5deefa12059a91184db545dcc8d54043e16b6ee9 Mon Sep 17 00:00:00 2001 From: Stephen Adamson Date: Wed, 29 Jul 2026 23:32:07 +0100 Subject: [PATCH] fix: prevent empty login form submission Fix isFormComplete derived always returning true for login mode. Now requires email and password to be non-empty before enabling Sign In button. Add early-return guard in handleSubmit to prevent sending empty credentials. --- frontend/src/routes/login/+page.svelte | 47 +++++++++++++++----------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index 1037634..b1e209e 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -15,7 +15,7 @@ import * as languageCommon from '@zxcvbn-ts/language-common'; import * as languageEn from '@zxcvbn-ts/language-en'; import { toast } from 'svelte-sonner'; - import { sanitizeText } from '$lib/utils/toast-safe'; + import { extractErrorMessage, sanitizeText } from '$lib/utils/toast-safe'; // set up options so that feedback, dictionary etc. are included const zxcvbn = new ZxcvbnFactory({ @@ -144,6 +144,12 @@ async function handleSubmit() { if (isLogin) { + const email = formData.email.trim().toLowerCase(); + if (!email || !formData.password) { + toast.error('Please enter your email and password.'); + return; + } + // Login flow with loading toast const loadingToast = toast.loading('Signing in...'); @@ -152,7 +158,7 @@ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ - email: formData.email.trim().toLowerCase(), + email, password: formData.password }) }); @@ -179,7 +185,7 @@ toast.error('Invalid email or password.', { id: loadingToast }); } else { const text = await response.text(); - toast.error('Error: ' + sanitizeText(text), { id: loadingToast }); + toast.error('Error: ' + sanitizeText(extractErrorMessage(text)), { id: loadingToast }); } } catch (err) { console.error(err); @@ -213,7 +219,7 @@ toggleMode(); } else { const text = await response.text(); - toast.error('Error: ' + sanitizeText(text), { id: loadingToast }); + toast.error('Error: ' + sanitizeText(extractErrorMessage(text)), { id: loadingToast }); } } catch (err) { console.error(err); @@ -248,22 +254,23 @@ // form completion check const isFormComplete = $derived( - isLogin || - (formData.firstName.trim() && - formData.lastName.trim() && - formData.phone && - formData.dateOfBirth && - formData.email && - formData.password && - formData.confirmPassword && - formData.password === formData.confirmPassword && - passwordStrength && - formData.password.length >= 6 && - passwordStrength.score >= 2 && - agreedToPolicy && - !validationErrors.email && - !validationErrors.phone && - !validationErrors.dateOfBirth) + isLogin + ? formData.email.trim().length > 0 && formData.password.length > 0 + : (formData.firstName.trim() && + formData.lastName.trim() && + formData.phone && + formData.dateOfBirth && + formData.email && + formData.password && + formData.confirmPassword && + formData.password === formData.confirmPassword && + passwordStrength && + formData.password.length >= 6 && + passwordStrength.score >= 2 && + agreedToPolicy && + !validationErrors.email && + !validationErrors.phone && + !validationErrors.dateOfBirth) );