Commit 70c47cb8 authored by Stuart Clark's avatar Stuart Clark 💻
Browse files

feat(#2777579): formatter permission handling

parent b6deb3c2
Loading
Loading
Loading
Loading
Loading
+14 −0
Changes for CHANGELOG.md: 14 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Changelog

## 4.2.1 (2026-10-21)

### Security

- Tightened access control for the formatter engines. See the security advisory
  for this release.

### Changes

- Added per-operation and per-engine permissions. `administer custom formatters`
  still grants full access and is now marked as a restricted permission. Below
  it, separate create, edit, delete and view permissions cover the low risk
  engines, and the PHP and Twig engines each need their own permission as well.

## 4.2.0 (2026-10-08)

### Changes
+5 −2
Changes for README.md: 5 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -101,13 +101,16 @@ Read the manual at:
    `file`, and `entity_reference` fields, allowing formatted output to be
    inserted directly into WYSIWYG editors. Activate by installing the Insert
    module alongside Custom Formatters; no additional configuration required.
- **Granular permissions** — `administer custom formatters` grants full
  access. Below that, formatters are gated by base `create`/`edit`/
  `delete`/`view` permissions, and the PHP and Twig engines each require an
  additional dedicated permission on top, since both can execute code or
  read data beyond the field being rendered.

## Roadmap

Planned features for future releases:

- **Granular permissions** — Per-engine permission gates, e.g. a separate
  permission to create PHP formatters.
- **Export** — Generate a standalone Drupal module from a custom formatter.
- **Coder review integration** — Inline PHPCS review of PHP formatter code
  against Drupal coding standards directly in the formatter edit form.
+2 −2
Changes for custom_formatters.module: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -27,9 +27,9 @@ function custom_formatters_help(string $route_name, RouteMatchInterface $route_m
      $output .= '<dt>' . t('HTML + Tokens') . '</dt>';
      $output .= '<dd>' . t('A HTML-based editor with Token support. When the Token module is installed, a token tree browser is available for inserting tokens. Entity reference fields automatically provide tokens for the referenced entity.') . '</dd>';
      $output .= '<dt>' . t('PHP') . '</dt>';
      $output .= '<dd>' . t('A PHP-based editor with support for multiple fields and values. Note: this engine uses eval() and access is restricted to users with the "administer custom formatters" permission.') . '</dd>';
      $output .= '<dd>' . t('A PHP-based editor with support for multiple fields and values. Note: this engine uses eval(). Creating or editing a PHP formatter requires the "Create, Edit, or Delete PHP Custom Formatters" permission in addition to the base create/edit permission.') . '</dd>';
      $output .= '<dt>' . t('Twig') . '</dt>';
      $output .= '<dd>' . t('A Twig-based editor with support for multiple fields and values.') . '</dd>';
      $output .= '<dd>' . t('A Twig-based editor with support for multiple fields and values. Note: this engine can read data from entities beyond the field being rendered. Creating or editing a Twig formatter requires the "Create, Edit, or Delete Twig Custom Formatters" permission in addition to the base create/edit permission.') . '</dd>';
      $output .= '</dl>';

      return $output . ('<p>' . t('For more information, see the <a href=":handbook">Custom Formatters handbook page</a>.', [
+28 −0
Changes for custom_formatters.permissions.yml: 28 added lines, 0 removed lines.
Original line number Diff line number Diff line
administer custom formatters:
  title: 'Administer Custom Formatters'
  restrict access: true
  description: 'Full access to all formatters and engines, including PHP and Twig. Bypasses every other custom_formatters permission.'

create custom formatter:
  title: 'Create Custom Formatters'
  description: 'Create formatters using an engine that does not require its own extra permission (HTML+Token, Formatter Preset).'

edit custom formatters:
  title: 'Edit Custom Formatters'
  description: 'Edit existing formatters using an engine that does not require its own extra permission.'

delete custom formatters:
  title: 'Delete Custom Formatters'
  description: 'Delete existing formatters using an engine that does not require its own extra permission.'

view custom formatters:
  title: 'View Custom Formatters'
  description: 'View the formatter listing.'

create and edit php custom formatter:
  title: 'Create, Edit, or Delete PHP Custom Formatters'
  restrict access: true
  description: 'Required in addition to "Create Custom Formatters", "Edit Custom Formatters", or "Delete Custom Formatters". The PHP engine executes arbitrary code entered in the formatter.'

create and edit twig custom formatter:
  title: 'Create, Edit, or Delete Twig Custom Formatters'
  restrict access: true
  description: "Required in addition to \"Create Custom Formatters\", \"Edit Custom Formatters\", or \"Delete Custom Formatters\". This engine can read arbitrary object data, such as another user's password hash."
+3 −3
Changes for custom_formatters.routing.yml: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ custom_formatters.add_page:
    _title: 'Add formatter'
    _controller: '\Drupal\custom_formatters\Controller\CustomFormattersController::addList'
  requirements:
    _permission: 'administer custom formatters'
    _permission: 'create custom formatter+administer custom formatters'

custom_formatters.add:
  path: '/admin/structure/formatters/add/{formatter_type}'
@@ -12,7 +12,7 @@ custom_formatters.add:
    _title: 'Add formatter'
    _controller: '\Drupal\custom_formatters\Controller\CustomFormattersController::add'
  requirements:
    _permission: 'administer custom formatters'
    _entity_create_access: 'formatter:{formatter_type}'

custom_formatters.settings_form:
  path: '/admin/structure/formatters/settings'
@@ -28,7 +28,7 @@ entity.formatter.collection:
    _entity_list: 'formatter'
    _title: 'Formatters'
  requirements:
    _permission: 'administer custom formatters'
    _permission: 'view custom formatters+administer custom formatters'

entity.formatter.edit_form:
  path: '/admin/structure/formatters/manage/{formatter}'
Loading