Problem/Motivation
A recurring request is to run Canvas Override without the Canvas patch (issue #3567225, which un-finals Drupal\canvas\Storage\ComponentTreeLoader). This issue records the outcome of a thorough investigation and ships the one safe improvement that came out of it.
Finding: a fully working per-content editor without the patch is not achievable from the module side. ComponentTreeLoader is a final class and six Canvas consumers type-hint the concrete class in their constructors (ClientDataToEntityConverter, ComponentTreeInputExtractor, ComponentTreeEditAccessCheck, ComponentInstanceForm, ApiAutoSaveController, ApiLayoutController). By PHP's type system, any class that changes the loader's behaviour fails those hints (TypeError on Canvas's own hot path), and any class that passes them cannot change behaviour. Registering a non-subclass under the loader's service id compiles but then TypeErrors at the first Canvas route. Two alternatives were evaluated and rejected: a backing canvas_page per node (tried, verified, and reverted in #3620603 — parallel storage, one-way sync, GET-side-effect creation) and forking Canvas's @internal controllers (~1.5k lines including the site-wide publish endpoint, a resync treadmill against an API with no stability guarantee). The durable fix is upstream: land #3567225, and ideally extract a ComponentTreeLoaderInterface and re-hint the six consumers.
Bug this issue fixes: on unpatched Canvas, Canvas Override already disables the per-content feature (the content type checkbox is greyed out with an explanation). But a bundle can still carry the enabled flag from a config import made on a patched site, and its Canvas / Canvas editor links still resolve. Canvas's ComponentTreeEditAccessCheck (behind _canvas_component_tree_edit_access on the editor and canvas.api.* routes) calls ComponentTreeLoader::load(), which throws \LogicException for any node bundle on unpatched Canvas. An uncaught exception in an access check is an HTTP 500 on every such request.
Steps to reproduce
- Install Drupal CMS 2.1 (Drupal 11.4, unpatched Canvas 1.10.x) + Canvas Override.
- Give a node bundle the
canvas_override.enabledthird-party setting and afield_canvas_layoutfield (as a config import from a patched site would). - As an administrator, request
/canvas/api/v0/layout/node/{nid}(or open the Canvas editor). Result: HTTP 500, uncaughtLogicException: For now Canvas only works if the entity is a canvas_page!
Proposed resolution
Retarget Canvas's ComponentTreeEditAccessCheck service — it is consumed only through the access_check tag, so nothing type-hints the concrete class — to a module check that composes Canvas's final check (its constructor is public) and converts the \LogicException into a cacheable AccessResult::forbidden() with an explanation. ~40 module lines, zero forked Canvas code. Behaviour is byte-identical for canvas_page and for any entity Canvas supports (on patched sites the injected loader is already the module subclass); only the unsupported-entity 500 becomes a clean 403. Verified on fresh Drupal CMS 2.1 (Drupal 11.4.6, unpatched Canvas): upstream check throws (500); the module check returns FORBIDDEN with the message and the API returns 403.
Remaining tasks
- ✅ File an issue about this project
- ✅ Addition/Change/Update/Fix to this project
- ✅ Testing to ensure no regression
- ✅ Automated unit/functional testing coverage
- ➖ Developer Documentation support on feature change/addition
- ➖ User Guide Documentation support on feature change/addition
- ➖ UX/UI designer responsibilities
- ➖ Accessibility and Readability
- ✅ Reviewed by a human
- ✅ Code review by maintainers
- ✅ Full testing and approval
- ✅ Credit contributors
- ✅ Review with the product owner
- ✅ Update Release Notes
- ✅ Release canvas_override-1.0.0
User interface changes
- N/A
API changes
- On unpatched Canvas, the Canvas editor and canvas.api.* routes return 403 (was 500) for entities Canvas cannot edit.
Data model changes
- N/A
Release notes snippet
- Canvas Override now fails safely with a 403 (instead of a 500) when the Canvas editor or API is reached for an entity Canvas cannot edit on this site, e.g. a node bundle enabled via config import on an unpatched Canvas.
Issue fork canvas_override-3621557
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3621557-prop-link-node
changes, plain diff MR !29
- 3621557-reset-csrf-token
changes, plain diff MR !30
- 3621557-host-entity-prop-save
changes, plain diff MR !28
- 3621557-option2-class-replacement
changes, plain diff MR !27
- 3621557-graceful-403-unpatched
changes, plain diff MR !26
- 3621557-fix-fail-safely
compare
Comments
Comment #4
rajab natshahComment #6
rajab natshahComment #10
rajab natshah