3.0 KiB
<PermissionGate> — bitmask permission gate
(no submodules)
Purpose
<PermissionGate> is a declarative conditional renderer that consumes the Wave 1 usePermission() hook and decides whether to render its children based on the current user's bitwise permission set. It is the primary tool for hiding UI surfaces (admin links, destructive buttons, advanced settings panels) from users who lack the required permission bits.
The component is intentionally tiny — every interesting policy decision is delegated to usePermission(), which in turn reads useAuth().user.roles and performs the bitwise AND against the configured permission constants from Permissions. Two semantics are supported: any-of (the default, useful for "show this if any one of these roles applies") and all-of (requireAll, useful for compound predicates such as "must have both moderator and admin").
Features
- Any-of semantics by default; all-of via
requireAll. - Accepts named
Permissionkeys ("USER_READ","ADMIN_WRITE", ...) or raw numeric bitmasks. - Fallback subtree (default
null) rendered when the check fails. - Unauthenticated users always fail the check —
usePermission()returnsfalsewhenuser === null. - Zero runtime cost beyond a single context read + bitwise AND.
Usage: Basic
import { PermissionGate } from "@suaveplan/react-auth";
export function AdminLink() {
return (
<PermissionGate permissions={["ADMIN_READ"]}>
<a href="/admin">Admin Console</a>
</PermissionGate>
);
}
Usage: Advanced
import { PermissionGate, Permissions } from "@suaveplan/react-auth";
export function ModeratorPanel() {
return (
<PermissionGate
permissions={[
Permissions.MODERATE_USERS,
Permissions.MODERATE_CONTENT,
]}
requireAll
fallback={<p>You do not have moderator access.</p>}
>
<ModeratorTools />
</PermissionGate>
);
}
API Reference
PermissionGateProps
| Field | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
— | Subtree rendered when the permission check passes. |
fallback |
ReactNode |
null |
Subtree rendered when the permission check fails. |
permissions |
ReadonlyArray<Permission | number> |
[] |
Permission keys or raw numeric bitmasks. |
requireAll |
boolean |
false |
When true, every entry must match (all-of). |
Implementation Notes
- Empty
permissionsarray combined with defaultrequireAll={false}denies (because[].some(...) === false). This matches the upstream contract; passrequireAll={true}to allow on empty input. - The gate does NOT throw when no
<AuthProvider>is mounted —usePermission()does, surfacing the misuse at the call site rather than silently rendering the fallback. - For route-level guarding, prefer
<AuthGuard>(which redirects);<PermissionGate>is for in-page subtree hiding.