Capabilities

This project is not covered by Drupal’s security advisory policy.

Capabilities lets people assign one meaningful thing instead of many raw permissions. A capability is a named, translatable bundle of access, such as "Publish articles" or "Manage members of this project", that modules declare and site builders can define in the user interface.

It works in two places, on top of the access policy API that Drupal core introduced in 10.3:

  • Site-wide. A capability can stand for the Drupal permissions one job needs. Instead of ticking ten checkboxes on the permissions page, you give a role or a user "Publish articles", and they get every permission that job needs.
  • Within a scope. A capability can apply to one thing only, such as "edit project 7". Your module decides who holds it, for example from a membership table, and Drupal's access system does the rest. No role per project, no access checks scattered through controllers.

Features

  • Capabilities declared by modules in MODULE.capabilities.yml, the same way as permissions.
  • Capabilities defined by site builders in the UI, stored as configuration and exported with the rest of the site.
  • Assignment to roles and directly to users.
  • implies: a capability can include others, so larger jobs build on smaller ones.
  • An overview page that answers "why can this person do this?": which capability grants which permission, and through which role or direct assignment.
  • Scoped capabilities: a provider interface, an access policy, a resolver service and a _scoped_capability route requirement.
  • Correct cache metadata throughout, so access results cache safely.

Security

  • Handing out capabilities requires its own permission, and nobody can assign a capability that grants permissions they do not hold themselves. This is enforced when the data is saved, not only in the forms.
  • A capability that includes a restricted permission is marked as such wherever it can be assigned, as core does on the permissions page.
  • Permissions that do not exist, for example from a module that is not installed, are never granted and are listed in the status report.
  • Only declared capabilities can be granted. Unknown keys are dropped.

Declaring capabilities

Site-wide capabilities list the permissions they stand for:

content.review:
  scope: drupal
  label: 'Review articles'
  group: Content
  permissions:
    - 'access content overview'
    - 'view any unpublished content'

content.publish:
  scope: drupal
  label: 'Publish articles'
  group: Content
  description: 'Write, edit and publish articles.'
  permissions:
    - 'create article content'
    - 'edit any article content'
    - 'use editorial transition publish'
  implies: [content.review]

Scoped capabilities name the scope they belong to:

project.view:
  scope: capabilities.project
  label: 'View the project'

project.edit:
  scope: capabilities.project
  label: 'Edit project pages'
  implies: [project.view]

A list that cannot be written down in advance comes from a callback named under capability_callbacks: in the same file. hook_capabilities_info_alter() changes what other modules declare.

Checking access

On a route, with the identifier taken from a route parameter:

my_module.project_edit:
  path: '/project/{project}/edit'
  requirements:
    _scoped_capability: 'project.edit'
  options:
    capability_scope: capabilities.project
    capability_parameter: project

In code, the capabilities.resolver service returns an access result for one capability, or every capability in a scope mapped to true or false. Site-wide capabilities need no special checks: they grant ordinary Drupal permissions, so existing _permission requirements and hasPermission() calls keep working.

Requirements

  • Drupal 11.3 or later
  • PHP 8.3 or later

Installation

composer require drupal/capabilities
drush en capabilities

Then give the right people the Administer capabilities and Assign capabilities permissions, and find the overview under People.

Project status

Under active development on the 1.0.x branch. The API may still change before the first stable release. Bug reports, ideas and patches are welcome in the issue queue.

Supporting organizations: 

Project information

Releases