Vous êtes ici

Créer et utiliser des permissions dynamiques

Vous avez 30 secondes ?
S'abonner au flux d'actualités
Rubrique: 
Technique
Difficultée: 
Intermédiaire
Permissions dynamiques :
Par opposition à une permissioninfo-icon statique, une permissioninfo-icon dynamique est une permissioninfo-icon dont le nombre et la nature ne sont pas connus de leur créateur. Par exemple afficher les résultats pour le contenu de type X constitue une permissioninfo-icon dynamique : il y en aura une par type de contenu créé sur le site. De fait, le créateur du module ne peut pas prévoir leur nombre en avance et ne peut donc pas les lister dans le fichier $module.permissions.yml comme pour les permissions statiques.
 
Dans ce tutoriel, nous nous intéresserons aux permissions dynamiques. Prérequis : le module TutoPermissions, une fois le tutoriel sur les permissions statiques terminé.

Déclarer de nouvelles permissions dynamiques

Dans ce tutoriel, nous allons améliorer notre petit module TutoPermissions pour créer des permissions liées aux types de contenus définis sur le site. Cela constitue une déclaration dynamique des permissions puisqu'il nous faut créer une permissioninfo-icon par type de contenu présent sur le site, sans en connaître ni le nombre, ni leurs noms, en avance.
 
La déclaration de nouvelles permissions dynamiques s'effectue en déclarant une méthode et sa classe associée en tant que callback dans le fichier de permissioninfo-icon YAML (vu dans le tuto précédent : $module.permissions.yml). Lors de l'analyse de ce fichier, les permissions statiques contenues seront générées, puis les callbacks déclarés seront lancés. Ces méthodes PHP peuvent alors ajouter un nombre arbitraire de permissions à notre module.

Déclaration des callbacks dynamiques

En prenant le module indiqué dans les prérequis, nous allons ajouter les lignes suivantes à la fin de notre fichier tutopermissions.permissions.yml.
# Add a dynamic permissioninfo-icon callback
permission_callbacks:
  - Drupal\tutopermissions\DynamicPermissions::permissions
La syntaxe est la suivante : nous indiquons tout d'abord la déclaration de callbacks pour la création de permissions via la ligne : permission_callbacks.
La ligne suivante définit la classe à instancier et la méthode au sein de cette classe à utiliser. La syntaxe est la suivante :

  - Drupal\$modulename\$ClassName::$methodName

permission_callbacks attend un tableau de méthodes, d'où la syntaxe commençant par une indentation suivie d'un tiret. Cela vous permet de lancer plusieurs méthodes issues de plusieurs classes si nécessaire.

Implémentation des callbacks

Nous devons désormais implémenter la création des permissions. Il nous faut donc :
  1. Créer la classe DynamicPermissions dans le dossier src de notre module. Le fichier sera donc /tutopermissions/src/DynamicPermissions.php
  2. Créer la méthode permissions au sein de cette classe.
  3. Boucler sur chacun des types de contenus du site.
  4. Ajouter la permissioninfo-icon pour chacun des types de contenus.
Voici le code complet de notre fichier DynamicPermissions.php :
<?php

/**
 * @file
 * Contains \Drupal\tutopermissions\DynamicPermissions.
 */

// This file is defined within our module in src folder directly.
namespace Drupal\tutopermissions;

// Inject the NodeType class which will allow use to retrieve content types.
use Drupal\node\Entity\NodeType;
// Inject translation wrapper to use $this->t() method in our permissions.
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * This class holds dynamic permissioninfo-icon callback for our module.
 */

class DynamicPermissions {

  // Use the TranslationInterface wrapper methods in our code.
  // We need it for $this->t() to translate permissioninfo-icon title and description.
  use StringTranslationTrait;

  /**
   * Callback method to define permissions for each content type in our module.
   * @return array
   *   An array of permissions to define.
   */

  public function permissions() {
    $permissions = array();

    // Generate permissions for all content types.
    foreach (NodeType::loadMultiple() as $type) {

      // Get type id and type label for display
      $type_id = $type->id();
      $type_params = array('%type_name' => $type->label());

      // Create the permissioninfo-icon. The array keys are the same as per static
      // permissions definition.
      $permissions["access resultpage for $type_id"] = array(
        'title' => $this->t("Accéder aux résultats pour %type_name", $type_params),
        'description' => $this->t("Autoriser l'accès à la page de résultat de TutoPermissions pour le contenu de type : <em>%type_name</em>.", $type_params),
      );
    }

    return $permissions;
  }
}

 
Nos nouvelles permissions apparaissent sur la page de gestion des droits (en rouge sur l'image).
 
Avons-nous vraiment besoin d'expliquer le code de la classe DynamicPermissions ? Normalement non puisque la POO PHP est un prérequis de ces tutos ! Notez simplement ceci :
- Il est nécessaire d'utiliser StringTranslationTrait qui définit des méthodes wrappers de la classe TranslationInterface. Elle nous permet l'usage de la méthode $this->t() afin de traduire nos chaînes de caractères.
- Il est nécessaire d'importer la classe NodeType afin de récupérer les types de contenus. Cette classe définit une Configuration Entity, mais nous verrons ce que c'est dans un prochain tutoriel. Tout ce dont nous avons besoin ici, c'est de sa méthode loadMultiple() qui récupère toutes les entités de configurations (en l'occurrence ici les types de contenus) enregistrées.
- Les clefs de chaque permissions sont les mêmes que lors de la définition des permissions statiques : title, description, restrict access et warning. N'hésitez pas à vous reporter au tutoriel correspondant.
 
N'oubliez pas de traduire vos chaînes de caractères ! Ceci est fait automatiquement lors de la déclaration de permissions statiques via le fichier YAML, mais pas ici !

Utilisation des permissions dynamiques

Les permissions dynamiques s'utilisent exactement comme les permissions statiques ! Après tout, ce sont des permissions comme les autres ! La plus grande difficulté sera de récupérer la clef de la permissioninfo-icon pour pouvoir l'utiliser ! Voyons ici un exemple en modifiant l'affichage de notre page de résultat. Pour cela, il suffit d'utiliser la méthode hasPermission() d'un objet utilisateur, tout comme nous l'avions fait précédemment.
 
Voyons un cas pratique : remplaçons le code de la fonction resultpage() de la classe src/Controller/TutoPermissionsController.php par le code suivant :
  /**
   * Return the 'result' page.
   *
   * @return array A render array containing our 'result' page content.
   */

  public function resultpage() {
    $user = \Drupal::currentUser();

    $output = array();
    $output['welcome'] = array(
      '#markup' => $this->t("Bienvenue sur notre fausse page de résultat.")
    );

    if ($user->hasPermission('access adminpage')) {
      $output['admin'] = array(
        '#type' => 'container'
      );
      $output['admin']['infos'] = array(
        '#markup' => $this->t("Quelques infos spécifiques pour l'administration.")
      );
    }

    // Generate results for each content types.
    foreach (NodeType::loadMultiple() as $type) {
      $type_id = $type->id();
      $type_params = array('%type_name' => $type->label());

      // Check user permissioninfo-icon regarding current content type.
      if ($user->hasPermission("access resultpage for $type_id")) {
        $output["result_$type_id"] = array(
          '#type' => 'container'
        );
        $output["result_$type_id"]['infos'] = array(
          '#markup' => $this->t("Quelques résultats pour le contenu de type %type_name...", $type_params)
        );
      }
    }

    return $output;
  }

Désormais, en vous connectant à la page /resultpage avec des utilisateurs de différents rôles, vous devriez avoir un visuel différent dépendant de votre niveau de permissioninfo-icon !
 
Vue pour un utilisateur anonyme.
 
Vue pour un utilisateur administrateur.
 
Nous l'avions vu dans le tutoriel précédent sur les permissions, mais le super admin, aussi appelé parfois user #1 (ou user/1) voit tout ! Les permissions ne s'appliquent pas à cet utilisateur au statut particulier. Ne vous méprenez pas lors de vos tests !
 
En résumé...
 
L'ajout de permissions dynamique à votre module permet d'ajuster son comportement à des composants définis en dehors de votre module et dont vous n'avez pas la maîtrise. La déclaration de ces permissions dynamiques s'effectue via une série de callbacks définis dans le fichier $module.permissions.yml et implémentés dans une classe de votre choix placée par convention dans le dossier src de votre module.
Notation: 
Average: 5 (1 vote)
Vous avez aimé: