Skip to content

Actions & Possession

An action is the kind of operation performed on a resource. The CRUD verbs are built in, and v3 lets you use any custom action name.

The named helpers are sugar for the four CRUD actions × two possessions:

ac.grant('user')
.createOwn('video') // create + own
.readAny('video') // read + any
.updateOwn('video') // update + own
.deleteAny('video'); // delete + any

A typical mapping (you decide what each means — a create might send an SMS, a delete might be a soft‑delete UPDATE):

AccessControlREST/HTTPDatabase
createPOSTINSERT
readGETSELECT
updatePUT / PATCHUPDATE
deleteDELETEDELETE

CRUD helpers are sugar over the generic .action() (and its alias .do()), which accept any action name. Possession travels with the :own / :any convention (omit ⇒ any).

// granting
ac.grant('editor')
.action('publish', 'article', ['*']); // publish (any)
ac.grant('author')
.action('publish:own', 'article', ['*']); // ownership-gated publish
// checking
ac.can('editor').do('publish', 'article').granted;
ac.can('author', { user, article })
.do('publish:own', 'article').granted;
ac.can('admin').do('update', 'post').granted; // CRUD via .do() too

getActions() lists the action names in the model. Pass a role (or roles) to scope it to what that role can do — including inherited actions:

ac.grant('user').readOwn('profile');
ac.grant('admin').extend('user').deleteAny('post').createAny('post');
ac.getActions(); // ['read', 'delete', 'create'] (all)
ac.getActions('user'); // ['read']
ac.getActions('admin'); // ['create', 'delete', 'read'] (own + inherited)

It throws if a given role doesn’t exist. (Companions: getRoles(), getResources().)

  • any — any record of the resource.
  • own — only records the requester owns.

Grants cascade from any to own: a blanket any grant also satisfies an own check (if you can act on any record, you can act on your own).

ac.grant('admin').updateAny('order', ['*']);
ac.can('admin').updateOwn('order').granted; // true (any ⊇ own)

own only means “owned” if you tell the engine how ownership is determined — see Ownership. With no resolver configured, own keeps its v2 behavior (it selects the attribute set; you enforce ownership).