Skip to Content
React AuthorizationOverview

@evanion/react-acl

@evanion/react-acl 0.1.0 and its patch releases up to 0.1.2, the version on npm. Values on this page were produced by running the source at f9b1d93, a later commit than the 0.1.0 tag, and are not re-executed.

An Edit button nested deep in a React tree needs your permission rules, the signed-in user and the current time to know whether to render. @evanion/react-acl holds all three above the tree, so no component in between passes them down.

How react-acl reaches a nested button

@evanion/react-acl is the React binding of @evanion/acl, the package that holds your permission rules and answers whether someone may do something. react-acl evaluates nothing itself, and @evanion/acl answers every question. Its PolicyProvider takes the rules, the signed-in user and the current time once, and hands them to every component under it through React context, React’s channel for passing a value down a tree without props:

One PolicyProvider holds the rules, the signed-in user and the current time. ShopPage, ListingView and ActionBar pass none of the three, and EditControl reads all three through React context when it calls useCan.

Baize, a board game shop, draws its Edit button three components below the provider. The button asks useCan one question and names only what it asks about:

'use client'; import { } from '@evanion/react-acl'; type = { : string; : string; : 'draft' | 'published' }; export function ({ }: { : }) { const = ('listing', 'edit', ); if (!.) return null; return < ="button">Edit listing</>; }

EditControl passes 'listing', the kind of record it asks about, the action 'edit' and the listing itself. It renders the button only when decision.allowed is true. 'use client' marks the file as a client component in a React Server Components app such as Next.js, and hooks run only in client components. Other React apps ignore the line.

The current time is there because some rules hold only inside a time window, such as a discount that ends at 18:00. One provider gives the whole screen one time, so two components cannot read times either side of 18:00 and answer two ways on one screen.

The react-acl vocabulary

Every react-acl page uses the terms below. They come from @evanion/acl, and react-acl uses them unchanged.

  • The matrix is your rules as one JSON document. Your server builds it with @evanion/acl and sends it to the browser with the page.
  • An evaluator answers questions from one matrix. hydratePolicy from @evanion/acl builds one from the JSON. These pages always call it access.
  • A subject is who is acting: the signed-in shopper, as a plain object your server resolved.
  • The instant is the time every time window in the rules is read against.
  • An object kind names a kind of record the rules cover, such as 'listing'. A row is one record of that kind, such as one listing.
  • A decision is what an evaluator returns for one question. allowed is the answer, and reason says why.

What react-acl can do

Each react-acl hook calls the @evanion/acl method beside it, with the subject and the instant the provider holds, and returns what that method returns.

The screen asksThe hookThe method it calls
May this shopper take this action on this row?useCanaccess.can
May they take it on each row of this list?useCanManyaccess.canMany
Which inputs of this form may they see, or set?useCanFieldsaccess.canFields
What may they reach at all, for a menu?useCapabilitiesaccess.capabilities

createPolicyContext takes a policy built with policy(), @evanion/acl’s builder for rules written in TypeScript, and returns the same provider and hooks typed by it, so a misspelt object kind or action fails to compile.

When react-acl is the wrong tool

react-acl has no part in two places:

  • Server code, such as a server component, a React Router loader or a Next.js Server Action. Each runs on the server and calls access.can from @evanion/acl directly.
  • One component asking one question. access.can with the subject as its first argument returns the same decision without a provider.

react-acl also enforces nothing. A hook only shows or hides controls, and a hidden Edit button is still a URL the shopper can post to, so the server asks access.can again before it writes.

Mount react-acl under your server’s matrix

You now know where the react-acl provider sits and what each hook asks. On Getting started you install react-acl, hand it your server’s matrix and see the Edit button render for the seller who listed the game.

Last updated on