Scroll
Ograničite pristup vokabularu taksonomskih termina pomoću Event Subscriber-a
Ponekad su vam potrebne fiksne, trajne kategorije na sajtu, koje ne bi trebalo slučajno ažurirati. U ovom slučaju možete koristiti sopstveni kod sa Event Subscriber-om.
Dodajmo novu klasu Event Subscriber-a u prilagođeni modul.
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 }
I uključujemo naš Event Subscriber u 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;
/**
* Preusmerava ne-administratore sa administratorskih stranica Tag vokabulara.
*
* Subscriber na nivou Request-a se pokreće rano, što omogućava da se zahtev prekine
* i vrati redirect odgovor pre nego što se izvrši odgovarajući kontroler.
*/
class TagRedirectSubscriber implements EventSubscriberInterface {
/**
* Servis za upravljanje tipovima entiteta.
*
* Ova zavisnost je ovde kao primer; nije striktno potrebna za trenutnu
* logiku ali može biti korisna za buduća proširenja gde je potrebno učitavanje entiteta.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* Proxy servis za trenutnog korisnika.
*
* Koristi se za brzu proveru uloga korisnika kako bi se omogućio prolazak
* administratorima.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected AccountProxyInterface $currentUser;
/**
* Konstruktor subscriber-a.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Servis za tipove entiteta.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* Korisnik koji šalje zahtev.
*/
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 {
// Prioritet 32 osigurava da su parametri rute dostupni, ali se kontroler još nije izvršio.
return [
KernelEvents::REQUEST => ['onKernelRequest', 32],
];
}
/**
* Preusmerava ne-administratore sa administratorskih ruta Tag vokabulara.
*
* @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
* Kernel događaj sa zahtevom.
*/
public function onKernelRequest(RequestEvent $event): void {
// Radi samo na glavnim (master) zahtevima.
if (!$event->isMainRequest()) {
return;
}
// Administratori nisu preusmereni.
if ($this->currentUser->hasRole('administrator')) {
return;
}
$request = $event->getRequest();
$route_name = $request->attributes->get('_route');
// Destinacija za sve pokušaje koji su blokirani.
$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':
// Proveravamo da li se radi o "tag" vokabularu.
$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() vraća mašinsko ime vokabulara.
if ($term && $term->bundle() === 'tag') {
$event->setResponse(new TrustedRedirectResponse($redirect_to));
}
return;
default:
return;
}
}
}
Klasa TagRedirectSubscriber
je prilagođeni Event Subscriber za Drupal, namenjen ograničavanju pristupa administrativnim stranicama određenog taxonomy vokabulara (u ovom slučaju, „tag“) za ne-administratore. Evo pregleda njene strukture i ključnih aspekata u kodu:
1. Svrha i upotreba
- Cilj: Sprečiti slučajne ili neautorizovane izmene „tag“ vokabulara preusmeravanjem ne-admin korisnika sa administratorskih ruta.
- Prednost: Obezbeđuje dodatni sloj UI/UX kontrole pristupa za kritične taxonomy vokabulare, obezbeđujući stabilnost fiksnih kategorija.
2. Struktura klase i zavisnosti
- Klasa implementira
EventSubscriberInterface
, što je čini kompatibilnom sa Symfony event sistemom koji koristi Drupal. - Zavisnosti se ubrizgavaju kroz konstruktor:
EntityTypeManagerInterface
: Uključeno radi potencijalnih budućih operacija nad entitetima. Nije neophodno za trenutnu logiku, ali omogućava lako proširenje.AccountProxyInterface
: Koristi se za efikasno dobijanje i proveru uloga trenutnog korisnika.
3. Subscribovani događaji
- Klasa se pretplaćuje na
KernelEvents::REQUEST
događaj sa prioritetom 32.
Ovaj prioritet obezbeđuje:- Parametri rute su dostupni (routing je rešen).
- Kontroler za rutu još NIJE izvršen, što omogućava subscriber-u da presretne i prekine zahtev redirect-om po potrebi.
4. Logika preusmeravanja
- Metod
onKernelRequest()
sprovodi sve provere pristupa i logiku preusmeravanja:- Radi samo na glavnim zahtevima: Izbegava višestruko procesiranje kod pod-zahteva.
- Dozvoljava administratore: Ako korisnik ima ulogu
administrator
, pristup je uvek dozvoljen. - Proverava imena ruta: Samo određene rute vezane za taxonomy vokabular ili njegove termine se obrađuju.
- Preusmerava ne-admine:
- Za overview, add ili list rute (
entity.taxonomy_vocabulary.overview_form
,entity.taxonomy_vocabulary.overview_terms
,entity.taxonomy_term.add_form
) proverava da li je vokabulartag
. - Za edit i delete rute (
entity.taxonomy_term.edit_form
,entity.taxonomy_term.delete_form
) proverava da li jebundle()
terminatag
.
- Za overview, add ili list rute (
- Koristi trusted redirect: Ako su uslovi zadovoljeni, korisnik se preusmerava na sigurnu administratorsku stranicu pregleda za "tag" vokabular.
- Mogućnost proširenja: Logika se lako može proširiti na dodatne vokabulare ili uloge jednostavnom izmenom uslova.
5. Bezbednost i najbolje prakse
- Rano presretanje: Pokretanjem na request događaj, subscriber može da sprovede proveru pristupa pre nego što bilo koji osetljivi podaci budu procesirani ili prikazani.
- Role-based bypass: Efikasno proverava uloge korisnika kako ne bi blokirao rad site buildera ili administratora.
- Jasna separacija odgovornosti: Logika rutiranja, korisničke provere i preusmeravanja su jasno razdvojene radi održavanja.
6. Moguća poboljšanja
- Pošto je
EntityTypeManagerInterface
ubrizgan, lako možete dodati provere bazirane na entitetima u budućnosti (npr. dozvole bazirane na specifičnim osobinama termina ili povezanim sadržajima). - Klasa se može generalizovati da podržava više vokabulara ili da omogućava podešavanje preusmeravanja putem konfiguracije.
7. Ključne napomene
- Ovaj Event Subscriber predstavlja praktičan način za kontrolu pristupa u Drupalu, koristeći Symfony event-driven arhitekturu za ranu i efikasnu obradu zahteva.
- Pristup je idealan za zaštitu taxonomy vokabulara kojima bi trebalo da upravljaju samo pouzdani korisnici, čime se smanjuje rizik od slučajnih promena.