From 93d8c1f7753c4d90b894cafe475b7ca55b89a95e Mon Sep 17 00:00:00 2001 From: claude_code Date: Mon, 22 Jun 2026 02:49:17 +0300 Subject: [PATCH] fix(home): show "New note" button by resolving writability from role The button never rendered: it filtered spaces to writable ones via a CASL ability built from membership.permissions, but the /spaces list endpoint returns membership.role only (permissions come from /spaces/info). The empty ability hid the button for everyone. Resolve writability from membership.role instead, mirroring the server space-ability mapping (ADMIN and WRITER can manage pages, READER is read-only). Drop the now-unused CASL imports. Co-Authored-By: Claude Opus 4.8 --- .../home/components/new-note-button.tsx | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/apps/client/src/features/home/components/new-note-button.tsx b/apps/client/src/features/home/components/new-note-button.tsx index fc838fbb..154ad7a0 100644 --- a/apps/client/src/features/home/components/new-note-button.tsx +++ b/apps/client/src/features/home/components/new-note-button.tsx @@ -1,27 +1,22 @@ import { Button, Menu, Text } from "@mantine/core"; import { IconPlus } from "@tabler/icons-react"; -import { createMongoAbility } from "@casl/ability"; import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { useGetSpacesQuery } from "@/features/space/queries/space-query.ts"; import { useCreatePageMutation } from "@/features/page/queries/page-query.ts"; import { buildPageUrl } from "@/features/page/page.utils.ts"; import { ISpace } from "@/features/space/types/space.types.ts"; -import { - SpaceAbility, - SpaceCaslAction, - SpaceCaslSubject, -} from "@/features/space/permissions/permissions.type.ts"; +import { SpaceRole } from "@/lib/types.ts"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx"; import { AvatarIconType } from "@/features/attachments/types/attachment.types.ts"; -// A space is writable when the member's CASL rules allow managing pages — -// mirrors the create-page gate used in the space sidebar. +// The /spaces list endpoint returns membership.role but NOT membership.permissions +// (only /spaces/info includes CASL rules). Mirror the server space-ability mapping: +// ADMIN and WRITER can manage pages, READER is read-only. So a space is writable +// for the current user when their role is ADMIN or WRITER. function canCreatePage(space: ISpace): boolean { - const ability = createMongoAbility( - (space.membership?.permissions ?? []) as any, - ); - return ability.can(SpaceCaslAction.Manage, SpaceCaslSubject.Page); + const role = space.membership?.role; + return role === SpaceRole.ADMIN || role === SpaceRole.WRITER; } // Prominent home-screen action to create a new note (page). Because the home