You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds an extensible `_access` object that any API module can opt into via
`enableAccessControl()`, replacing per-module hardcoded sharing. It extends
the module schema with `_access.public` and registers the base `public`
grant on both accessCheckHook (per-item, single-document reads) and
accessQueryHook (query-level, keeps pagination accurate). Ships the
`isPublicAccess` predicate and `addAccessClause` query helper (both
re-exported) and the `access` schema extension. Other modules extend
`_access` with their own keys and tap both hooks with additive grants.
accessCheckHook observers are now additive access grants, OR-combined
across observers (previously AND-combined). Returning false now abstains
rather than denies; a restriction must veto by throwing. Existing
in-repo observers are unaffected (roles vetoes by throw, adaptframework
is a single observer), but external consumers relying on
return-false-to-deny must switch to throwing.
Copy file name to clipboardExpand all lines: docs/writing-an-api.md
+23-7Lines changed: 23 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -341,7 +341,9 @@ See the table below for a list of hooks provided by the `AbstractApiModule` clas
341
341
|`postUpdateHook`| After updating a document | No |
342
342
|`preDeleteHook`| Before deleting a document | No |
343
343
|`postDeleteHook`| After deleting a document | No |
344
-
|`accessCheckHook`| When checking access to a resource | No |
344
+
|`accessCheckHook`| Per-item access check (single-document reads) | No |
345
+
|`accessQueryHook`| Merges access-control clauses into a list query (skipped for super users) | No |
346
+
|`queryHook`| Merges user-driven filter clauses into a list query (runs for all users) | Yes |
345
347
346
348
### Using hooks
347
349
@@ -374,17 +376,31 @@ class NotesModule extends AbstractApiModule {
374
376
}
375
377
```
376
378
377
-
### Access control with accessCheckHook
379
+
### Access control
378
380
379
-
Use `accessCheckHook` to implement custom access control:
381
+
Access is an **additive grant model**: observers widen access, they don't restrict it. Both access hooks are OR-combined across all observers, so any one observer granting access is sufficient.
382
+
383
+
-`accessQueryHook` — the primary gate. Merge a clause into `req.apiData.query` so the database only returns documents the user can see. Filtering here (rather than after the query) keeps pagination counts and the `Link` header accurate. Skipped for super users.
384
+
-`accessCheckHook` — the per-item safety net for single-document reads. Return `true` to grant, a non-truthy value to abstain, or `throw` to hard-veto the item (a veto denies regardless of other grants — this is how a restriction is expressed).
Call `enableAccessControl()` in your module's `init()` to opt into a shared, extensible `_access` object. This extends the module schema with `_access.public` and registers a `public` grant on both hooks:
380
394
381
395
```javascript
382
-
this.accessCheckHook.tap(async(req, doc) => {
383
-
// Return true to allow access, false or undefined to deny
Other modules extend `_access` with their own keys (e.g. `_access.users`, `_access.groups`) and tap both hooks with additional grants, all OR-combined with the base `public` grant. Use `addAccessClause` (exported from `adapt-authoring-api`) for the query-level grant so observers compose safely with each other and with any user-driven `$or`.
403
+
388
404
## Overriding methods
389
405
390
406
You can override database methods to customise behaviour:
0 commit comments