Skip to content

Breaking: Add generic _access mechanism (fixes #98) - #108

Merged
taylortom merged 3 commits into
masterfrom
issue/98
Jul 2, 2026
Merged

Breaking: Add generic _access mechanism (fixes #98)#108
taylortom merged 3 commits into
masterfrom
issue/98

Conversation

@taylortom

@taylortom taylortom commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Fixes #98

New

  • enableAccessControl() on AbstractApiModule — opt-in to a shared, extensible _access object. Extends the module schema with _access.public and registers the base public grant on both access hooks: accessCheckHook (per-item, single-document reads) and accessQueryHook (query-level, keeps pagination accurate).
  • schema/access.schema.json$merge extension adding _access.public (mirrors the authored.schema.json pattern). Auto-registered by jsonschema; resolved via extendSchema(schemaName, 'access').
  • lib/utils/isPublicAccess.js — pure predicate (resource._access?.public === true).
  • lib/utils/addAccessClause.js — OR-merges an access clause into a mongo query, mutating in place. Repeated calls accumulate grants into one shared $or group (additive), AND-combined with any pre-existing user-driven $or (e.g. search), which is lifted into $and. Lets multiple query-level observers compose safely.
  • Both utils re-exported from lib/utils.js and index.js for consuming modules.

Breaking

  • accessCheckHook observers are now additive access grants, OR-combined across observers (previously AND-combined via .every(Boolean) → now .some(Boolean)). Any one observer granting access is sufficient — required for the additive _access model where api grants public, authored grants createdBy, etc.
  • Returning false now abstains (no grant) rather than denying; a restriction must veto by throwing. Hook JSDoc updated accordingly.
  • In-repo observers are unaffected (roles vetoes by throw; adaptframework is a single observer). External consumers relying on return-false-to-deny must switch to throwing.
  • _access.public defaults to true (public-by-default for all content types). Resources are public unless a grant or the creating UI sets it otherwise — preserves open access for resource types without a sharing UI; clients that scope access (e.g. the course wizard) set it explicitly. Note for the backfill: the migration must write explicit values from the legacy fields (_isShared:false → _access.public:false) and must not rely on this default, or existing private content would be exposed on cutover.

Testing

  • New table-driven specs: tests/utils-isPublicAccess.spec.js, tests/utils-addAccessClause.spec.js (14 cases).
  • npx standard clean; full suite passes (77/77).

This is the expand step. Design decisions (incl. the public-by-default flip, REST-only enforcement boundary, and custom-widget-not-oneOf UI approach) are logged in a comment on #98.

Dependent work (now tracked):

Sequence switch→contract so legacy fields stay readable until all UIs write _access.*.

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.
@taylortom
taylortom merged commit e23c759 into master Jul 2, 2026
2 checks passed
@taylortom
taylortom deleted the issue/98 branch July 2, 2026 19:40
github-actions Bot pushed a commit that referenced this pull request Jul 2, 2026
# [4.0.0](v3.10.0...v4.0.0) (2026-07-02)

### Breaking

* Add generic _access mechanism (fixes #98) (#108) ([e23c759](e23c759)), closes [#98](#98) [#108](#108)
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 4.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New: Add generic _access mechanism to AbstractApiModule

1 participant