Restrictions, Validation & Permissions 

What an editor is allowed to place into a given cell of a Grid Element, or into a given column of a page, is decided by four separate layers. They are easy to conflate because they operate on the same underlying configuration, but they run at different times, for different reasons, and a bypass at one layer does not imply a bypass at another.

Structural restrictions 

Each cell of a grid layout (page-level Backend Layout or Grid Element layout) can carry allowed, disallowed and maxitems configuration, defined in the layout's TSconfig (see the Grid TS Syntax reference). allowed/disallowed apply by default to CType, list_type and tx_gridelements_backend_layout. Server-side validation also automatically includes any further field mentioned by a column's own allowed or disallowed configuration, so project-specific fields can be protected without changing the restriction format. maxitems caps how many elements a cell accepts.

The column restrictions are used both to filter the normal authoring UI and to validate persisted changes server side. top_level_layout is a separate layout-level nesting restriction whose enforcement path differs, as described below.

This configuration is the shared input to both layers below: what gets offered to an editor, and what actually gets accepted.

Authoring-time filtering (UI layer) 

Several components filter what an editor sees, based on the restrictions above:

  • Grid Element layout options offered in the New Content Element Wizard are filtered through LayoutSetup::getLayoutWizardItems().
  • ModifyNewContentElementWizardItemsListener, a PSR-14 listener on Core's ModifyNewContentElementWizardItemsEvent, filters the wizard's full item list of content element types and plugins, resolving the target column's restrictions either from the page's own backend layout or from the target grid container's layout, depending on where the wizard was opened.
  • The corresponding FormEngine select fields (colPos, CType, list_type) use itemsProcFunc implementations that apply the same filtering to their item lists.

This layer determines what is convenient to pick, not what is permitted. The listener above reads its restriction data (allowed/disallowed) directly from request query parameters, which means any authenticated backend user can construct a request that offers different values than the wizard would. UI filtering alone would not be a security boundary.

Server-side enforcement 

The same restrictions are enforced again, server side, independent of what the UI offered. Classes/Hooks/DataHandler.php implements processDatamap_beforeStart() and processCmdmap_beforeStart(), backed by Classes/Helper/RestrictionGuard.php:

  • processDatamap_beforeStart() checks normal tt_content datamap saves and resolves the effective target column, either the container's own layout and tx_gridelements_columns, or the target page's Backend Layout and colPos. It rejects the save if any restricted field's value is disallowed, or if the column's maxitems would be exceeded.
  • processCmdmap_beforeStart() runs the equivalent check for copy and move commands (drag-and-drop, cut/paste, paste), resolving the same restrictions for the destination the command targets.
  • top_level_layout is handled separately for copy and move operations that would place an existing Grid Element inside another container. It is not part of the generic allowed/disallowed/maxitems field-validation loop.

maxitems enforcement counts existing siblings in the exact target scope (container and column, or page and column, per language) and also accounts for other records being saved in the same request, so several new elements created together cannot collectively exceed the limit even though none of them exists in the database yet.

A rejected save or command is not partially applied: the offending entry is removed from the datamap or cmdmap before TYPO3 processes it, and a flash message explains why. This makes allowed/disallowed/maxitems a real constraint on what ends up stored, not merely a convenience for what the wizard suggests. This document makes no claim about enforcement behavior in other maintained branches.

Permissions and auth mode 

The layers above decide what is allowed in a particular cell. A separate, TYPO3 Core mechanism decides whether a given backend user may use a particular CType at all: explicit-allow/deny auth mode, checked via BackendUserAuthentication::checkAuthMode() and configured per backend user or group, the same mechanism Core uses for any other restricted field value.

Grid Elements gates two of its own features behind this check rather than inventing a separate permission system:

  • ModifyNewContentElementWizardItemsListener only runs at all if the current user's permissions allow the gridelements_pi1 CType. A user without that permission does not see the Grid Elements branch of the wizard.
  • The "Paste as Reference" context menu action only renders if the user's permissions allow the shortcut CType (ItemProvider::canRender()), since creating a reference means creating a shortcut record.

Summary 

Layer Decides Enforced by
Structural restrictions What a layout's top_level_layout setting and a column's allowed/disallowed/maxitems configuration say Layout TSconfig, typically authored through the Grid Wizard, the shared input to both layers below
Authoring-time filtering What is offered to an editor Wizard item listener, itemsProcFunc implementations
Server-side enforcement What is actually accepted and stored DataHandler beforeStart hooks, RestrictionGuard
Permissions / auth mode Whether a user may use a given CType at all TYPO3 Core checkAuthMode()