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';