Check Permissions in Admin Customizations

EnterpriseBeta

In this guide, you'll learn how to show or hide content in your admin customizations based on the logged-in admin user's permissions and roles.

Permission Utilities Overview#

In your admin customizations, such as widgets and UI routes, you can use the following utilities to check the admin user's permissions and roles:

  • PermissionGuard: A component that renders its children only if the admin user has the specified permissions.
  • RoleGuard: A component that renders its children only if the admin user has the specified roles.
  • usePermissions: A hook that returns functions to check the admin user's permissions and roles.

A permission is a string of the format resource:operation, such as customer:create. It matches the policies of the admin user's roles, including wildcard policies.

When the RBAC Module isn't installed, these utilities allow all permissions and roles.

Tip: These utilities only change what the Medusa Admin dashboard displays. The Medusa backend still checks the admin user's permissions when the dashboard sends requests to API routes. Learn how to guard your custom API routes in the Protect API Routes guide.

PermissionGuard Component#

The PermissionGuard component renders its children only if the admin user has the specified permissions.

For example, to show a button only to admin users who can create customers:

src/admin/widgets/customer-actions.tsx
import { defineWidgetConfig } from "@medusajs/admin-sdk"
import { Button, Container } from "@medusajs/ui"
import { PermissionGuard } from "@medusajs/dashboard/hooks"

const CustomerActionsWidget = () => {
  return (
    <Container>
      <PermissionGuard resource="customer" operation="create">
        <Button>Create Customer</Button>
      </PermissionGuard>
    </Container>
  )
}

export const config = defineWidgetConfig({
  zone: "customer.list.before",
})

export default CustomerActionsWidget

The PermissionGuard component accepts the following props:

Loading...

For example, to require multiple permissions and show a message if the admin user doesn't have them:

Code
<PermissionGuard
  permissions={["customer:read", "order:read"]}
  requireAll
  fallback={<Text>You can't view customer orders.</Text>}
>
  <CustomerOrders />
</PermissionGuard>

RoleGuard Component#

The RoleGuard component renders its children only if the admin user has the specified roles, by their names. It's useful when checking a role is more practical than listing its permissions.

For example:

Code
import { RoleGuard } from "@medusajs/dashboard/hooks"

// ...

<RoleGuard role="Billing">
  <BillingSection />
</RoleGuard>

By default, an admin user has a role if their permissions cover all the policies of that role, even if the role isn't assigned to them. For example, a super admin passes every role check. To require that the role is assigned to the admin user, set the match prop to assigned:

Code
<RoleGuard role="Auditor" match="assigned">
  <AuditLogExport />
</RoleGuard>

The RoleGuard component accepts the following props:

Loading...
Warning: RoleGuard matches roles by their names. If you rename a role, update the guards that reference its old name.

usePermissions Hook#

The usePermissions hook returns functions to check the admin user's permissions and roles in your component's logic.

For example:

src/admin/widgets/customer-delete.tsx
import { defineWidgetConfig } from "@medusajs/admin-sdk"
import { Button, Container } from "@medusajs/ui"
import { usePermissions } from "@medusajs/dashboard/hooks"

const CustomerDeleteWidget = () => {
  const {
    can,
    isLoading,
  } = usePermissions()

  if (isLoading) {
    return null
  }

  if (!can("customer", "delete")) {
    return null
  }

  return (
    <Container>
      <Button variant="danger">Delete Customers</Button>
    </Container>
  )
}

export const config = defineWidgetConfig({
  zone: "customer.list.before",
})

export default CustomerDeleteWidget

The hook returns an object with the following properties:

Loading...
Was this page helpful?
Ask Bloom
For assistance in your development, use Claude Code Plugins or Docs MCP server in Cursor, VSCode, etc...FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break
⇧↵