Files
famdone/frontend/src/routes/login/+page.server.ts
T
2026-09-16 21:07:21 +01:00

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}`);
}
};