From 089da94d8b41b3878b12a57213b78df78f31dd40 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Mon, 1 Jun 2026 19:41:15 +0200 Subject: [PATCH] fix(security): apply two findings from sharing security review - get_document: strip extracted_text for share recipients (T-04-04-03 consistency) - ShareModal: emit 'unshared' when last recipient is revoked; DocumentCard clears is_shared badge Co-Authored-By: Claude Sonnet 4.6 --- backend/api/documents.py | 5 +++++ frontend/src/components/documents/DocumentCard.vue | 1 + frontend/src/components/sharing/ShareModal.vue | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/backend/api/documents.py b/backend/api/documents.py index b4000cf..8f46651 100644 --- a/backend/api/documents.py +++ b/backend/api/documents.py @@ -545,6 +545,7 @@ async def get_document( if doc is None: raise HTTPException(404, "Document not found") + is_recipient = False if doc.user_id != current_user.id: # Allow recipients of an active share to view the document share_result = await session.execute( @@ -555,10 +556,14 @@ async def get_document( ) if share_result.scalar_one_or_none() is None: raise HTTPException(404, "Document not found") + is_recipient = True meta = await storage.get_metadata(session, doc_id) if meta is None: raise HTTPException(404, "Document not found") + # T-04-04-03: recipients get metadata only — extracted_text excluded (consistent with /shares/received) + if is_recipient: + meta.pop("extracted_text", None) return meta diff --git a/frontend/src/components/documents/DocumentCard.vue b/frontend/src/components/documents/DocumentCard.vue index 08a9ba8..e528be1 100644 --- a/frontend/src/components/documents/DocumentCard.vue +++ b/frontend/src/components/documents/DocumentCard.vue @@ -85,6 +85,7 @@ v-if="showShareModal" :doc="doc" @close="showShareModal = false" + @unshared="doc.is_shared = false" /> diff --git a/frontend/src/components/sharing/ShareModal.vue b/frontend/src/components/sharing/ShareModal.vue index 4b29809..5d77875 100644 --- a/frontend/src/components/sharing/ShareModal.vue +++ b/frontend/src/components/sharing/ShareModal.vue @@ -125,7 +125,7 @@ const props = defineProps({ }, }) -const emit = defineEmits(['close']) +const emit = defineEmits(['close', 'unshared']) const docsStore = useDocumentsStore() @@ -202,6 +202,7 @@ async function handleRevoke(shareId) { try { await docsStore.revokeShare(shareId) + if (shares.value.length === 0) emit('unshared', props.doc.id) } catch (e) { // Re-add on failure if (removed && removedIdx !== -1) {