Conversation
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.
|
🎉 This PR is included in version 4.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #98
New
enableAccessControl()onAbstractApiModule— opt-in to a shared, extensible_accessobject. Extends the module schema with_access.publicand registers the basepublicgrant on both access hooks:accessCheckHook(per-item, single-document reads) andaccessQueryHook(query-level, keeps pagination accurate).schema/access.schema.json—$mergeextension adding_access.public(mirrors theauthored.schema.jsonpattern). Auto-registered byjsonschema; resolved viaextendSchema(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$orgroup (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.lib/utils.jsandindex.jsfor consuming modules.Breaking
accessCheckHookobservers 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_accessmodel where api grantspublic, authored grantscreatedBy, etc.falsenow abstains (no grant) rather than denying; a restriction must veto by throwing. Hook JSDoc updated accordingly.throw; adaptframework is a single observer). External consumers relying on return-false-to-deny must switch to throwing._access.publicdefaults totrue(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
tests/utils-isPublicAccess.spec.js,tests/utils-addAccessClause.spec.js(14 cases).npx standardclean; 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-
oneOfUI approach) are logged in a comment on #98.Dependent work (now tracked):
createdBy), New: Extend _access with users key adapt-authoring-users#46 (_access.users), New: Extend _access with groups key adapt-authoring-usergroups#14 (_access.groups, removes the restrictive filter).checkContentAccess+applyContentAccessFilter).Sequence switch→contract so legacy fields stay readable until all UIs write
_access.*.