Altérer le contrôle d'accès des entités de Drupal 8

Un centre de contrôle à l'abandon

Drupal 8 dispose nativement d'un contrôle d'accès très évolué pour les entités de type Node, autrement dit pour tous les contenus d'un site. Les autres entités disposent de contrôle d'accès plus sommaires, même si l'évolution fonctionnelle agile de Drupal 8 va nous permettre de voir évoluer cette situation très rapidement, notamment par exemple pour une gestion beaucoup plus fine des droits d'accès relatifs aux blocs de contenu.

Mais grâce à l'architecture modulaire de Drupal 8, et son découpage fonctionnel, altérer et personnaliser les droits d'accès sur les entités peut se faire aisément. Découvrons comment personnaliser et prendre le contrôle sur les accès aux pages des termes de taxonomy.

Nous allons pour ce faire créer un module intitulé Term page access.

Créer des permissions pour chaque vocabulaire disponible

Au lieu de déclarer des permissions statiques, ce que nous ne pouvons pas faire puisque ne connaissant pas les vocabulaires qui seront créé, nous déclarons de nouvelles permissions dynamiques au moyen d'une fonction de Callback..

# File term_page_access.permissions.yml
permission_callbacks:
  - \Drupal\term_page_access\TermPageAccessPermissions::permissions

Nous déclarons ici une fonction de Callback pour déclarer nos permissions.

La classe TermPageAccessPermissions, située à la racine du répertoire /src de notre module, contiendra alors la méthode permissions() qui va déclarer nos différentes permissions pour personnaliser l'accès aux pages de termes de taxonomy.

<?php

namespace Drupal\term_page_access;

use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\core\Entity\EntityTypeManagerInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;


/**
 * Defines a class for dynamic permissions based on vocabularies.
 */
class TermPageAccessPermissions implements ContainerInjectionInterface {

  use StringTranslationTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;


  /**
   * Constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container->get('entity_type.manager'));
  }

  /**
   * Returns an array of transition permissions.
   *
   * @return array
   *   The access protected permissions.
   */
  public function permissions() {

    $perms = [];
    $vocabularies = $this->entityTypeManager->getStorage('taxonomy_vocabulary')->loadMultiple();
    /* @var \Drupal\taxonomy\Entity\Vocabulary $vocabulary */
    foreach ($vocabularies as $id => $vocabulary) {
      $perms['view ' . $id . ' terms'] = [
        'title' => $this->t('View the %label terms', [
          '%label' => $vocabulary->label(),
        ]),
        'description' => $this->t('Access to the terms page of %label vocabulary', [
          '%label' => $vocabulary->label(),
        ]),
      ];
    }

    return $perms;
  }

}

 

Et nous obtenons dans l'interface de gestion des permissions la possibilité de contrôler qui pourra voir quoi.

Permissions dynamiques générées sur les termes de taxonomy

 

Altérer le contrôle d'accès des termes de taxonomy

Il nous suffit désormais d'altérer le type d'entité des termes de taxonomy pour lui substituer à sa classe de contrôle d'accès la notre que nous aurons créée.

Utilisons hook_entity_type_alter() pour changer cette classe.

<?php

/**
 * @file
 * Contains term_page_access.module.
 */


/**
 * Implements hook_entity_type_alter().
 */
function term_page_access_entity_type_alter(array &$entity_types) {
  /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
  $entity_types['taxonomy_term']->setAccessClass('Drupal\term_page_access\TermPageAccessControlHandler');
}

Et nous créons notre propre classe de contrôle d'accès, inspiré de la classe originale situé dans le module Taxonomy, pour nous permettre d'affiner les accès aux pages des différents termes de taxonomy.

<?php

namespace Drupal\term_page_access;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityAccessControlHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Defines the access control handler for the taxonomy term entity type.
 *
 * @see \Drupal\taxonomy\Entity\Term
 */
class TermPageAccessControlHandler extends EntityAccessControlHandler {

  /**
   * {@inheritdoc}
   */
  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
    switch ($operation) {
      case 'view':
        return AccessResult::allowedIfHasPermissions($account, ["view {$entity->bundle()} terms", 'administer taxonomy'], 'OR');
        break;

      case 'update':
        return AccessResult::allowedIfHasPermissions($account, ["edit terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
        break;

      case 'delete':
        return AccessResult::allowedIfHasPermissions($account, ["delete terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
        break;

      default:
        // No opinion.
        return AccessResult::neutral();
    }
  }

  /**
   * {@inheritdoc}
   */
  protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
    return AccessResult::allowedIfHasPermission($account, 'administer taxonomy');
  }

}

Un contrôle d'accès sur mesure

Notons ici que ces nouvelles permissions d'accès aux termes de taxonomy s'appliquent aux pages de rendu proprement dites des termes de taxonomy mais aussi également aux termes associés à un contenu et qui sont rendus sur la page du contenu elle-même.  Ainsi un utilisateur ne pouvant pas visualiser un terme de taxonomy ne pourra pas les voir apparaître sur le rendu d'une page de contenu.

Dans ce cas, pour pouvoir permettre à un utilisateur de visualiser ces termes sur une page de contenu, tout en lui interdisant un accès à la page du terme de taxonomy elle-même, il convient plutôt de recourir aux événements pour contrôler seulement l'accès à ces pages et non à l'intégralité des termes de taxonomy.

Vous avez des problématiques de droits d'accès complexes sur votre projet Drupal 8 ? N'hésitez pas à recourir aux services d'un freelance spécialiste Drupal 8 qui pourra les adapter à vos besoins et vos processus métier.

 

Ajouter un commentaire