| 1 |
import React from "react"; |
| 2 |
import { useCanCap } from "../../hooks/useCapabilities"; |
| 3 |
|
| 4 |
/** |
| 5 |
* Render-gate component. Hides children when the current user lacks |
| 6 |
* the capability. Used as the UI mirror of REST `permission_callback` |
| 7 |
* checks so the operator doesn't see buttons the API would 403. |
| 8 |
* |
| 9 |
* IMPORTANT — this is UX, not security. |
| 10 |
* The actual access boundary is the server's permission_callback. |
| 11 |
* <Can> just hides the control so the operator doesn't click and |
| 12 |
* get a confusing 403. NEVER assume <Can> hiding a button is |
| 13 |
* sufficient protection — the API must always re-check. |
| 14 |
* |
| 15 |
* Usage: |
| 16 |
* |
| 17 |
* <Can cap="yatra_refund_bookings"> |
| 18 |
* <Button onClick={...}>Refund</Button> |
| 19 |
* </Can> |
| 20 |
* |
| 21 |
* <Can cap="yatra_view_audit_log" fallback={<UpgradeNotice/>}> |
| 22 |
* <AuditTab/> |
| 23 |
* </Can> |
| 24 |
* |
| 25 |
* @since 3.5.0 |
| 26 |
*/ |
| 27 |
export interface CanProps { |
| 28 |
/** The Yatra capability the current user must have. */ |
| 29 |
cap: string; |
| 30 |
/** Children to render when allowed. */ |
| 31 |
children: React.ReactNode; |
| 32 |
/** Optional element to render when DENIED. Default: null (collapse). */ |
| 33 |
fallback?: React.ReactNode; |
| 34 |
} |
| 35 |
|
| 36 |
export const Can: React.FC<CanProps> = ({ cap, children, fallback = null }) => { |
| 37 |
const allowed = useCanCap(cap); |
| 38 |
return <>{allowed ? children : fallback}</>; |
| 39 |
}; |
| 40 |
|