first commit
This commit is contained in:
62
docs/ui/react/react-auth/src/hooks/use-permission.md
Normal file
62
docs/ui/react/react-auth/src/hooks/use-permission.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# `use-permission`
|
||||
|
||||
## Purpose
|
||||
|
||||
`usePermission()` exposes a bitwise permission-check API over the current `user.roles` bitmask. The package ships a closed registry of 16 named permission flags (`Permissions` enum) covering user / post / admin / system / moderation / settings axes. The hook accepts either a `Permission` string key (for ergonomics in JSX) or a raw numeric bit (for composition), tests `(user.roles & bit) === bit` for each query, and returns helpers for the three common patterns: single flag, any-of, all-of. With no authenticated user every predicate returns `false`, mirroring the strictest safe default. `getPermissionNames()` projects the bitmask onto the human-readable flag names so consumers can render checklists without re-implementing the mapping.
|
||||
|
||||
## Features
|
||||
|
||||
- 16-flag closed `Permissions` enum keyed by name with bit values.
|
||||
- Accepts string keys or numeric bits at every call site.
|
||||
- `hasPermission`, `hasAnyPermission`, `hasAllPermissions`, `getPermissionNames`, `userRoles` fields.
|
||||
- Unauthenticated users get safe-default `false` / `[]` returns.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```tsx
|
||||
import { usePermission } from "@suaveplan/react-auth";
|
||||
|
||||
function DeleteButton() {
|
||||
const { hasPermission } = usePermission();
|
||||
if (!hasPermission("POST_DELETE")) return null;
|
||||
return <button type="button">Delete</button>;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Compose checks against numeric bits and named flags together; render the user's effective permission list:
|
||||
|
||||
```tsx
|
||||
import { Permissions, usePermission } from "@suaveplan/react-auth";
|
||||
|
||||
function AuditBadge() {
|
||||
const { hasAllPermissions, getPermissionNames } = usePermission();
|
||||
const moderator = hasAllPermissions([
|
||||
Permissions.MODERATE_USERS,
|
||||
Permissions.MODERATE_CONTENT,
|
||||
1 << 6, // ADMIN_READ — same bit, asserted by number
|
||||
]);
|
||||
return (
|
||||
<details>
|
||||
<summary>{moderator ? "Moderator" : "Member"}</summary>
|
||||
<ul>
|
||||
{getPermissionNames().map((name) => (
|
||||
<li key={name}>{name}</li>
|
||||
))}
|
||||
</ul>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `const Permissions` — closed map of `{ NAME: bit }` for 16 flags.
|
||||
- `type Permission = keyof typeof Permissions`.
|
||||
- `interface UsePermissionResult` — `{ hasPermission(p): boolean; hasAnyPermission(ps): boolean; hasAllPermissions(ps): boolean; getPermissionNames(): string[]; userRoles: number }`.
|
||||
- `function usePermission(): UsePermissionResult`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The `Permissions` map is `as const` so each key narrows to its literal numeric bit. The hook reads `user` from `useAuth()`, which means it shares the same context-rebind semantics as the rest of the auth surface — a `signIn` that changes `user.roles` propagates to every consumer on the next render without manual re-subscription. `getPermissionNames` iterates `Object.entries(Permissions)` and is intentionally O(n) in flag count (16) — short and constant. `userRoles` is exposed as a fallback `0` when unauthenticated, so callers performing custom bit checks do not need a separate `user === null` guard.
|
||||
Reference in New Issue
Block a user