Défilement
Restreindre l’accès au vocabulaire des termes de taxonomie en utilisant un Event Subscriber
Parfois, vous avez besoin de Catégories fixes et permanentes sur le site, qui ne doivent être mises à jour qu'accidentellement. Dans ce cas, vous pouvez utiliser un code personnalisé avec un Event Subscriber.
Ajoutons une nouvelle classe Event Subscriber dans un module personnalisé.
drupalbook_custom.services.yml
services:
drupalbook_custom.tag_redirect_subscriber:
class: Drupal\drupalbook_custom\EventSubscriber\TagRedirectSubscriber
arguments:
- '@entity_type.manager'
- '@current_user'
tags:
- { name: event_subscriber }
Et incluez notre Event Subscriber dans drupalbook_custom/src/EventSubscriber/TagRedirectSubscriber :
<?php
namespace Drupal\drupalbook_custom\EventSubscriber;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Redirige les non-administrateurs des pages d’administration du vocabulaire Tag.
*
* Un subscriber au niveau de la requête s’exécute tôt, nous permettant d’interrompre
* la requête et de renvoyer une réponse de redirection avant l’exécution du contrôleur associé.
*/
class TagRedirectSubscriber implements EventSubscriberInterface {
/**
* Le service gestionnaire de types d’entités.
*
* Conservé comme exemple de dépendance ; pas strictement nécessaire pour la
* logique actuelle mais utile si des améliorations futures requièrent le chargement d’entités.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* Le service proxy de l’utilisateur courant.
*
* Utilisé pour vérifier rapidement les rôles afin d’éviter la redirection pour
* les administrateurs.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected AccountProxyInterface $currentUser;
/**
* Constructeur du subscriber.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Le gestionnaire de type d’entité.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* L’utilisateur effectuant actuellement la requête.
*/
public function __construct(
EntityTypeManagerInterface $entity_type_manager,
AccountProxyInterface $current_user,
) {
$this->entityTypeManager = $entity_type_manager;
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
// La priorité 32 garantit que les paramètres de route sont disponibles,
// mais que le contrôleur n’a pas encore été exécuté.
return [
KernelEvents::REQUEST => ['onKernelRequest', 32],
];
}
/**
* Effectue la redirection lorsqu’un non-administrateur accède aux routes d’administration des tags.
*
* @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
* L’événement kernel portant la requête.
*/
public function onKernelRequest(RequestEvent $event): void {
// Agir uniquement sur la requête principale.
if (!$event->isMainRequest()) {
return;
}
// Laisser passer les administrateurs sans redirection.
if ($this->currentUser->hasRole('administrator')) {
return;
}
$request = $event->getRequest();
$route_name = $request->attributes->get('_route');
// Destination pour toutes les tentatives bloquées.
$redirect_to = 'https://drupalbook.org/admin/structure'
. '/taxonomy/manage/tag/overview';
switch ($route_name) {
case 'entity.taxonomy_vocabulary.overview_form':
case 'entity.taxonomy_vocabulary.overview_terms':
case 'entity.taxonomy_term.add_form':
// Vérifie que nous sommes sur le vocabulaire "tag".
$vocabulary = $request->attributes->get('taxonomy_vocabulary');
if (!empty($vocabulary) && $vocabulary->id() === 'tag') {
$event->setResponse(new TrustedRedirectResponse($redirect_to));
}
return;
case 'entity.taxonomy_term.edit_form':
case 'entity.taxonomy_term.delete_form':
/** @var \Drupal\taxonomy\Entity\Term|null $term */
$term = $request->attributes->get('taxonomy_term');
// bundle() retourne le nom machine du vocabulaire.
if ($term && $term->bundle() === 'tag') {
$event->setResponse(new TrustedRedirectResponse($redirect_to));
}
return;
default:
return;
}
}
}
La classe TagRedirectSubscriber
est un Event Subscriber personnalisé pour Drupal, conçu pour restreindre l’accès aux pages d’administration d’un vocabulaire de taxonomie spécifique (ici, « tag ») aux non-administrateurs. Voici une explication de sa structure et des points clés :
1. Objectif et cas d’utilisation
- But : Empêcher les mises à jour accidentelles ou non autorisées du vocabulaire « tag » en redirigeant les utilisateurs non-admin hors de ses routes d’administration.
- Avantage : Offre une couche de contrôle d’accès basée sur l’interface pour des vocabulaires de taxonomie critiques, garantissant la stabilité de catégories fixes.
2. Structure de la classe et dépendances
- La classe implémente
EventSubscriberInterface
, la rendant compatible avec le système d’événements Symfony utilisé par Drupal. - Dépendances injectées via le constructeur :
EntityTypeManagerInterface
: inclus pour des opérations potentielles sur les entités. Non requis pour la logique actuelle mais facilite l’extensibilité future.AccountProxyInterface
: utilisé pour récupérer et vérifier efficacement les rôles de l’utilisateur courant.
3. Événements souscrits
- La classe souscrit à l’événement
KernelEvents::REQUEST
avec une priorité de 32.
Cette priorité garantit :- Les paramètres de la route sont disponibles (le routage est résolu).
- Le contrôleur de la route n’a PAS encore été exécuté, permettant au subscriber d’intercepter et d’interrompre la requête avec une redirection si nécessaire.
4. Logique de redirection
- La méthode
onKernelRequest()
réalise tous les contrôles d’accès et la logique de redirection :- Agit uniquement sur les requêtes principales : évite la gestion multiple lors des sous-requêtes.
- Laisse passer les administrateurs : si l’utilisateur a le rôle
administrator
, l’accès est toujours autorisé. - Vérifie les noms de route : seules certaines routes liées au vocabulaire de taxonomie ou à ses termes sont considérées.
- Redirige les non-admins :
- Pour les routes d’aperçu, d’ajout ou de liste (
entity.taxonomy_vocabulary.overview_form
,entity.taxonomy_vocabulary.overview_terms
,entity.taxonomy_term.add_form
), il vérifie si le vocabulaire esttag
. - Pour les routes de modification et suppression (
entity.taxonomy_term.edit_form
,entity.taxonomy_term.delete_form
), il vérifie si lebundle()
du terme (nom machine du vocabulaire) esttag
.
- Pour les routes d’aperçu, d’ajout ou de liste (
- Utilise une redirection de confiance : si les conditions sont remplies, l’utilisateur est redirigé vers une page d’aperçu sûre pour le vocabulaire « tag ».
- Extensibilité : la logique est facilement extensible pour gérer d’autres vocabulaires ou rôles en ajustant les conditions.
5. Sécurité et bonnes pratiques
- Interception précoce : en s’exécutant lors de l’événement de requête, le subscriber peut appliquer l’accès avant tout traitement ou affichage de données sensibles.
- Contournement basé sur les rôles : vérifie efficacement les rôles utilisateurs pour ne pas bloquer les administrateurs ou constructeurs de site.
- Séparation claire des responsabilités : maintient la logique de routage, les vérifications utilisateur et la redirection bien distinctes pour faciliter la maintenance.
6. Améliorations potentielles
- Puisque
EntityTypeManagerInterface
est injecté, vous pouvez facilement ajouter des contrôles basés sur les entités dans le futur (par exemple, des permissions basées sur des propriétés spécifiques d’un terme ou du contenu lié). - Vous pourriez généraliser la classe pour gérer plusieurs vocabulaires ou fournir des redirections personnalisables via la configuration.
7. Points clés à retenir
- Ce Event Subscriber illustre une approche pratique de contrôle d’accès dans Drupal, tirant parti de l’architecture événementielle de Symfony pour un traitement précoce et efficace des requêtes.
- L’approche est idéale pour protéger des vocabulaires de taxonomie qui doivent être gérés uniquement par des utilisateurs de confiance, réduisant ainsi le risque de modifications accidentelles.