v11->v14 upgrade: add Step 8c — non-admin editor permissions

After a v11->v14 upgrade, non-admin editors often can't edit content
(no edit icons) and/or the Media tab is missing, even though the group
has "edit content" and tables_modify includes tt_content. The upgrade
wizards do not convert the backend group access-lists. Document the fix
for all three facets on be_groups:

1. explicit_allowdeny: v<=11 ":ALLOW"-suffix format vs v12+ exact
   inList match (no suffix) — REPLACE strips it; blocks ALL editing.
2. CType allow-list missing renamed v14 names (wst3bootstrap_* -> t3bs_*,
   ws_slider, heroitem, news_*, address_*).
3. non_exclude_fields missing v14 fields -> hidden Media tab
   (e.g. hero tx_heroitem_bg*).

Includes the read-only recordEditAccessInternals/check/doesUserHaveAccess
CLI diagnosis and the db_mountpoints red-herring note. Bump to v1.1;
extend description + when-to-use for the symptom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-21 11:30:29 +02:00
parent 4ef2af5822
commit db6cc87c90
+47 -2
View File
@@ -1,9 +1,9 @@
---
name: typo3-v11-to-v14-ddev-upgrade
description: "Bring an existing TYPO3 v11 site up and booting on TYPO3 v14 LTS (v14.3) locally under DDEV, starting from a v11 SQL dump + the old sitepackage. Use when upgrading/migrating a TYPO3 v11 (or v12/13) project to v14 for local dev, when a v11 database dump must be made to boot on v14, or when a t3bootstrap-based v11 site needs its composer/config/schema/upgrade-wizards/site-sets brought to v14. Covers: composer.json rework to ^14 + private git repos & composer registry auth, config/system/settings.php, the v14 .htaccess, database:updateschema, backend admin, upgrade wizards (incl. confirmable + one-way ones), language packs, wiring t3bootstrap TypoScript via site sets, and the recurring v11->v14 traps. NOT for fresh installs and NOT for server deployment (see the konsoleH staging-deploy skill for that)."
description: "Bring an existing TYPO3 v11 site up and booting on TYPO3 v14 LTS (v14.3) locally under DDEV, starting from a v11 SQL dump + the old sitepackage. Use when upgrading/migrating a TYPO3 v11 (or v12/13) project to v14 for local dev, when a v11 database dump must be made to boot on v14, when a t3bootstrap-based v11 site needs its composer/config/schema/upgrade-wizards/site-sets brought to v14, or when after such an upgrade a non-admin editor can't edit content (no edit icons / missing Media tab). Covers: composer.json rework to ^14 + private git repos & composer registry auth, config/system/settings.php, the v14 .htaccess, database:updateschema, backend admin, upgrade wizards (incl. confirmable + one-way ones), language packs, wiring t3bootstrap TypoScript via site sets, fixing non-admin editor permissions (be_groups explicit_allowdeny :ALLOW-format conversion, v14 CType allow-list, non_exclude_fields), and the recurring v11->v14 traps. NOT for fresh installs and NOT for server deployment (see the konsoleH staging-deploy skill for that)."
metadata:
author: Wappler
version: "1.0"
version: "1.1"
---
# TYPO3 v11 → v14 upgrade (local, DDEV)
@@ -101,6 +101,51 @@ local DDEV is fine.
`ddev exec vendor/bin/typo3 language:update`. Composer mode ships **no** language packs → labels fall
back to English (e.g. news "more-link"). Run this whenever the site language isn't English.
## Step 8c — Non-admin editor permissions (⚠ the migration does NOT fix these)
Very confusing symptom: a **non-admin editor** (e.g. a "Redakteur" group) opens the Page module, **sees
the content but there are no edit icons**, and/or the **Media tab is missing** from the content form —
while the Access (Berechtigungen) module shows the group *has* "edit content" and `tables_modify` includes
`tt_content`. Cause: the v11→v14 upgrade wizards do **not** convert the backend group access-lists. Fix
three separate `be_groups` fields, per editor group (find it: `SELECT uid,title FROM be_groups WHERE
deleted=0`). Editors must **log out/in** afterwards.
1. **`explicit_allowdeny` format — THE big one (blocks ALL content editing).** v≤11 stored allowed values
as `tt_content:CType:text:ALLOW`; **v12+ dropped the suffix** and `BackendUserAuthentication::
checkAuthMode()` does an exact `GeneralUtility::inList()` against `tt_content:CType:text` (no suffix).
The migrated `:ALLOW` never matches → every CType (even plain Text/Header) is denied → no edit icons on
anything. Strip the suffix (all groups):
`UPDATE be_groups SET explicit_allowdeny = REPLACE(explicit_allowdeny, ':ALLOW', '') WHERE deleted=0`
(`:DENY` entries may stay — `…:value:DENY` never equals `…:value`, so the value correctly stays
non-allowed.) Verify: `FIND_IN_SET('tt_content:CType:text', explicit_allowdeny) > 0`.
2. **Missing v14 CType names in the allow-list.** The container migration renamed CTypes `wst3bootstrap_*`
→ `t3bs_*`; the allow-list only has the old names. Append the new names actually used — compare
`SELECT DISTINCT CType FROM tt_content` vs the list and add `tt_content:CType:<name>` (NO `:ALLOW`
suffix) for each missing one; typically `t3bs_fluidrow/_column/_tabs/_tab_item/_accordion/
_accordion_item/_megamenu`, `ws_slider`, `heroitem`, `news_*`, `address_*`.
3. **`non_exclude_fields` missing v14 fields → hidden tabs (e.g. Media).** TCA `exclude` fields are hidden
from non-admins unless granted here (format `table:field`, unchanged in v12). The v11 list lacks fields
ADDED in v14, so any tab whose fields are ALL exclude+denied won't render — e.g. the hero **Media** tab
contains only `tx_heroitem_bg`/`_bg_tablet`/`_bg_smartphone` (all denied → no tab). Grant the missing
`tt_content` exclude fields (append `tt_content:<field>` for each). Common culprits: `imagecols_grid,
effects, aos_*, bg_container, tx_wsslider_{renderer,layout,source}, tx_heroitem_*, tx_teaser2_layout`.
NOTE `image`/`assets`/`media` are NOT exclude fields (always shown) — the missing tab is the *settings*
fields, not the FAL field. Other record types editors touch (news, address) can be stale the same way.
**Diagnose precisely — read-only CLI bootstrap** (also the way to *confirm* a fix without a BE login):
```php
SystemEnvironmentBuilder::run(0, SystemEnvironmentBuilder::REQUESTTYPE_CLI | SystemEnvironmentBuilder::REQUESTTYPE_BE);
Bootstrap::init($classLoader);
$be = GeneralUtility::makeInstance(BackendUserAuthentication::class);
$be->user = BackendUtility::getRecord('be_users', <uid>); $be->fetchGroupData(); $GLOBALS['BE_USER'] = $be;
$be->recordEditAccessInternals('tt_content', $row, false, false, true); // false → $be->errorMsg names the failing gate
$be->check('non_exclude_fields', 'tt_content:<field>'); // tab/field visibility
$be->doesUserHaveAccess($pageRow, 16); // page "edit content" perm
```
`recordEditAccessInternals` failing with `authMode "explicitAllow" failed for field "CType"` == facet 1/2.
(Writing `be_groups` *from* such a script may be blocked by agent tooling — apply fixes as plain SQL
`UPDATE`/`REPLACE`/`CONCAT`.) Red herring: an empty `db_mountpoints` on the user is fine if the group (or a
subgroup) supplies a mount — check the user's *effective* `getWebmounts()` before chasing it.
## Step 9 — Wire TypoScript via site sets
v14 t3bootstrap delivers TypoScript (incl. the `PAGE` object) through **site sets**, not `sys_template`.
The site config must declare them under `dependencies:` in `config/sites/<SITE_ID>/config.yaml`, or the