Skip to content

feat: integrate PermissionProvider and permission hooks#1704

Merged
rishiraj38 merged 6 commits into
layer5io:masterfrom
rishiraj38:feat/permission-provider
Jul 13, 2026
Merged

feat: integrate PermissionProvider and permission hooks#1704
rishiraj38 merged 6 commits into
layer5io:masterfrom
rishiraj38:feat/permission-provider

Conversation

@rishiraj38

@rishiraj38 rishiraj38 commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

This PR implements a generic, CASL-agnostic PermissionProvider in Sistent and integrates it into Meshery UI. By moving permission checks into Sistent's base components and checking them declaratively via props, we decouple Sistent from direct CASL dependency and eliminate hardcoded sessionStorage lookups from within Sistent.


Changes Made

Sistent Library (/sistent)
  1. PermissionProvider (src/custom/PermissionProvider.tsx)
    • Added a new CASL-agnostic context/hook wrapper. It accepts a generic userHasPermission: (key: Key) => boolean callback and optional userContext information.
  2. PermissionShield (src/custom/permissions.tsx)
    • Removed direct dependency on sessionStorage (e.g., sessionStorage.getItem('currentOrg')).
    • Now reads userName, orgName, and roleNames directly from PermissionProvider's userContext.
  3. Base Components (Button, IconButton, MenuItem, ListItem, ListItemButton)
    • Updated components to accept permissionKey (from @meshery/schemas) and permissionAction: 'showShield' | 'hide'.
    • The components automatically evaluate permissions via the provider hook and apply the appropriate action if the user lacks the permission (e.g., automatically rendering the PermissionShield tooltip overlay).
Meshery UI (/meshery/ui)
  1. _app.tsx
    • Mounted the PermissionProvider at the root, passing down a CASL adapter (ability.can) and feeding userContext from the Redux store/queries.
  2. Navigator.tsx & navigatorComponents.tsx
    • Converted Navigator item configurations to pass the canonical Keys directly.
    • Removed custom CAN() imports and calls inside Navigator.tsx in favor of declarative permissionKey and permissionAction props on ListItemComponent.

Benefits

  • Decoupled Architecture: Sistent and its base components are now completely unaware of CASL. Transitioning away from CASL in the future will require changing only one function inside _app.tsx.
  • Cleaner Code: Eliminates redundant disabled={!CAN(...)} logic and wrapper elements on the caller's side.
  • No Storage Leakage: Removed direct dependencies on sessionStorage inside the UI library.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request integrates several base components (such as Button, IconButton, ListItem, ListItemButton, and MenuItem) with a new PermissionProvider to support customizable permission actions ('showShield', 'disable', or 'hide'). It also refactors PermissionShield to retrieve user, organization, and role context from the provider instead of sessionStorage. The review feedback suggests replacing unsafe type assertions (null as unknown as JSX.Element) with empty fragments (<></>) when hiding components, and conditionally rendering the "User" row in the PermissionShield tooltip to prevent empty rows when the username is undefined.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/base/Button/Button.tsx Outdated
Comment thread src/base/MenuItem/MenuItem.tsx Outdated
Comment thread src/custom/permissions.tsx Outdated

@banana-three-join banana-three-join left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  if (!permissionKey) {
    return <MuiListItem {...rest} ref={ref} />;
  }

  // User HAS permission → render normally
  if (hasPermission) {
    return <MuiListItem {...rest} ref={ref} />;
  }

These conditional evaluations are contradictory and should be avoided. A user without a permission key shouldn't have access to the same layouts and components as someone with a permission key. Instead, the components should be explicitly rendered in either a hidden, disabled or visible state.

On that note, I believe there isn't much that much of a difference between the disabled and show guard state so the disabled state should be removed.

Comment thread src/custom/PermissionProvider.tsx Outdated
Signed-off-by: Rishi Raj <rishiraj438gt@gmail.com>
@rishiraj38 rishiraj38 force-pushed the feat/permission-provider branch from 4e92c45 to 1908e4d Compare July 10, 2026 17:59
@rishiraj38

Copy link
Copy Markdown
Member Author
  if (!permissionKey) {
    return <MuiListItem {...rest} ref={ref} />;
  }

  // User HAS permission → render normally
  if (hasPermission) {
    return <MuiListItem {...rest} ref={ref} />;
  }

These conditional evaluations are contradictory and should be avoided. A user without a permission key shouldn't have access to the same layouts and components as someone with a permission key. Instead, the components should be explicitly rendered in either a hidden, disabled or visible state.

On that note, I believe there isn't much that much of a difference between the disabled and show guard state so the disabled state should be removed.

Good catch! Collapsed the two early returns into a single if (!permissionKey || hasPermission) guard and removed the disable action entirely; showShield already communicates why the action is restricted, so disable was just a worse version of it. PermissionAction is now just 'hide' | 'showShield'.

Comment thread src/base/Button/Button.tsx
Signed-off-by: Rishi Raj <rishiraj438gt@gmail.com>
@rishiraj38

Copy link
Copy Markdown
Member Author

@aabidsofi19 @banana-three-join, any more feedback on the PR, or are we good to merge?

@rishiraj38 rishiraj38 dismissed banana-three-join’s stale review July 13, 2026 15:00

Feedback incorporated.

@rishiraj38 rishiraj38 merged commit f170b53 into layer5io:master Jul 13, 2026
5 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants