final flows including emails for passwords
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
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 FamChore password',
|
||||
html: `
|
||||
<p>You requested a password reset for your FamChore 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 });
|
||||
}
|
||||
Reference in New Issue
Block a user