From a045a1fbd844e1be797996aac5640c12508deff0 Mon Sep 17 00:00:00 2001 From: aewing Date: Sun, 29 Mar 2026 03:22:51 +0000 Subject: [PATCH] Add PocketBase token context diagnostics --- server.ts | 49 +++++++++++++++++++++++++++++++++++++++++++++---- tasks.html | 16 ++++++++++++++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/server.ts b/server.ts index 6e118f4..9b02307 100644 --- a/server.ts +++ b/server.ts @@ -57,6 +57,20 @@ async function createValidatedPbClient(token: string): Promise { return client; } +function decodeJwtPayload(token: string): Record | null { + try { + const parts = String(token || '').split('.'); + if (parts.length < 2) return null; + const base = parts[1].replace(/-/g, '+').replace(/_/g, '/'); + const padded = base + '='.repeat((4 - (base.length % 4 || 4)) % 4); + const payload = Buffer.from(padded, 'base64').toString('utf8'); + const parsed = JSON.parse(payload); + return parsed && typeof parsed === 'object' ? parsed as Record : null; + } catch { + return null; + } +} + // --------------------------------------------------------------------------- // Shared helpers // --------------------------------------------------------------------------- @@ -447,10 +461,21 @@ app.get('/api/tasks/users', async (c) => { if (!pbToken) return c.json({ success: false, message: 'Missing x-pb-token' }, 401); let taskPb: PocketBase; + const tokenPayload = decodeJwtPayload(pbToken); try { taskPb = await createValidatedPbClient(pbToken); - } catch { - return c.json({ success: false, message: 'Invalid PocketBase token' }, 401); + } catch (error) { + const message = (error as Error)?.message || String(error); + return c.json({ + success: false, + message: 'Invalid PocketBase token', + details: message, + tokenContext: { + type: String(tokenPayload?.type || ''), + collectionId: String(tokenPayload?.collectionId || ''), + collectionName: String(tokenPayload?.collectionName || ''), + }, + }, 401); } try { @@ -505,10 +530,21 @@ app.get('/api/tasks/list', async (c) => { if (!pbToken) return c.json({ success: false, message: 'Missing x-pb-token' }, 401); let taskPb: PocketBase; + const tokenPayload = decodeJwtPayload(pbToken); try { taskPb = await createValidatedPbClient(pbToken); - } catch { - return c.json({ success: false, message: 'Invalid PocketBase token' }, 401); + } catch (error) { + const message = (error as Error)?.message || String(error); + return c.json({ + success: false, + message: 'Invalid PocketBase token', + details: message, + tokenContext: { + type: String(tokenPayload?.type || ''), + collectionId: String(tokenPayload?.collectionId || ''), + collectionName: String(tokenPayload?.collectionName || ''), + }, + }, 401); } try { @@ -710,6 +746,11 @@ app.get('/api/tasks/list', async (c) => { email: meRecord?.email || '', name: meName, }, + tokenContext: { + type: String(tokenPayload?.type || ''), + collectionId: String(tokenPayload?.collectionId || ''), + collectionName: String(tokenPayload?.collectionName || ''), + }, count: records.length, lookupMethod, warning: warning || undefined, diff --git a/tasks.html b/tasks.html index 4321eda..03d43c6 100644 --- a/tasks.html +++ b/tasks.html @@ -311,7 +311,13 @@ }); const data = await resp.json().catch(() => ({})); if (!resp.ok || !data?.success) { - throw new Error(data?.message || 'Failed to load users'); + const details = data?.details + ? (typeof data.details === 'string' ? data.details : JSON.stringify(data.details)) + : ''; + const context = data?.tokenContext ? ` tokenContext=${JSON.stringify(data.tokenContext)}` : ''; + throw new Error(details + ? `${data?.message || 'Failed to load users'}: ${details}${context}` + : `${data?.message || 'Failed to load users'}${context}`); } usersCache = Array.isArray(data.users) ? data.users : []; @@ -390,7 +396,10 @@ const details = data?.details ? (typeof data.details === 'string' ? data.details : JSON.stringify(data.details)) : ''; - throw new Error(details ? `${data?.message || 'Failed to load tasks'}: ${details}` : (data?.message || 'Failed to load tasks')); + const context = data?.tokenContext ? ` tokenContext=${JSON.stringify(data.tokenContext)}` : ''; + throw new Error(details + ? `${data?.message || 'Failed to load tasks'}: ${details}${context}` + : `${data?.message || 'Failed to load tasks'}${context}`); } if (data?.userName && taskUserSelect.value !== data.userName) { taskUserSelect.value = data.userName; @@ -401,6 +410,7 @@ userName: data?.userName || userName, userId: data?.userId || undefined, authUser: data?.authUser || undefined, + tokenContext: data?.tokenContext || undefined, lookupMethod: data?.lookupMethod || undefined, warning: data?.warning || undefined, tasks: data.tasks || [], @@ -416,6 +426,8 @@ try { await client.collection(config.collection).authRefresh(); } catch { + client.authStore.clear(); + writeOutput('Existing PocketBase session could not refresh for Users collection. Please login again.'); } }