3 namespace Drupal\permissions_by_entity\EventSubscriber;
5 use Drupal\Core\Entity\FieldableEntityInterface;
6 use Drupal\Core\StringTranslation\TranslationInterface;
7 use Drupal\permissions_by_entity\Service\AccessCheckerInterface;
8 use Drupal\permissions_by_entity\Service\CheckedEntityCache;
9 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
11 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
12 use Symfony\Component\HttpKernel\KernelEvents;
15 * Class PermissionsByEntityKernelEventSubscriber.
17 * @package Drupal\permissions_by_entity\EventSubscriber
19 class PermissionsByEntityKernelEventSubscriber implements EventSubscriberInterface {
24 * @var \Drupal\permissions_by_entity\Service\AccessCheckerInterface
26 private $accessChecker;
29 * The core string translator.
31 * @var \Drupal\Core\StringTranslation\TranslationInterface
36 * The cache for checked entities.
38 * @var \Drupal\permissions_by_entity\Service\CheckedEntityCache
40 private $checkedEntityCache;
43 * PermissionsByEntityKernelEventSubscriber constructor.
45 * @param \Drupal\permissions_by_entity\Service\AccessCheckerInterface $access_checker
46 * The service to check if the current user is allowed to access an entity.
47 * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
48 * The core string translator.
49 * @param \Drupal\permissions_by_entity\Service\CheckedEntityCache $checked_entity_cache
50 * The cache for checked entities.
52 public function __construct(
53 AccessCheckerInterface $access_checker,
54 TranslationInterface $translation,
55 CheckedEntityCache $checked_entity_cache
57 $this->accessChecker = $access_checker;
58 $this->translation = $translation;
59 $this->checkedEntityCache = $checked_entity_cache;
65 * @see DynamicPageCacheSubscriber
67 * This is required to run before the DynamicPageCacheSubscriber as otherwise
68 * the response would be cached which can lead to false access.
70 public static function getSubscribedEvents() {
72 KernelEvents::REQUEST => ['onKernelRequest', 28],
77 * Callback method for the KernelEvents::REQUEST event.
79 * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
82 public function onKernelRequest(GetResponseEvent $event) {
83 // Get the current request from the event.
84 $request = $event->getRequest();
87 /** @var \Drupal\Core\Entity\FieldableEntityInterface $entity */
89 if ($request->attributes->has('node')) {
90 $entity = $request->attributes->get('node');
92 elseif ($request->attributes->has('_entity')) {
93 $entity = $request->attributes->get('_entity');
96 // If there is no entity abort here.
97 if (!$entity instanceof FieldableEntityInterface) {
101 // If we already checked this entity, we do nothing.
102 if ($this->checkedEntityCache->isChecked($entity)) {
106 // Add this entity to the cache.
107 $this->checkedEntityCache->add($entity);
109 // Check if the current user is allowed to access this entity.
111 $entity && $entity instanceof FieldableEntityInterface &&
112 !$this->accessChecker->isAccessAllowed($entity)
115 // If the current user is not allowed to access this entity,
116 // we throw an AccessDeniedHttpException.
117 throw new AccessDeniedHttpException(
118 $this->translation->translate(
119 'You are not allowed to view content of this entity type.'