fix auth issues
This commit is contained in:
@@ -134,7 +134,14 @@ export async function load(event) {
|
|||||||
chat = await resolveChatIdentity(session, pbToken);
|
chat = await resolveChatIdentity(session, pbToken);
|
||||||
// fams is superadmin-only (non-realtime). Fetched server-side for both
|
// fams is superadmin-only (non-realtime). Fetched server-side for both
|
||||||
// roles; also recomputes + persists the derived `active` flag.
|
// roles; also recomputes + persists the derived `active` flag.
|
||||||
const res = await ensureFamAccess(famId).catch(() => null);
|
// Retried: a post-deploy PB blip here blanks `fam`, which both hides
|
||||||
|
// data AND disables the canonical slug redirect below (letting /{id}
|
||||||
|
// URLs persist).
|
||||||
|
let res: any = null;
|
||||||
|
for (let i = 0; i < 3 && !res; i++) {
|
||||||
|
if (i > 0) await new Promise((r) => setTimeout(r, 400 * i));
|
||||||
|
res = await ensureFamAccess(famId).catch(() => null);
|
||||||
|
}
|
||||||
if (res) {
|
if (res) {
|
||||||
fam = res.fam;
|
fam = res.fam;
|
||||||
famAccess = res.access;
|
famAccess = res.access;
|
||||||
|
|||||||
@@ -78,6 +78,14 @@
|
|||||||
// Settings stays usable while paused so admins can apply a code / manage billing.
|
// Settings stays usable while paused so admins can apply a code / manage billing.
|
||||||
let hasAuth = $derived(!!data.session);
|
let hasAuth = $derived(!!data.session);
|
||||||
let locked = $derived(disabled && !page.url.pathname.endsWith('/settings'));
|
let locked = $derived(disabled && !page.url.pathname.endsWith('/settings'));
|
||||||
|
// Expired-token zombie state: public PB rules still let logged-out users
|
||||||
|
// READ everything, so the dashboard looks alive while every write fails.
|
||||||
|
// Say so explicitly (join/switch/picker flows render their own UI).
|
||||||
|
let showLoggedOut = $derived(
|
||||||
|
!data.session &&
|
||||||
|
!pickerMode &&
|
||||||
|
!['join', 'switch'].includes(page.url.pathname.split('/')[2] || '')
|
||||||
|
);
|
||||||
|
|
||||||
// ── Post-checkout activation (event-driven) ──
|
// ── Post-checkout activation (event-driven) ──
|
||||||
// Landing with ?checkout=return: if the webhook has already landed we show
|
// Landing with ?checkout=return: if the webhook has already landed we show
|
||||||
@@ -282,6 +290,28 @@
|
|||||||
<div class="page-wrap">
|
<div class="page-wrap">
|
||||||
<div class="page-content" class:locked>{@render children()}</div>
|
<div class="page-content" class:locked>{@render children()}</div>
|
||||||
|
|
||||||
|
{#if showLoggedOut}
|
||||||
|
<div class="disabled-overlay loggedout-overlay">
|
||||||
|
<div class="disabled-card">
|
||||||
|
<strong>You're logged out</strong>
|
||||||
|
<span>
|
||||||
|
Your session expired, so everything below is read-only — toggles and
|
||||||
|
claims won't work until you log back in.
|
||||||
|
</span>
|
||||||
|
<span class="loggedout-actions">
|
||||||
|
<a class="btn-primary" href="/login">Parent log in</a>
|
||||||
|
{#if page.params.username}
|
||||||
|
<a
|
||||||
|
class="btn-secondary"
|
||||||
|
href={`/${data.famSlug || page.params.fam}/join/${page.params.username}`}
|
||||||
|
>Rejoin as {page.params.username}</a
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
<span class="hint">Kids: re-open your invite link, or ask a parent to send it again.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{#if locked}
|
{#if locked}
|
||||||
<div class="disabled-overlay">
|
<div class="disabled-overlay">
|
||||||
<div class="disabled-card">
|
<div class="disabled-card">
|
||||||
@@ -482,6 +512,34 @@
|
|||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
/* Logged-out card must be clickable (the paused overlay is display-only). */
|
||||||
|
.loggedout-overlay {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.loggedout-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.6rem;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 0.4rem;
|
||||||
|
}
|
||||||
|
.loggedout-actions a {
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0.5rem 1.1rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.loggedout-actions .btn-primary {
|
||||||
|
background: #6366f1;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.loggedout-actions .btn-secondary {
|
||||||
|
background: #eef2ff;
|
||||||
|
color: #4338ca;
|
||||||
|
}
|
||||||
|
.disabled-card .hint {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
}
|
||||||
.chat-toggle {
|
.chat-toggle {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
|||||||
@@ -847,6 +847,10 @@
|
|||||||
|
|
||||||
async function toggle(chore: AssignedChore) {
|
async function toggle(chore: AssignedChore) {
|
||||||
if (accessDisabled) return;
|
if (accessDisabled) return;
|
||||||
|
if (!pbToken) {
|
||||||
|
showToast('Logged out — please log in again to update chores.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (chore.isTodo && isTodoExpired(chore)) return;
|
if (chore.isTodo && isTodoExpired(chore)) return;
|
||||||
if (togglingIds.has(chore.id)) return;
|
if (togglingIds.has(chore.id)) return;
|
||||||
togglingIds = new Set(togglingIds).add(chore.id);
|
togglingIds = new Set(togglingIds).add(chore.id);
|
||||||
|
|||||||
@@ -30,8 +30,21 @@ export const actions = {
|
|||||||
// An explicit email/password login supersedes kid mode on a shared device.
|
// An explicit email/password login supersedes kid mode on a shared device.
|
||||||
clearActiveChild(event.cookies);
|
clearActiveChild(event.cookies);
|
||||||
|
|
||||||
const fam = await pbAdmin.getOne('fams', user.famId).catch(() => null);
|
// Fam lookup with retries: right after a deploy/rebuild PB can blip and
|
||||||
const famSlug = fam?.slug || user.famId;
|
// 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.
|
// Parents (admins) land on the fam dashboard — no username in the URL.
|
||||||
if (user.role === 'parent') {
|
if (user.role === 'parent') {
|
||||||
|
|||||||
Reference in New Issue
Block a user