From b62ca14cc1fdf5e9e05bd2326ea89d91ebe91a0f Mon Sep 17 00:00:00 2001 From: elpatron Date: Thu, 28 May 2026 21:42:47 +0200 Subject: [PATCH] Fix invitee access to shared logbooks by listing collaborated logbooks in API and saving them locally on accept --- client/src/components/InvitationAcceptance.tsx | 14 ++++++++++++++ server/src/routes/logbooks.ts | 18 ++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/client/src/components/InvitationAcceptance.tsx b/client/src/components/InvitationAcceptance.tsx index ea5d9b5..179ca2c 100644 --- a/client/src/components/InvitationAcceptance.tsx +++ b/client/src/components/InvitationAcceptance.tsx @@ -4,6 +4,7 @@ import { Ship, LogIn, UserPlus, AlertTriangle, ShieldCheck, Languages, ArrowRigh import { getActiveMasterKey, registerUser, loginUser } from '../services/auth.js' import { decryptJson, encryptBuffer } from '../services/crypto.js' import { saveLogbookKey } from '../services/logbookKeys.js' +import { db } from '../services/db.js' import { useDialog } from './ModalDialog.tsx' interface InvitationAcceptanceProps { @@ -36,6 +37,7 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio const [ownerUsername, setOwnerUsername] = useState('') const [decryptedTitle, setDecryptedTitle] = useState('') const [logbookId, setLogbookId] = useState('') + const [rawEncryptedTitle, setRawEncryptedTitle] = useState('') // Authentication states const [isLoggedIn, setIsLoggedIn] = useState(false) @@ -104,6 +106,8 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio setOwnerUsername(details.ownerUsername) setLogbookId(details.logbookId) + setRawEncryptedTitle(details.encryptedTitle) + // Decrypt title client-side using URL key const parsed = JSON.parse(details.encryptedTitle) const title = await decryptJson(parsed.ciphertext, parsed.iv, parsed.tag, logbookKey!) @@ -158,6 +162,16 @@ export default function InvitationAcceptance({ onAccepted, onCancel }: Invitatio // 3. Save key locally in Dexie await saveLogbookKey(logbookId, logbookKey) + // 3b. Save logbook index locally in Dexie so sync is triggered immediately + if (rawEncryptedTitle) { + await db.logbooks.put({ + id: logbookId, + encryptedTitle: rawEncryptedTitle, + updatedAt: new Date().toISOString(), + isSynced: 1 + }) + } + // 4. Redirect to workspace onAccepted(logbookId, decryptedTitle) } catch (err: any) { diff --git a/server/src/routes/logbooks.ts b/server/src/routes/logbooks.ts index e11382e..a4c502c 100644 --- a/server/src/routes/logbooks.ts +++ b/server/src/routes/logbooks.ts @@ -15,11 +15,25 @@ const requireUser = (req: any, res: any, next: any) => { router.use(requireUser) -// 1. Get all logbooks for the authenticated user +// 1. Get all logbooks for the authenticated user (owned and shared) router.get('/', async (req: any, res) => { try { const logbooks = await prisma.logbook.findMany({ - where: { userId: req.userId }, + where: { + OR: [ + { userId: req.userId }, + { + collaborators: { + some: { userId: req.userId } + } + } + ] + }, + include: { + collaborators: { + where: { userId: req.userId } + } + }, orderBy: { createdAt: 'desc' } }) return res.json(logbooks)