63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import { json } from '@sveltejs/kit';
|
|
import { RESEND_API } from '$app/env/private';
|
|
import { createSuperClient } from '$lib/server/pocketbase';
|
|
import { Resend } from 'resend';
|
|
|
|
export async function POST({ request, url }) {
|
|
const fd = await request.formData();
|
|
const email = (fd.get('email') || '').toString().trim().toLowerCase();
|
|
|
|
if (!email) {
|
|
return json({ ok: true }); // Generic response to avoid enumeration
|
|
}
|
|
|
|
try {
|
|
const pb = await createSuperClient();
|
|
|
|
// Find user by email
|
|
let user;
|
|
try {
|
|
user = await pb.collection('users').getFirstListItem(`email = '${email}'`);
|
|
} catch {
|
|
// User not found — still return success
|
|
return json({ ok: true });
|
|
}
|
|
|
|
// Only allow password reset for parents (they have emails)
|
|
if (user.role !== 'parent') {
|
|
return json({ ok: true });
|
|
}
|
|
|
|
// Generate token and expiry (1 hour)
|
|
const token = globalThis.crypto.randomUUID();
|
|
const expiry = new Date(Date.now() + 60 * 60 * 1000).toISOString();
|
|
|
|
// Store token on user record
|
|
await pb.collection('users').update(user.id, {
|
|
passwordResetToken: token,
|
|
passwordResetExpiry: expiry
|
|
});
|
|
|
|
// Send email via Resend
|
|
const resend = new Resend(String(RESEND_API));
|
|
const resetUrl = `${url.origin}/login/verify/${token}`;
|
|
|
|
await resend.emails.send({
|
|
from: 'no-reply@famchamp.ai',
|
|
to: email,
|
|
subject: 'Reset your FamDone password',
|
|
html: `
|
|
<p>You requested a password reset for your FamDone account.</p>
|
|
<p><a href="${resetUrl}">Click here to reset your password</a></p>
|
|
<p>This link expires in 1 hour.</p>
|
|
<p>If you didn't request this, you can ignore this email.</p>
|
|
`
|
|
});
|
|
} catch {
|
|
// Swallow all errors to avoid information leakage
|
|
}
|
|
|
|
// Always return success
|
|
return json({ ok: true });
|
|
}
|