From 709184ae0b08e72b642e66d6dca88ba5b6f5c7d1 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 8 Jun 2026 17:44:09 -0400 Subject: [PATCH] fix: Before/After creation options appear in menu when no permission on parent doc (#12629) * fix: Before/After creation options appear in menu when no permission on parent closes #12624 * fix: Manager of root document sees non-functional Before/After create options Before/After only gated on the team-level createDocument ability, so a user with document-level manager access (but no collection access) saw the options yet hit a backend rejection. Gate on the actual sibling location instead, mirroring authorizeDocumentCreate. Co-Authored-By: Claude Opus 4.8 --------- Co-authored-by: Claude Opus 4.8 --- app/actions/definitions/documents.tsx | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/app/actions/definitions/documents.tsx b/app/actions/definitions/documents.tsx index 57c7990151..0c2e18517b 100644 --- a/app/actions/definitions/documents.tsx +++ b/app/actions/definitions/documents.tsx @@ -240,6 +240,26 @@ function findDocumentSiblingIndex( return siblings?.findIndex((node) => node.id === document.id) ?? -1; } +/** + * Determines whether the user can create a sibling of the given document. + * A sibling shares the document's parent, so this mirrors the backend's + * create authorization: create permission on the parent document, or on the + * collection when the document is at the root. + * + * @param stores - the root stores. + * @param document - the document to create a sibling of. + * @returns true if the user can create a sibling. + */ +function canCreateSiblingDocument( + stores: ActionContext["stores"], + document: { collectionId?: string | null; parentDocumentId?: string } +): boolean { + return document.parentDocumentId + ? stores.policies.abilities(document.parentDocumentId).createChildDocument + : !!document.collectionId && + stores.policies.abilities(document.collectionId).createDocument; +} + export const createNestedDocument = createInternalLinkAction({ name: ({ t }) => t("Nested document"), analyticsName: "New document", @@ -279,7 +299,7 @@ const createDocumentBefore = createInternalLinkAction({ if (collection?.sort.field === "title") { return false; } - return stores.policies.abilities(currentTeamId).createDocument; + return canCreateSiblingDocument(stores, document); }, to: ({ activeDocumentId, stores, sidebarContext }) => { const document = activeDocumentId @@ -321,7 +341,7 @@ const createDocumentAfter = createInternalLinkAction({ if (collection?.sort.field === "title") { return false; } - return stores.policies.abilities(currentTeamId).createDocument; + return canCreateSiblingDocument(stores, document); }, to: ({ activeDocumentId, stores, sidebarContext }) => { const document = activeDocumentId