Présentation du module Permissions by field sur Drupal 8

un cadenas sur une chaine

Le puissant système de contrôle d'accès et de permissions de Drupal 8 peut s'avérer être un critère déterminant pour le choix de Drupal. Ce système est à la base de modules comme Organic Group ou Domain access, qui permettent respectivement d'implémenter des groupes au sein d'un même site et d'implémenter une architecture multi-site virtuelle.

Mais ces puissants modules, parce qu'ils apportent aussi toute une interface de configuration et de gestion, sont complexes et donc plus long à porter sur Drupal 8. Il est toutefois possible de réaliser des fonctionnalités similaires, certes sans leur richesse fonctionnelle native, en s'appuyant sur ce même système de contrôle d'accès de Drupal, notamment pour implémenter ces notions de groupes, permettant de regrouper des contenus, des utilisateurs et de moduler les droits d'accès à ces contenus en fonction de l'appartenance à ces groupes.

Le module Permissions by field nous permet de contrôler les accès aux contenus d'un site Drupal selon plusieurs méthodes génériques, en s'appuyant sur la puissance d'Entity Reference et la Field API de Drupal 8, jusqu'à pouvoir déléguer une gestion complexe de droits d'accès vers les éditeurs de contenu selon leurs besoins.

Découvrons ce module et les différents cas d'usage possibles.

Principe de fonctionnement général

Une fois installé, Permissions by field nous met à disposition un nouveau type de champ. Les champs Permissions by field. Ces champs s'appuient sur les champs Entity Reference et leur ajoutent des propriétés supplémentaires permettant de déterminer les droits d'accès par rapport à l'entité référencée et les options sélectionnées. Le champ va en quelque sorte poser un verrou sur son contenu, verrou dont la clé sera l'entité référencée. Il suffira alors que les utilisateurs disposent de ce même champ, qui référence la même entité, pour obtenir la clé permettant d'ouvrir le verrou posé sur le contenu et pouvoir le consulter, le modifier ou encore le supprimer selon les droits qui auront été associés au verrou.

Le module supporte les types d'entités suivantes pour générer des droits d'accès relatifs à ces dernières :

  • Les contenus
  • Les termes de taxonomie
  • Les roles des utilisateurs
  • Et les utilisateurs. Pour ce dernier cas, on peut donner des droits directement aux utilisateurs référencés par le champ ou bien accorder ces mêmes droits aux utilisateurs ainsi qu'aux utilisateurs qui référencent les utilisateurs référencés par le champ.

Nous allons découvrir les différents cas d'utilisation proposés par ce module, et les configurations nécessaires pour implémenter des droits d'accès modulables.

Gestion des droits d'accès selon les contenus

Permissions selon les contenus

La configuration d'un champ Permissions by field pour référencer des entités de type contenu va nous permettre de réaliser un Organic group light très facilement. Pour reprendre l'exemple présenté dans le schéma ci-dessous, nous pouvons associer au type de contenu Article un champ Pbf (Permissions by field) qui va référencer le type de contenu Groupe. Nous aurons alors la possibilité d'associer des articles à un ou plusieurs groupes, et de déterminer pour chacun de ces groupes le niveau de droits accordés aux membres du groupe. De la même manière, en associant un autre champ Pbf aux utilisateurs, champ qui devra avoir le même nom machine que son équivalent sur les articles, nous pourrons associer ces utilisateurs à un ou plusieurs groupes, et du fait de cette association ces utilisateurs disposeront des droits définis sur chaque article publié.

Regardons en images comment configurer un tel fonctionnel.

Après avoir créer deux types de contenu, Article et Group, nous ajoutons un champ Permissions by field au type de contenu Article. Nous personnalisons le nom machine de notre champ : field_pbf_group.

Ajouter un champ Permissions by field

Nous paramétrons ensuite le type d'entité que nous pourrons référencer, et le nombre de valeurs autorisées. Nous choisissons ici de pouvoir référencer des contenus, de façon illimitée.

Configuration du stockage du champ Permissions by field

Nous pouvons ensuite paramétrer la configuration du champ. La configuration des champs Permissions by field est très similaire à celle des champs de type Entity Reference. Ce type de champ rajoute des options de configuration aux champs référençant les entités cibles pour déterminer les droits d'accès accordés aux utilisateurs référençant les mêmes entités cibles (dans notre exemple, les entités cibles sont les contenus de type Group)

Configuration du champ Permissions by field

Les options de configuration accordant les droits d'accès sur le contenu créé sont les suivantes :

  • Public : les droits d'accès utilisés seront ceux configurés globalement au niveau du site. Le cas d'usage typique est d'associer ce contenu à un groupe tout le laissant accessible aux visiteurs, ou aux utilisateurs non membres du groupe, selon les droits d'accès configurés au niveau du site. La sélection de cette option désactive toutes les autres options ci-après qui seront inopérantes.
  • Grant view : les utilisateurs référençant la même entité cible disposeront des droits de consultation du contenu
  • Grant update : les utilisateurs référençant la même entité cible disposeront des droits de modification du contenu
  • Grant delete : les utilisateurs référençant la même entité cible disposeront des droits de suppression du contenu

Nous pouvons alors associer un article au Groupe 1, et rendre cet article accessible sur tout le site, selon les permissions générales du site.

Configuration du champ Permissions by field pour un accès public

Ou encore ne donner l'accès à cet article qu'aux membres du Groupe 1 (i.e. les utilisateurs qui référencent le groupe 1 avec le même champ Permissions by field), avec les droits de consultation et de modification.

Configuration du champ Permissions by field pour un accès aux membres d'un groupe

Ou encore ne donner aucun accès à cet article, excepté bien sûr l'auteur du contenu qui disposera toujours de l'intégralité des permissions sur son contenu.

Configuration du champ Permissions by field pour un accès uniquement à l'auteur

Notons que ces droits d'accès ne sont opérants qu'à partir du moment où le contenu est publié. Si le contenu n'est pas publié, donc à l'état de brouillon, les permissions générales du site s'appliquent (voir son propre contenu non publié).

Configurer les permissions par contenu ou de façon globale

Nous pouvons configurer de quelle façon les permissions définies par un champ Permissions by field seront accessibles aux utilisateurs.

Soit les permissions accordées sont définies contenu par contenu.

Permissions contenu par contenu

Soit les permissions sont définies de façon globale.

Permissions selon la configuration du champ Pbf

Nous pouvons sélectionner le comportement souhaité depuis la configuration du formulaire du champ Permissions by field, sur la page de configuration de l'affichage du formulaire du type de contenu.

 

Configuration du widget Pbf

Notons que c'est au niveau de la configuration du widget que nous pouvons aussi configurer les droits d'accès cochés par défaut lors de la création de nouveaux contenus, si nous retenons de configurer contenu par contenu les droits d'accès.

Configuration des utilisateurs

Pour finaliser notre configuration, il reste à ajouter un champ Permissions by field aux utilisateurs du site.

Nous procédons de même que pour l'ajout du champ sur les contenus, en prenant soin d'utiliser le même nom machine (field_pbf_group dans notre exemple). Nous pouvons alors associer les utilisateurs aux différents groupes présent sur le site.

Association d'un utilisateur à un groupe

Il est alors possible de laisser les utilisateurs sélectionner eux même les groupes auxquels ils souhaitent être membre, depuis l'édition de leur profil, ou encore de n'autoriser que certains roles ou utilisateurs à pouvoir accéder et modifier ces champs associés aux utilisateurs, au moyen d'un petit module sur mesure ou encore avec le module Field permissions.

Notons que le module Permissions by field est en phase active de développement, et permet d'automatiser la saisie de ces champs Permissions by field attachés aux utilisateurs selon certaines conditions (cf. la section Synchronisation des champs ci-dessous)

Gestion des droits selon les termes de taxonomie

Permissions selon les termes de taxonomie

Permissions by field nous permet également de déterminer les droits par rapport à une référence sur un terme de taxonomie. Le fonctionnement et la configuration est très exactement identique à celui basé sur la référence à un contenu, mais en nous appuyant cette fois sur des termes.

Cela peut permettre de moduler certains accès en modification par exemple, selon certaines sections du site, ou encore de reproduire cette construction de groupe décrite plus haut mais cette fois axée sur la taxonomie.

Gestion des droits selon les roles des utilisateurs

Permissions selon les roles des utilisateurs

Permissions by field nous permet également de moduler les permissions d'accès aux contenus selon le rôle des utilisateurs. Nous pouvons créer un champ sur les contenus de type Article qui vont référencer les différents rôles configurés sur le site.

Configuration du stockage du champ Permissions by field pour les rôles

Pour chaque article publié, nous pouvons alors moduler les permissions accordées sur ce contenu en fonction des rôles des utilisateurs.

Utilisation des rôles pour moduler les permissions pour chaque contenu

Par exemple, donner des droits de modification au rôle Editor, et des droits de consultation au rôle Contributor.

Gestion des droits selon les utilisateurs

Nous pouvons accorder des droits directement aux utilisateurs référencés. Mais nous pouvons aussi accorder ces droits aux utilisateurs qui référencent les utilisateurs référencés. La méthode à choisir pour accorder les droits doit être définie dans les paramètres du champ.

Nous ajoutons donc un champ Permissions by field au type de contenu Article et sélectionnons cette fois les utilisateurs comme entité cible du champ. Dans la configuration du champ nous pouvons alors sélectionner quelle méthode nous allons utiliser pour accorder des droits selon les utilisateurs référencés

Choix de la méthode pour gérer les droits selon les utilisateurs référencés

Nous pouvons alors soit

  • Donner les permissions configurées directement aux utilisateurs référencés par ce champ
  • Donner les permissions configurées aux utilisateurs référencés par ce champ et aux utilisateurs qui référencent depuis un champ Pbf les utilisateurs référencés 

Accorder des droits directement à certains utilisateurs

Permissions par utilisateur

Le fonctionnement de ce cas d'usage est somme toute très simple. Nous avons alors la possibilité d'accorder différentes permissions utilisateur par utilisateur au contenu, ce qui permet de jouer très finement sur les droits d'accès, contenu par contenu, et utilisateur par utilisateur.

Accorder des droits aux utilisateurs référençant les utilisateurs référencés par le champ Permissions by field

Permissions selon les utilisateurs

 

Ce cas d'usage, sans doute plus rare, permet d'adresser une gestion des permissions selon une logique de réseaux entre utilisateurs d'un site. En établissant des liens entre utilisateurs du site au moyen d'un champ Permissions by field, par exemple permettre aux utilisateurs de se connecter à d'autres utilisateurs (ami, relation, etc.), nous pouvons alors accorder des droits aux relations ou amis d'un utilisateur qui sera référencé par le contenu.

La configuration de ce cas d'usage est alors similaire à celui basé sur les contenus ou les termes de taxonomie. La clé sera de créer un champ dont le nom machine sera identique sur les contenus de type Article et les utilisateurs.

Synchronisation de champs Permissions by field

Il est possible de mettre en place une synchronisation entre deux champs Pbf. Le cas d'usage typique est de référencer des utilisateurs depuis un type de contenu Groupe, afin de sélectionner les membres d'un groupe, et de synchroniser le champ associé à ces utilisateurs pour qu'ils référencent ce groupe et disposent par ce fait des droits correspondant aux contenus liés à ces groupes.

Afin de synchroniser deux champs Permissions by field, il faut deux conditions :

  • Sur l'entité hôte (le type de contenu), le champ Pbf doit référencer des entités de type utilisateur
  • L'entité utilisateur doit disposer d'un champ Pbf qui référence le même type de contenu.

Passons à un exemple pour mieux comprendre le principe.

Nous créons un champ Pbf (nom machine field_group_user) sur le type de contenu Groupe et nous le configurons pour référencer des utilisateurs. Si nous reprenons les étapes de configuration décrites dans la section Gestion des droits d'accès selon les contenus, les utilisateurs disposent d'un champ Pbf (nom machine field_pbf_group) qui référencent les types de contenu Groupe.

Nous pouvons alors configurer le champ attaché au groupe pour qu'il se synchronise automatiquement avec le champ détecté associé aux utilisateurs.

Configuration de la synchronisation d'un champ Permissions by field

Ainsi, dès qu'un utilisateur sera référencé depuis un groupe, son champ sera synchronisé avec ce groupe, et héritera alors de la clé associée à ce groupe, lui permettant d'accéder aux contenus disposant de ce verrou.

Nous disposons également d'une option qui permet de synchroniser en retour le champ associé au groupe si l'utilisateur modifie les contenus référencés (les groupes) depuis son profil. Nous disposons alors d'une synchronisation bi-directionnelle des champs. Ainsi un utilisateur peut sélectionner lui-même les groupes auxquels il souhaite participer, et le champ associé au groupe référençant les "membres" de ce groupe sera mis à jour en conséquence.

A l'inverse si l'option (Allow targeted field from users to synchronize this field) n'est pas cochée, seul les modifications effectuées sur le contenu Groupe synchronisera le champs associé aux utilisateurs.

Et nous pouvons vérifier que le champ associé aux utilisateurs est bien synchronisé depuis sa page de configuration.

Champ Permissions by field synchronisé depuis un autre champ

Cette option de synchronisation peut permettre de mettre en place rapidement une gestion simplifiée des membres d'un groupe, que ce soit depuis le groupe (et l'utilisateur qui disposent des droits de modification du groupe, droits qui peuvent être accordés depuis ce même champ référençant les utilisateurs), ou que ce soit depuis le profil de chaque utilisateur, leur laissant le libre choix de rejoindre ou quitter les différents groupes disponibles.

Gérer des permissions complexes d'accès aux contenus

Permissions by field, en s'appuyant sur les champs et sur entity Reference pour moduler les différentes permissions des contenus, permet d'adresser de nombreux cas d'usage. Il est aussi tout à faire possible d'associer sur un même contenu différents types de champs Permissions by field pour mettre en place un système complexe et modulable de droits d'accès, accessible aux éditeurs de contenus, et pas seulement aux concepteurs ou administrateurs du site.

Gestion de permissions complexes

Permissions by field est un module très simple. Il s'appuie avant tout sur la puissance et la souplesse des champs Entity Reference. Il peut permettre de mettre en place des permissions complexes, qu'elles soient basées sur des contenus, des termes de taxonomie, des roles ou encore des utilisateurs, ou un système de permissions plus simple pour adresser des cas typiques d'espaces, de sections ou de groupes privés / publics au sein d'un site.

Du fait qu'il s'appuie sur Entity Reference, nous pouvons utiliser Views pour créer toutes les vues nécessaires basées sur les relations mises en place entre contenus, termes de taxonomie, roles et utilisateurs. Bien que n'offrant pas d'interface native pour proposer une gestion de membres, de leurs roles, etc au sein d'un espace privé, à l'instar des module Organic Group ou Group, il peut adresser de nombreux cas d'usage plus simples ne nécessitant pas toute la puissance de ces modules.

 

Commentaires

Soumis par Bernard (non vérifié) le 23/02/2017 à 10:53 - Permalien

Bonjour,

très bon article et un module très intéressant que j'ai testé mais il ne prends pas en compte le contenu déjà existants malgré des paramètres par défaut établis "Set grant access settings generally".

Ai-je oublié une étape ou y a t il une autre modification à faire ?

Bonjour,
Tant que le contenu n'a pas été enregistré avec le nouveau champs PBF actif, les verrous ne sont pas posés. Il vous suffit de lancer un enregistrement en masse de vos contenus existants pour lesquels vous avez ajouté un contrôle d'accès.

Soumis par Mojowork (non vérifié) le 20/11/2017 à 11:24 - Permalien

En réponse à par fabrice

Pour le contenu déjà existant, l'enregistrement simple ne semble pas attribuer la valeur par défaut au champ pbf du contenu.
Je pense devoir faire un traitement en lot pour permettre aux personnes ayant le rôle Anonyme de voir le contenu.
En utilisant le hook_update ca devrait passer mais saurais tu quelle fonction appeler pour "setter" le champ pbf en lui fournissant en pluss les bons "grant" ?

Merci pour l'article

Bonjour,
C'est à la base un champ entity Reference. On peut donc le mettre à jour par exemple ainsi. Vous pouvez regarder les tests qui sont dans le module.

// Set article2 as public without custom permission.
$value = [
'target_id' => $this->group1->id(),
'grant_public' => 1,
'grant_view' => 0,
'grant_update' => 0,
'grant_delete' => 0,
];
$this->article2->set($this->fieldname, $value)->save();

Soumis par Mojowork (non vérifié) le 23/11/2017 à 16:32 - Permalien

En réponse à par fabrice

Merci bcp pour cette réponse, ca marche très bien, y compris lorsque l'on souhaite poser le verrou sur un rôle entier.
Je vous file la variante même si elle est triviale, il suffit de préciser l'identifiant du rôle.
$value = [
'target_id' => "anonymous",
'grant_public' => 0,
'grant_view' => 1,
'grant_update' => 1,
'grant_delete' => 0,
];

QUESTION BONUS : mon champ est multivalué et du coup j'ai un problème avec la méthode set :
$this->article2->set($this->fieldname, $value)->save();

J'ai essayé un truc du style mais ca marche pas :
$value = [
'target_id' => "anonymous",
'grant_public' => 0,
'grant_view' => 1,
'grant_update' => 1,
'grant_delete' => 0,
],
[
'target_id' => "authenticated",
'grant_public' => 0,
'grant_view' => 1,
'grant_update' => 1,
'grant_delete' => 0,
]
];

Merci

C'est bon, j'ai trouvé et j'ai honte car c'etait grave évident (mais avec Drupal on se mefie tjs;)):
$value1 = [
'target_id' => "anonymous",
'grant_public' => 0,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
];
$value2 = [
'target_id' => "authenticated",
'grant_public' => 0,
'grant_view' => 1,
'grant_update' => 1,
'grant_delete' => 0,
];

et paf :
$node->set("fieldname", $value1);
$node->fieldname[] = $value2;

Soumis par Chebil Abdelffatteh (non vérifié) le 12/07/2017 à 12:17 - Permalien

Bonjour,

Objectif : donner un accès unique au node par utilisateur .

J'ai essayé de configurer ce module afin de donner un accès par node aux différent utilisateurs :
1- installer module
2- ajouter un field de type permission by field à mon content type
3- choisir la référence User
4- Donner juste accès view à utilisateur X

Résultat = ne fonctionne pas.

Est-ce-que j'ai oublié une étape ?

Cdt,

Soumis par fabrice le 13/07/2017 à 15:55 - Permalien

En réponse à par Chebil Abdelffatteh (non vérifié)

Reconstruire les permissions peut-être. Mais si vous constatez un souci alors le mieux est de faire une issue sur la file du module, et de mieux détailler votre problème. Car "ne fonctionne pas" n'est pas très utile comme rapport de bug.

Soumis par Morgane (non vérifié) le 26/04/2018 à 16:49 - Permalien

Bonjour, parfait ce petit module, je l'ai indexé sur les rôles c'est exactement ce que je cherchais. Y'a t'il moyen de le présenter sous forme de case a cocher plutot qu'en autocomplétion ?

Merci d'avance !

Soumis par Benoit (non vérifié) le 09/05/2019 à 23:33 - Permalien

Bonjour,
Cela fait 2 jours que je me bat avec ce module dont le paramétrage semble relativement simple, et le résultat obtenu n'est pas probant.
Voilà ce que j'ai mis en place :
- Création d'un nouveau type de contenu : group (il contient seulement le nom du groupe et un champ description)
- création du groupe : group1
- création du groupe : group2

- Création de 3 users (user1, user2, user3)
- user1 : pbf_ref_group = group1
- user2 : pbf_ref_group = group2
- user3 : pbf_ref_group = non alimenté

- modification du type de article : Ajout d'un champ pbf : pbf_ref_group
- création d'un article : article1, pbf_ref_group=group1, with grant_view and grant_update checked
- création d'un article : article2, pbf_ref_group=group2, with grant_view and grant_update checked

les 3 users peuvent voir les 3 articles !!

Ou est-ce que je me trompe ?

Je vous remercie par avance pour toute aide ou information qui pourraient me mettre sur la bonne piste.

Soumis par Falvard (non vérifié) le 08/05/2021 à 12:52 - Permalien

Bonjour,
Tout d'abord merci pour vos billets qui comme toujours sont excellents.
J'aimerai mettre en place pour un type de contenu, la possibilité pour tous les utilisateurs du rôle de celui qui a créé une occurrence du contenu (et uniquement eux) de voir, modifier, supprimer cette occurrence.
Avec les permissions standards, pour le type de contenu en question :
- si je coche "uniquement son propre contenu", les autres utilisateurs du rôle ne peuvent rien faire.
- si je coche "n'importe quel contenu", tous les utilisateurs quelque soit leur rôle peuvent agir dessus.
Afin d'implémenter ce type de comportement je pensais utiliser le module "Permissions by field" en le "couplant" aux rôles.
Après quelques essais c'est parfait, mais pas très pratique dans mon cas.
Pourquoi demander à l'utilisateur son rôle (pour restreindre l'accès justement à tous les utilisateur de son rôle) alors qu'on connaît le rôle.
Serait-il possible d'avoir une valeur par défaut du type token [current-user:roles:keys:last] et ainsi masquer ce champ ?
Merci

Soumis par fabrice le 08/05/2021 à 19:23 - Permalien

Bonjour,

Je ne pense qu'un tel token relève du périmètre de ce module. Vous devriez regarder si un autre module contribué peut proposer ce genre de chose. Sinon vous pouvez définir la valeur du champ basé sur le role de l'utilisateur dans un hook_entity_presave, et cacher le champ du formulaire, pour faire plus simple.

Bonjour,
Finalement j'ai suivi vos conseils et développé un module custom. Jusqu’à maintenant cela fonctionnait bien mais depuis quelque temps j'ai des problèmes. J'ai donc désactivé mon module custom => Toujours le problème. Je suis revenu à la version 8.x-1.2 au cas où mais toujours le problème. Du coup je ne vois que deux solutions, soit j'utilise mal le module (mais je pense que lorsque je l'ai mis en place il fonctionnait bien sinon je ne l'aurai pas fait), soit c'est la montée de version vers Drupal 8.9.19 qui a causé ce problème.
J'utilise la configuration par utilisateur en attribuant des droits grant view, update et delete. Les droits update et delete semblent ne pas fonctionner. C'est à dire un utilisateur n'ayant pas ces droits sur un contenu peut tout de même les modifier ou les supprimer. Ma table des droits partagés semble bonne. Par contre, les droits views fonctionnent correctement.
Merci de votre retour

Ajouter un commentaire