add shared login pin mechansim
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { createPbClient } from '$lib/server/pocketbase';
|
||||
import { createPbClient, createSuperClient } from '$lib/server/pocketbase';
|
||||
import { createServices, type ChatActor } from '$lib/server/services';
|
||||
import { ensureFamAccess } from '$lib/server/access';
|
||||
import { seedDemoCompletions } from '$lib/server/migrate';
|
||||
import { getPlatformFlags } from '$lib/server/platform';
|
||||
import { scanChildSessions } from '$lib/server/session';
|
||||
|
||||
async function paydayCheck(famId: string, pbToken: string) {
|
||||
try {
|
||||
@@ -56,7 +57,62 @@ export async function load(event) {
|
||||
const session = event.locals.user;
|
||||
const role = session?.role || 'child';
|
||||
const isParent = role === 'parent';
|
||||
const pbToken = event.cookies.get('pb_token') || '';
|
||||
const pbToken = event.locals.pbToken || '';
|
||||
const deviceChildIds = scanChildSessions(event.cookies);
|
||||
|
||||
// ── Shared-device picker mode ──
|
||||
// The device holds child sessions but none is active (per-profile logout).
|
||||
// Anything except the join flow lands on the standalone picker.
|
||||
const paramFam = event.params.fam;
|
||||
const isJoinPage = (event.url.pathname || '').split('/').includes('join');
|
||||
if (!session && deviceChildIds.length > 0 && !isJoinPage) {
|
||||
if (!(event.url.pathname || '').endsWith('/switch')) {
|
||||
throw redirect(303, `/${encodeURIComponent(paramFam)}/switch`);
|
||||
}
|
||||
let pickerFamName = paramFam || '';
|
||||
let pickerChildren: {
|
||||
id: string;
|
||||
name: string;
|
||||
color: string;
|
||||
username: string;
|
||||
}[] = [];
|
||||
try {
|
||||
const pb = await createSuperClient();
|
||||
const fam = await pb
|
||||
.collection('fams')
|
||||
.getFirstListItem(`slug='${paramFam}'`)
|
||||
.catch(() => null);
|
||||
if (fam) {
|
||||
pickerFamName = fam.name || fam.slug;
|
||||
const users = await pb.collection('users').getFullList({
|
||||
filter: `id in ('${deviceChildIds.join("','")}') && role='child'`
|
||||
});
|
||||
pickerChildren = (users || []).map((u: any) => ({
|
||||
id: u.id,
|
||||
name: u.name || u.username || '',
|
||||
color: u.color || '#6366f1',
|
||||
username: u.username || ''
|
||||
}));
|
||||
}
|
||||
} catch {}
|
||||
return {
|
||||
famSlug: paramFam || '',
|
||||
session: null,
|
||||
isParent,
|
||||
role,
|
||||
famId: '',
|
||||
chat: null,
|
||||
pbToken: '',
|
||||
fam: null,
|
||||
famAccess: { disabled: false, mode: 'none', reason: '' },
|
||||
demoMode: (await getPlatformFlags()).demo,
|
||||
picker: true,
|
||||
pickerFamName,
|
||||
pickerChildren,
|
||||
deviceChildIds,
|
||||
lockMins: 0
|
||||
};
|
||||
}
|
||||
|
||||
let famId = '';
|
||||
let chat: {
|
||||
@@ -70,6 +126,7 @@ export async function load(event) {
|
||||
mode: 'none' as 'none' | 'code' | 'sub' | 'canceled',
|
||||
reason: ''
|
||||
};
|
||||
let lockMins = 0;
|
||||
|
||||
if (session && pbToken) {
|
||||
famId = session.famId;
|
||||
@@ -82,11 +139,22 @@ export async function load(event) {
|
||||
fam = res.fam;
|
||||
famAccess = res.access;
|
||||
}
|
||||
// Shared-device idle lock setting (0 = off; missing row defaults to 10
|
||||
// min). Superuser read — the settings rules are parent-oriented and
|
||||
// children must see it too.
|
||||
try {
|
||||
const pb = await createSuperClient();
|
||||
const settings = await pb
|
||||
.collection('settings')
|
||||
.getFullList({ filter: `famId='${famId}'` })
|
||||
.catch(() => []);
|
||||
const row = (settings as any[])?.[0];
|
||||
lockMins = row && row.lockMins != null ? Number(row.lockMins) : 10;
|
||||
} catch {}
|
||||
// Canonical URL: the [fam] segment must be the family SLUG, never the PB
|
||||
// id. If someone lands on /{famId}/... (a stale shortcut, bookmark, or a
|
||||
// login that fell back to the id), rewrite the first path segment to the
|
||||
// slug so the id is replaced everywhere it'd otherwise persist.
|
||||
const paramFam = event.params.fam;
|
||||
const canonicalSlug = fam?.slug;
|
||||
if (canonicalSlug && paramFam && paramFam !== canonicalSlug) {
|
||||
const rest = event.url.pathname.replace(`/${paramFam}`, '') || '/';
|
||||
@@ -100,7 +168,7 @@ export async function load(event) {
|
||||
return {
|
||||
// Canonical fam slug — from the URL param ([fam] routes). Client code
|
||||
// reads page.data.famSlug; never copy it into local $state.
|
||||
famSlug: event.params.fam || '',
|
||||
famSlug: paramFam || '',
|
||||
session: session
|
||||
? {
|
||||
famId: session.famId,
|
||||
@@ -121,6 +189,11 @@ export async function load(event) {
|
||||
pbToken,
|
||||
fam,
|
||||
famAccess,
|
||||
demoMode
|
||||
demoMode,
|
||||
picker: false,
|
||||
pickerFamName: '',
|
||||
pickerChildren: [],
|
||||
deviceChildIds,
|
||||
lockMins
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user