59 lines
2.0 KiB
TypeScript
59 lines
2.0 KiB
TypeScript
import { fail, redirect } from '@sveltejs/kit';
|
|
import { createPbClient } from '$lib/server/pocketbase';
|
|
import { setSessionCookie, clearActiveChild } from '$lib/server/session';
|
|
import { pbAdmin } from '$lib/server/pocketbase';
|
|
import { handleOf } from '@shared/slugify';
|
|
|
|
export const actions = {
|
|
default: async (event) => {
|
|
const fd = await event.request.formData();
|
|
const email = fd.get('email') as string;
|
|
const password = fd.get('password') as string;
|
|
|
|
if (!email || !password) {
|
|
return fail(400, { error: 'Email and password required', email });
|
|
}
|
|
|
|
let authResult: { token: string; record: any };
|
|
try {
|
|
authResult = await createPbClient().collection('users').authWithPassword(email, password);
|
|
} catch {
|
|
return fail(400, { error: 'Invalid email or password', email });
|
|
}
|
|
|
|
const user = authResult.record;
|
|
if (!user.famId) {
|
|
return fail(400, { error: 'No family linked to this account', email });
|
|
}
|
|
|
|
setSessionCookie(event.cookies, authResult.token);
|
|
// An explicit email/password login supersedes kid mode on a shared device.
|
|
clearActiveChild(event.cookies);
|
|
|
|
// Fam lookup with retries: right after a deploy/rebuild PB can blip and
|
|
// a single failed fetch falls back to the raw fam ID in the URL
|
|
// (/{famId}/...), which then persists via bookmarks/shortcuts.
|
|
let fam: any = null;
|
|
for (let i = 0; i < 4 && !fam; i++) {
|
|
if (i > 0) await new Promise((r) => setTimeout(r, 500 * i));
|
|
fam = await pbAdmin.getOne('fams', user.famId).catch(() => null);
|
|
}
|
|
if (!fam) {
|
|
return fail(503, {
|
|
error: 'Family data is briefly unavailable (server restarting). Please try again.',
|
|
email
|
|
});
|
|
}
|
|
const famSlug = fam.slug;
|
|
|
|
// Parents (admins) land on the fam dashboard — no username in the URL.
|
|
if (user.role === 'parent') {
|
|
throw redirect(303, `/${famSlug}`);
|
|
}
|
|
|
|
// Children don't log in via email; this is just a safe fallback.
|
|
const handle = handleOf(user.username || '') || user.name || email.split('@')[0];
|
|
throw redirect(303, `/${famSlug}/${handle}`);
|
|
}
|
|
};
|