Skip to content

EDM-3608: Check permissions for catalog/item list#602

Merged
rawagner merged 2 commits intoflightctl:mainfrom
rawagner:catalog_permissions
Mar 31, 2026
Merged

EDM-3608: Check permissions for catalog/item list#602
rawagner merged 2 commits intoflightctl:mainfrom
rawagner:catalog_permissions

Conversation

@rawagner
Copy link
Copy Markdown
Collaborator

@rawagner rawagner commented Mar 30, 2026

Summary by CodeRabbit

  • New Features
    • Permission-based access gating added across catalog pages, wizards, install/edit flows so content is shown only when appropriate list/get/create/patch rights are present.
    • "Choose from catalog" button now appears only for users with catalog-item list permission.
    • Pages and wizards display loading indicators while permissions are being verified to improve UX during access checks.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 643c627d-bffa-48b8-b228-074b5d3a86f0

📥 Commits

Reviewing files that changed from the base of the PR and between 4793899 and e8a66ef.

📒 Files selected for processing (6)
  • libs/ui-components/src/components/Catalog/AddCatalogItemWizard/AddCatalogItemWizard.tsx
  • libs/ui-components/src/components/Catalog/CatalogPage.tsx
  • libs/ui-components/src/components/Catalog/EditWizard/EditWizard.tsx
  • libs/ui-components/src/components/Catalog/InstallWizard/InstallWizard.tsx
  • libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx
  • libs/ui-components/src/components/DynamicForm/VolumeImageField.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • libs/ui-components/src/components/DynamicForm/VolumeImageField.tsx
  • libs/ui-components/src/components/Catalog/EditWizard/EditWizard.tsx
  • libs/ui-components/src/components/Catalog/AddCatalogItemWizard/AddCatalogItemWizard.tsx
  • libs/ui-components/src/components/Catalog/InstallWizard/InstallWizard.tsx
  • libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx

Walkthrough

Several catalog-related UI components now perform RBAC checks via the permissions context and render their content inside a PageWithPermissions gate based on derived permission booleans and loading state.

Changes

Cohort / File(s) Summary
Catalog Pages
libs/ui-components/src/components/Catalog/CatalogPage.tsx, libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx
Added permission checks for RESOURCE.CATALOG_ITEM: LIST and RESOURCE.CATALOG: LIST; derive canListItems / canListCatalogs and loading via usePermissionsContext().checkPermissions; page content is wrapped in PageWithPermissions with allowed={canListItems && canListCatalogs}.
Create / Edit / Install Wizards
libs/ui-components/src/components/Catalog/AddCatalogItemWizard/AddCatalogItemWizard.tsx, libs/ui-components/src/components/Catalog/EditWizard/EditWizard.tsx, libs/ui-components/src/components/Catalog/InstallWizard/InstallWizard.tsx
Exported wrappers now gate wizard rendering with RBAC checks using usePermissionsContext and checkPermissions. Default exports changed to permission-wrapped components in AddCatalogItemWizard and InstallWizard; Edit wizards wrapped with PageWithPermissions using RESOURCE.CATALOG_ITEM GET (and additional verbs for add/edit) to compute allowed.
Dynamic Form — Catalog Selection
libs/ui-components/src/components/DynamicForm/VolumeImageField.tsx
"Choose from catalog" button is now conditionally rendered only when RESOURCE.CATALOG_ITEM: LIST permission is granted (checked via usePermissionsContext), preventing unauthorized users from opening the catalog modal.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Component
    participant PermissionsCtx
    participant PageWithPerms
    participant UI

    User->>Component: navigate / open page or wizard
    Component->>PermissionsCtx: checkPermissions(permissionSet)
    PermissionsCtx-->>Component: { canX, canY, loading }
    Component->>PageWithPerms: render(allowed=(canX && canY), loading=loading)
    PageWithPerms-->>Component: show gated content OR show denied/loading
    Component->>UI: render inner UI (or denied/loading state)
    UI-->>User: display result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly summarizes the main change: adding RBAC permission checks for catalog and catalog item list operations across multiple components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx (1)

26-29: Permission gating implementation looks correct.

The permission check setup and PageWithPermissions wrapper correctly gate access based on canListItems && canListCatalogs. Per learnings, checkPermissions is a pure calculation on cached permission arrays, so the loading state handling here is appropriate.

Note: This file defines its own catalogPagePermissions constant (lines 26-29) that duplicates the one in CatalogPage.tsx (lines 428-429). Consider extracting this to a shared location to avoid drift.

Also applies to: 41-42, 59-59, 75-75

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx`
around lines 26 - 29, The constant catalogPagePermissions is duplicated (defined
in ResourceCatalogPage as catalogPagePermissions and also in CatalogPage) —
extract this shared permission array into a single exported symbol (e.g., export
const catalogPagePermissions from a shared permissions module or from
CatalogPage) and update ResourceCatalogPage to import and use that single
exported catalogPagePermissions instead of redefining it; update all usages
(e.g., where PageWithPermissions consumes catalogPagePermissions and any local
references to canListItems/canListCatalogs) to reference the shared symbol so
the permission definition is centralized and avoids drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx`:
- Around line 26-29: The constant catalogPagePermissions is duplicated (defined
in ResourceCatalogPage as catalogPagePermissions and also in CatalogPage) —
extract this shared permission array into a single exported symbol (e.g., export
const catalogPagePermissions from a shared permissions module or from
CatalogPage) and update ResourceCatalogPage to import and use that single
exported catalogPagePermissions instead of redefining it; update all usages
(e.g., where PageWithPermissions consumes catalogPagePermissions and any local
references to canListItems/canListCatalogs) to reference the shared symbol so
the permission definition is centralized and avoids drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2842fb4e-f522-4d34-815e-9ec077ec897c

📥 Commits

Reviewing files that changed from the base of the PR and between f5d7f94 and b596848.

📒 Files selected for processing (2)
  • libs/ui-components/src/components/Catalog/CatalogPage.tsx
  • libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx

onInstall: (installItem: { item: CatalogItem; channel: string; version: string }) => void;
};

const catalogPagePermissions = [
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good for CatalogPage, but I believe other sections in the UI also need additional checks.
Quick review from Cursor:

The add/edit item wizard’s General Info step, install wizard, edit-from-catalog wizard, edit item wizard, and asset picker modal can still issue catalog/catalog-item requests without a matching client-side permission check first;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added those additional locations as well

@rawagner rawagner force-pushed the catalog_permissions branch from b596848 to 4793899 Compare March 30, 2026 09:34
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
libs/ui-components/src/components/Catalog/EditWizard/EditWizard.tsx (1)

252-253: Avoid per-component permission loading gates for cached checks.

Line 252 and Line 280 already use checkPermissions, which is synchronous against cached permissions. Passing permissionsLoading into PageWithPermissions here adds unnecessary spinner gating; prefer gating only by allowed.

♻️ Suggested simplification
-  const { checkPermissions, loading: permissionsLoading } = usePermissionsContext();
+  const { checkPermissions } = usePermissionsContext();
   const [canGetItem] = checkPermissions(editWizardPermissions);
@@
-    <PageWithPermissions allowed={canGetItem} loading={permissionsLoading}>
+    <PageWithPermissions allowed={canGetItem} loading={false}>
@@
-  const { checkPermissions, loading: permissionsLoading } = usePermissionsContext();
+  const { checkPermissions } = usePermissionsContext();
   const [canGetItem] = checkPermissions(editWizardPermissions);
@@
-    <PageWithPermissions allowed={canGetItem} loading={permissionsLoading}>
+    <PageWithPermissions allowed={canGetItem} loading={false}>

Based on learnings: In PR #376, checkPermissions in usePermissionsContext is a pure calculation on cached permissions and loading state handling is generally not required at individual component call sites.

Also applies to: 259-260, 280-281, 287-288

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/ui-components/src/components/Catalog/EditWizard/EditWizard.tsx` around
lines 252 - 253, The component is passing the synchronous cached-loading flag
permissionsLoading from usePermissionsContext into PageWithPermissions, causing
unnecessary spinner gating; instead call checkPermissions (as already done to
get canGetItem) and remove permissionsLoading from PageWithPermissions props so
gating is driven only by the allowed boolean (e.g., canGetItem). Update all
occurrences where permissionsLoading is forwarded (including the other
checkPermissions usages around the EditWizard component such as the
canGetItem/canEdit checks) to stop passing permissionsLoading and rely solely on
the allowed flags.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@libs/ui-components/src/components/Catalog/AddCatalogItemWizard/AddCatalogItemWizard.tsx`:
- Around line 256-260: The edit-mode permission gate
(addCatalogItemWizardPermissions) currently requires VERB.PATCH for
RESOURCE.CATALOG_ITEM but not VERB.GET, causing fetch errors when the component
(which calls the GET for the item at load) lacks read permission; update
addCatalogItemWizardPermissions to include { kind: RESOURCE.CATALOG_ITEM, verb:
VERB.GET } alongside the existing PATCH/CREATE entries so users who can edit
also have permission to fetch the item (refer to
addCatalogItemWizardPermissions, RESOURCE.CATALOG_ITEM, VERB.GET, VERB.PATCH).

---

Nitpick comments:
In `@libs/ui-components/src/components/Catalog/EditWizard/EditWizard.tsx`:
- Around line 252-253: The component is passing the synchronous cached-loading
flag permissionsLoading from usePermissionsContext into PageWithPermissions,
causing unnecessary spinner gating; instead call checkPermissions (as already
done to get canGetItem) and remove permissionsLoading from PageWithPermissions
props so gating is driven only by the allowed boolean (e.g., canGetItem). Update
all occurrences where permissionsLoading is forwarded (including the other
checkPermissions usages around the EditWizard component such as the
canGetItem/canEdit checks) to stop passing permissionsLoading and rely solely on
the allowed flags.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cf0c6f8c-6b22-4d13-819a-293ac62c06ca

📥 Commits

Reviewing files that changed from the base of the PR and between b596848 and 4793899.

📒 Files selected for processing (6)
  • libs/ui-components/src/components/Catalog/AddCatalogItemWizard/AddCatalogItemWizard.tsx
  • libs/ui-components/src/components/Catalog/CatalogPage.tsx
  • libs/ui-components/src/components/Catalog/EditWizard/EditWizard.tsx
  • libs/ui-components/src/components/Catalog/InstallWizard/InstallWizard.tsx
  • libs/ui-components/src/components/Catalog/ResourceCatalog/ResourceCatalogPage.tsx
  • libs/ui-components/src/components/DynamicForm/VolumeImageField.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/ui-components/src/components/Catalog/CatalogPage.tsx

@rawagner rawagner force-pushed the catalog_permissions branch from 4793899 to e8a66ef Compare March 30, 2026 09:47
Copy link
Copy Markdown

@siserafin siserafin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@rawagner rawagner merged commit 642aea3 into flightctl:main Mar 31, 2026
9 checks passed
rawagner added a commit to rawagner/flightctl-ui that referenced this pull request Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants