import { ExclamationCircle } from "@medusajs/icons"
import { Container, Heading, Text } from "@medusajs/ui"
import { useMemo } from "react"
import { useTranslation } from "react-i18next"
import { Navigate, Outlet, useMatches } from "react-router-dom"
import { type Permission } from "../../../lib/permissions"
import {
usePermissions,
useRegisterPermissions,
} from "../../../providers/permissions-provider"
type PermissionRouteHandle = {
/**
* The permissions required to access the route.
*/
permissions?: Permission | Permission[]
/**
* If true (default), the actor must hold ALL listed permissions.
* If false, holding ANY one is enough.
*/
requireAll?: boolean
/**
* Optional path to redirect to when access is denied. When omitted, the
* access-denied page is rendered in place.
*/
redirectTo?: string
}
type ResolvedRequirement = {
permissions: Permission[]
requireAll: boolean
redirectTo?: string
}
const readRequirementFromHandle = (
handle: unknown
): ResolvedRequirement | undefined => {
if (!handle || typeof handle !== "object") {
return undefined
}
const declared = handle as PermissionRouteHandle
const rawPermissions = declared.permissions
if (!rawPermissions) {
return undefined
}
const permissions = Array.isArray(rawPermissions)
? rawPermissions
: [rawPermissions]
if (!permissions.every((permission) => typeof permission === "string")) {
console.error(
"Invalid permissions: all permissions must be strings",
permissions
)
return undefined
}
if (!permissions.length) {
return undefined
}
return {
permissions,
requireAll: declared.requireAll ?? true,
redirectTo: declared.redirectTo,
}
}
/**
* Route-level permission guard. Mount it as the `element` of a route and
* declare the permission requirement in the route's `handle.permissions`.
*
* Example:
*
* ```tsx
* {
* path: "/customers/create",
* element: