Resources, Attributes & Filtering
A resource is a uniquely named thing being accessed — a document, a DB record, a file, a relationship. Whether something is a distinct resource is a design decision.
ac.grant('user') .createAny('account') .updateOwn('account', ['*', '!password', '!email']) .updateOwn('credentials');A resource is defined the first time you grant/deny on it (or declared up front
with setup()).
ac.hasResource('banana'); // falseac.grant('monkey').createOwn('banana'); // defined nowac.hasResource('banana'); // trueac.getResources(); // ['account', 'credentials', 'banana']Attributes (Glob Notation)
Section titled “Attributes (Glob Notation)”Each grant scopes access to a set of attributes using
glob notation: * (all), ! (negate),
and nested dotted paths.
ac.grant('user').readOwn('account', [ '*', // all attributes… '!password', // …except password 'profile.*' // (nested paths are supported)]);Omitting attributes defaults to ['*'] for a grant. An explicit empty array
[] is preserved — a grant with [] (or a deny with omitted attributes)
allows no attributes, so granted is false.
Filtering Data
Section titled “Filtering Data”filter() returns a deep copy of a record (or array of records) containing
only the allowed attributes — handy for shaping API responses.
ac.grant('user').readOwn('account', ['*', '!password', 'profile.*']);
const perm = ac.can('user').readOwn('account');perm.attributes; // ['*', '!password', 'profile.*']perm.filter(accountRecord); // a copy without `password`Filtering an array maps over each element:
const visible = ac.can('user').readAny('account').filter(accounts);Categories
Section titled “Categories”Related resources can share a category with / (e.g. media/photo,
media/video), enabling category‑wide grants and gates without name collisions
(media/photo and legal/photo are distinct). See
Groups & Categories.