From 9b2ca21d28aac26243d2085e93eb22d54174d0c6 Mon Sep 17 00:00:00 2001 From: Sanju Sivalingam Date: Wed, 18 Feb 2026 22:47:12 +0530 Subject: [PATCH] fix: address code review issues for email verification - Use $env/dynamic/private instead of process.env (SvelteKit convention) - Fail fast if USESEND_API_KEY is missing - Await sendEmail with try/catch + console.error (was silently discarded) - Fallback for user.name in email greeting - Fix open redirect on login redirect param --- web/src/lib/api/auth.remote.ts | 3 ++- web/src/lib/server/auth.ts | 14 +++++++++----- web/src/lib/server/email.ts | 5 ++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/web/src/lib/api/auth.remote.ts b/web/src/lib/api/auth.remote.ts index 2a60987..5706e55 100644 --- a/web/src/lib/api/auth.remote.ts +++ b/web/src/lib/api/auth.remote.ts @@ -23,7 +23,8 @@ export const login = form(loginSchema, async (user) => { throw err; } const next = url.searchParams.get('redirect') || '/dashboard'; - redirect(303, next); + const safeNext = next.startsWith('/') && !next.startsWith('//') ? next : '/dashboard'; + redirect(303, safeNext); }); export const signout = form(async () => { diff --git a/web/src/lib/server/auth.ts b/web/src/lib/server/auth.ts index a4b57fd..883ac62 100644 --- a/web/src/lib/server/auth.ts +++ b/web/src/lib/server/auth.ts @@ -15,11 +15,15 @@ export const auth = betterAuth({ plugins: [sveltekitCookies(getRequestEvent), apiKey()], emailVerification: { sendVerificationEmail: async ({ user, url }) => { - void sendEmail({ - to: user.email, - subject: 'Verify your DroidClaw email', - text: `Hi ${user.name},\n\nClick the link below to verify your email:\n\n${url}\n\nThis link expires in 1 hour.\n\n-- DroidClaw` - }); + try { + await sendEmail({ + to: user.email, + subject: 'Verify your DroidClaw email', + text: `Hi ${user.name || 'there'},\n\nClick the link below to verify your email:\n\n${url}\n\nThis link expires in 1 hour.\n\n-- DroidClaw` + }); + } catch (err) { + console.error('Failed to send verification email:', err); + } }, sendOnSignUp: true, sendOnSignIn: true, diff --git a/web/src/lib/server/email.ts b/web/src/lib/server/email.ts index 3f015e6..4c3da77 100644 --- a/web/src/lib/server/email.ts +++ b/web/src/lib/server/email.ts @@ -1,6 +1,9 @@ +import { env } from '$env/dynamic/private'; import { UseSend } from 'usesend-js'; -const usesend = new UseSend(process.env.USESEND_API_KEY!); +if (!env.USESEND_API_KEY) throw new Error('USESEND_API_KEY is not set'); + +const usesend = new UseSend(env.USESEND_API_KEY); const EMAIL_FROM = 'noreply@app.droidclaw.ai';