Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Permissions

A permission allows one action: "view content", "administer the blog". A module declares permissions, and the administrator gives them to roles in the panel. Code checks not the user's role but whether the permission is present — so one module works on sites with any set of roles.

Where permissions are declared

In the file blog.permissions.yml in the root of the module folder. Create it by hand:

# web/modules/custom/blog/blog.permissions.yml
administer blog:
  title: 'Administer the blog'

The key is the machine name of the permission, a plain string with spaces. title is the name the administrator sees.

Granting a permission

After drush cr open People → Permissions, the address /admin/people/permissions. The Blog group now has the row "Administer the blog" with a checkbox for each role. Tick the role you need and save. By default the Administrator role gets every permission automatically.

Checking in a route

Replace the general permission in the settings route with your own:

# web/modules/custom/blog/blog.routing.yml
blog.settings:
  path: '/admin/config/content/blog'
  defaults:
    _form: '\Drupal\blog\Form\SettingsForm'
    _title: 'Blog settings'
  requirements:
    _permission: 'administer blog'

Now only roles with the administer blog permission can open the settings page. Others see "Access denied", and the link to the page disappears from their menu.

Several permissions are listed on one line: a comma means all are needed, a plus means any one is enough.

# web/modules/custom/blog/blog.routing.yml
  requirements:
    _permission: 'administer blog+administer site configuration'

Description and warning

# web/modules/custom/blog/blog.permissions.yml
administer blog:
  title: 'Administer the blog'
  description: 'Change the list title and the number of articles per page.'
  restrict access: true
 
view blog subscribers:
  title: 'View the list of subscribers'

description is shown under the title. restrict access: true adds a warning that the permission should be given only to trusted roles.

Checking in code

Sometimes you need to close not the whole page but a part of it. In a controller the current user is returned by the currentUser() method:

// web/modules/custom/blog/src/Controller/BlogController.php
public function list(): array
{
    $build['intro'] = ['#markup' => $this->config('blog.settings')->get('list_title')];
 
    if ($this->currentUser()->hasPermission('view blog subscribers')) {
        $build['admin'] = ['#markup' => '<p>Subscribers: 12</p>'];
    }
 
    return $build;
}

The line about subscribers is seen only by those who have the permission. In hooks the user is taken through \Drupal::currentUser().

MethodWhat it returns
hasPermission('…')Whether the permission is present
isAuthenticated()Whether the user is logged in
isAnonymous()Whether it is an anonymous visitor
id()The user number, 0 for an anonymous visitor
getDisplayName()The display name

Access to a node

The right to a particular node depends on the author, the published status and access modules, so the entity itself is asked:

// web/modules/custom/blog/src/Controller/BlogController.php
if ($node->access('update')) {
    // show the Edit link
}

The operations are view, update, delete. Without a second argument the check is made for the current user.

Common mistake

Checking a role — in_array('editor', $user->getRoles()) — is a bad habit: roles differ from site to site, they are renamed and added. Declare a permission and check hasPermission(), and let the site administrator decide who gets it. And keep in mind: the user with number 1 passes any permission check, so test access under an ordinary account.

Thanks for reading!

Donate to the site — we work hard for you.