diff --git a/embargoes.module b/embargoes.module index 34bb8a8..ce9366c 100644 --- a/embargoes.module +++ b/embargoes.module @@ -8,6 +8,7 @@ use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\embargoes\Access\EmbargoesFileAccessHandler; use Drupal\node\NodeInterface; /** @@ -45,6 +46,31 @@ function embargoes_media_view(array &$build, EntityInterface $media, EntityViewD \Drupal::service('embargoes.media_access')->setEmbargoMessage($media); } +/** + * Implements hook_entity_type_alter(). + */ +function embargoes_entity_type_alter(array &$entity_types) { + if (isset($entity_types['file'])) { + $entity_types['file']->setHandlerClass('access', EmbargoesFileAccessHandler::class); + } +} + +/** + * Implemens hook_file_download(). + */ +function embargoes_file_download($uri) { + $files = \Drupal::entityTypeManager() + ->getStorage('file') + ->loadByProperties(['uri' => $uri]); + $file = reset($files); + if ($file instanceof EntityInterface) { + $access = \Drupal::service('embargoes.file_access')->isActivelyEmbargoed($file, \Drupal::currentUser()); + if ($access->isForbidden()) { + return -1; + } + } +} + /** * Implements hook_theme(). */ diff --git a/src/Access/EmbargoedFileAccess.php b/src/Access/EmbargoedFileAccess.php index 0f92632..08a855f 100644 --- a/src/Access/EmbargoedFileAccess.php +++ b/src/Access/EmbargoedFileAccess.php @@ -24,8 +24,8 @@ public static function entityType() { public function isActivelyEmbargoed(EntityInterface $file, AccountInterface $user) { $state = parent::isActivelyEmbargoed($file, $user); $parent_nodes = $this->embargoes->getParentNidsOfFileEntity($file); - $embargoes = $this->embargoes->getActiveNodeEmbargoesByNids($parent_nodes, $this->request->getClientIp(), $user); - if (!empty($embargoes) && empty($this->embargoes->getIpAllowedEmbargoes($embargoes))) { + $embargoes = $this->embargoes->getActiveEmbargoesByNids($parent_nodes, $this->request->getClientIp(), $user); + if (!empty($embargoes)) { $state = AccessResult::forbidden(); $state->addCacheableDependency($file); $state->addCacheableDependency($user); diff --git a/src/Access/EmbargoesFileAccessHandler.php b/src/Access/EmbargoesFileAccessHandler.php new file mode 100644 index 0000000..5c6ca9c --- /dev/null +++ b/src/Access/EmbargoesFileAccessHandler.php @@ -0,0 +1,25 @@ +isActivelyEmbargoed($entity, $account); + if ($embargoed->isForbidden()) { + return $embargoed; + } + return parent::checkAccess($entity, $operation, $account); + } + +} diff --git a/src/EmbargoesEmbargoesService.php b/src/EmbargoesEmbargoesService.php index ab25383..ee5d331 100644 --- a/src/EmbargoesEmbargoesService.php +++ b/src/EmbargoesEmbargoesService.php @@ -5,7 +5,9 @@ use Drupal\embargoes\Entity\EmbargoesEmbargoEntityInterface; use Drupal\file\FileInterface; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityFieldManagerInterface; +use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslationInterface; @@ -112,7 +114,7 @@ public function getIpAllowedCurrentEmbargoesByNids(array $nids) { $embargo = $this->entityManager ->getStorage('embargoes_embargo_entity') ->load($embargo_id); - if (!is_null($embargo->getExemptIps())) { + if (!empty($embargo->getExemptIps())) { $ip_allowed_current_embargoes[$embargo_id] = $embargo_id; } } @@ -177,7 +179,7 @@ public function getIpAllowedEmbargoes(array $embargoes) { $embargo = $this->entityManager ->getStorage('embargoes_embargo_entity') ->load($embargo_id); - if (!is_null($embargo->getExemptIps())) { + if (!empty($embargo->getExemptIps())) { $ip_allowed_embargoes[$embargo_id] = $embargo->getExemptIps(); } } @@ -285,7 +287,9 @@ public function getMediaParentNids($mid) { * {@inheritdoc} */ public function getParentNidsOfFileEntity(FileInterface $file) { - $relationships = file_get_file_references($file); + $relationships = NestedArray::mergeDeep( + file_get_file_references($file), + file_get_file_references($file, NULL, EntityStorageInterface::FIELD_LOAD_REVISION, 'image')); if (!$relationships) { $nids = []; } diff --git a/src/EventSubscriber/IpRedirectAttacher.php b/src/EventSubscriber/IpRedirectAttacher.php index a22b8dd..79a6df8 100644 --- a/src/EventSubscriber/IpRedirectAttacher.php +++ b/src/EventSubscriber/IpRedirectAttacher.php @@ -3,8 +3,10 @@ namespace Drupal\embargoes\EventSubscriber; use Drupal\embargoes\Access\EmbargoedAccessInterface; +use Drupal\file\FileInterface; +use Drupal\node\NodeInterface; +use Drupal\media\MediaInterface; use Drupal\Core\Session\AccountInterface; -use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\KernelEvents; @@ -60,27 +62,21 @@ public function __construct(EmbargoedAccessInterface $node_access, EmbargoedAcce * The initial response. */ public function attachIpRedirect(GetResponseEvent $response) { - $route_name = $response->getRequest()->attributes->get(RouteObjectInterface::ROUTE_NAME); $redirect_url = NULL; - // Redirect for nodes. - if (substr($route_name, 0, 11) == 'entity.node') { - $node = $response->getRequest()->attributes->get('node'); - if ($node) { - $redirect_url = $this->nodeAccess->getIpEmbargoedRedirectUrl($node, $this->user); + // Cycle through all attributes; the first one we get back that's restricted + // means redirection is necessary. + foreach ($response->getRequest()->attributes->all() as $attribute) { + if ($attribute instanceof NodeInterface) { + $redirect_url = $this->nodeAccess->getIpEmbargoedRedirectUrl($attribute, $this->user); + break; } - } - // Redirect for media. - elseif (substr($route_name, 0, 12) == 'entity.media') { - $media = $response->getRequest()->attributes->get('media'); - if ($media) { - $redirect_url = $this->mediaAccess->getIpEmbargoedRedirectUrl($media, $this->user); + if ($attribute instanceof MediaInterface) { + $redirect_url = $this->mediaAccess->getIpEmbargoedRedirectUrl($attribute, $this->user); + break; } - } - // Redirect for files. - elseif (substr($route_name, 0, 11) == 'entity.file') { - $file = $response->getRequest()->attributes->get('file'); - if ($file) { - $redirect_url = $this->fileAccess->getIpEmbargoedRedirectUrl($file, $this->user); + if ($attribute instanceof FileInterface) { + $redirect_url = $this->fileAccess->getIpEmbargoedRedirectUrl($attribute, $this->user); + break; } } if ($redirect_url) { diff --git a/src/Form/EmbargoesEmbargoEntityForm.php b/src/Form/EmbargoesEmbargoEntityForm.php index 455e293..ddc75a6 100644 --- a/src/Form/EmbargoesEmbargoEntityForm.php +++ b/src/Form/EmbargoesEmbargoEntityForm.php @@ -8,6 +8,7 @@ use Drupal\Component\Uuid\UuidInterface; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Messenger\MessengerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -36,6 +37,13 @@ class EmbargoesEmbargoEntityForm extends EntityForm { */ protected $uuidGenerator; + /** + * Messaging interface. + * + * @var \Drupal\Core\Messenger\MessengerInterface + */ + protected $messenger; + /** * Embargoes service. * @@ -52,13 +60,16 @@ class EmbargoesEmbargoEntityForm extends EntityForm { * An embargoes logging service. * @param \Drupal\Component\Uuid\UuidInterface $uuid_generator * A UUID generator. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * Messaging interface. * @param \Drupal\embargoes\EmbargoesEmbargoesServiceInterface $embargoes_service * An embargoes service. */ - public function __construct(EmbargoesIpRangesServiceInterface $ip_ranges, EmbargoesLogServiceInterface $embargoes_log, UuidInterface $uuid_generator, EmbargoesEmbargoesServiceInterface $embargoes_service) { + public function __construct(EmbargoesIpRangesServiceInterface $ip_ranges, EmbargoesLogServiceInterface $embargoes_log, UuidInterface $uuid_generator, MessengerInterface $messenger, EmbargoesEmbargoesServiceInterface $embargoes_service) { $this->ipRanges = $ip_ranges; $this->embargoesLog = $embargoes_log; $this->uuidGenerator = $uuid_generator; + $this->messenger = $messenger; $this->embargoes = $embargoes_service; } @@ -70,6 +81,7 @@ public static function create(ContainerInterface $container) { $container->get('embargoes.ips'), $container->get('embargoes.log'), $container->get('uuid'), + $container->get('messenger'), $container->get('embargoes.embargoes')); } @@ -96,7 +108,7 @@ public function form(array $form, FormStateInterface $form_state) { ], ]; - $form['expiration_type'] = [ + $form['expiry_type'] = [ '#type' => 'radios', '#title' => $this->t('Expiration type'), '#default_value' => $embargo->getExpirationTypeAsInt(), @@ -177,7 +189,7 @@ public function form(array $form, FormStateInterface $form_state) { public function save(array $form, FormStateInterface $form_state) { $embargo = $this->entity; $embargo->setEmbargoType($form_state->getValue('embargo_type')); - $embargo->setExpirationType($form_state->getValue('expiration_type')); + $embargo->setExpirationType($form_state->getValue('expiry_type')); $embargo->setExpirationDate($form_state->getValue('expiration_date')); $embargo->setExemptIps($form_state->getValue('exempt_ips')); $embargo->setExemptUsers($form_state->getValue('exempt_users'));