Browse Source

More flexible headers for STOMP messages, theoretically.

pull/839/head
Adam Vessey 4 years ago
parent
commit
1d96fa8af1
  1. 5
      islandora.services.yml
  2. 67
      src/Event/StompHeaderEvent.php
  3. 8
      src/Event/StompHeaderEventException.php
  4. 40
      src/Event/StompHeaderEventInterface.php
  5. 45
      src/EventGenerator/EmitEvent.php
  6. 61
      src/EventSubscriber/StompHeaderSubscriber.php
  7. 6
      src/Plugin/Action/AbstractGenerateDerivative.php
  8. 74
      src/Plugin/Action/EmitFileEvent.php
  9. 80
      src/Plugin/Action/EmitMediaEvent.php

5
islandora.services.yml

@ -54,3 +54,8 @@ services:
arguments: ['@entity_type.manager', '@entity_field.manager', '@context.manager', '@flysystem_factory', '@language_manager']
islandora.entity_mapper:
class: Islandora\Crayfish\Commons\EntityMapper\EntityMapper
islandora.stomp.auth_header_listener:
class: Drupal\islandora\EventSubscriber\StompHeaderEventSubscriber
arguments: ['@jwt.authentication.jwt']
tags:
- { name: event_subscriber }

67
src/Event/StompHeaderEvent.php

@ -0,0 +1,67 @@
<?php
namespace Drupal\islandora\Event;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\EventDispatcher\Event;
/**
* Event used to build headers for STOMP.
*/
class StompHeaderEvent implements StompHeaderEventInterface {
/**
* Stashed entity, for context.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
protected $entity;
/**
* Stashed user info, for context.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $user;
/**
* The set of headers.
*
* @var \Symfony\Component\HttpFoundation\ParameterBag
*/
protected $headers;
/**
* Constructor.
*/
public function __construct(EntityInterface $entity, AccountInterface $user) {
$this->entity = $entity;
$this->user = $user;
$this->headers = new ParameterBag();
}
/**
* {@inheritdoc}
*/
public function getEntity() {
return $this->entity;
}
/**
* {@inheritdoc}
*/
public function getUser() {
return $this->user;
}
/**
* {@inheritdoc}
*/
public function getHeaders() {
return $this->headers;
}
}

8
src/Event/StompHeaderEventException.php

@ -0,0 +1,8 @@
<?php
namespace Drupal\islandora\Event;
/**
* Typification for handling exceptions specific to STOMP header generation.
*/
class StompHeaderEventException extends \Exception {}

40
src/Event/StompHeaderEventInterface.php

@ -0,0 +1,40 @@
<?php
namespace Drupal\islandora\Event;
/**
* Contract for representing an event to build headers for STOMP messages.
*/
interface StompHeaderEventInterface {
const EVENT_NAME = 'islandora.stomp.header_event';
/**
* Get the headers being built for STOMP.
*
* XXX: Ironically, using ParameterBag instead of HeaderBag due to case-
* sensitivity: In the context of HTTP, headers are case insensitive (and is
* what HeaderBag is intended; however, STOMP headers are case sensitive.
*
* @return \Symfony\Component\HttpFoundation\ParameterBag
* The headers
*/
public function getHeaders();
/**
* Fetch the entity provided as context.
*
* @return \Drupal\Core\Entity\EntityInterface
* The entity provided as context.
*/
public function getEntity();
/**
* Fetch the user provided as context.
*
* @return \Drupal\Core\Session\AccountInterface
* The user provided as context.
*/
public function getUser();
}

45
src/EventGenerator/EmitEvent.php

@ -11,7 +11,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\jwt\Authentication\Provider\JwtAuth;
use Drupal\islandora\Event\StompHeaderEventException;
use Stomp\Exception\StompException;
use Stomp\StatefulStomp;
use Stomp\Transport\Message;
@ -52,11 +52,11 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact
protected $stomp;
/**
* The JWT Auth Service.
* Event dispatcher service..
*
* @var \Drupal\jwt\Authentication\Provider\JwtAuth
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $auth;
protected $eventDispatcher;
/**
* The messenger.
@ -95,16 +95,16 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact
EntityTypeManagerInterface $entity_type_manager,
EventGeneratorInterface $event_generator,
StatefulStomp $stomp,
JwtAuth $auth,
MessengerInterface $messenger
MessengerInterface $messenger,
EventDispatcherInterface $event_dispatcher
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->account = $account;
$this->entityTypeManager = $entity_type_manager;
$this->eventGenerator = $event_generator;
$this->stomp = $stomp;
$this->auth = $auth;
$this->messenger = $messenger;
$this->eventDispatcher = $event_dispatcher;
}
/**
@ -119,8 +119,8 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact
$container->get('entity_type.manager'),
$container->get('islandora.eventgenerator'),
$container->get('islandora.stomp'),
$container->get('jwt.authentication.jwt'),
$container->get('messenger')
$container->get('messenger'),
$container->get('event_dispatcher')
);
}
@ -128,29 +128,26 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact
* {@inheritdoc}
*/
public function execute($entity = NULL) {
// Include a token for later authentication in the message.
$token = $this->auth->generateToken();
if (empty($token)) {
// JWT isn't properly configured. Log and notify user.
\Drupal::logger('islandora')->error(
$this->t('Error getting JWT token for message. Check JWT Configuration.')
);
$this->messenger->addMessage(
$this->t('Error getting JWT token for message. Check JWT Configuration.'), 'error'
);
return;
}
// Generate event as stomp message.
try {
$user = $this->entityTypeManager->getStorage('user')->load($this->account->id());
$data = $this->generateData($entity);
$event = $this->eventDispatcher->dispatch(
StompHeaderEvent::EVENT_NAME,
new StompHeaderEvent($entity, $user)
);
$message = new Message(
$this->eventGenerator->generateEvent($entity, $user, $data),
['Authorization' => "Bearer $token"]
$event->getHeaders()->all()
);
}
catch (StompHeaderEventException $e) {
\Drupal::logger('islandora')->error($e->getMessage());
$this->messenger->addMessage($e->getMessage(), 'error');
return;
}
catch (\RuntimeException $e) {
// Notify the user the event couldn't be generated and abort.
\Drupal::logger('islandora')->error(

61
src/EventSubscriber/StompHeaderSubscriber.php

@ -0,0 +1,61 @@
<?php
namespace Drupal\islandora\EventSubscriber;
use Drupal\islandora\Event\StompHeaderEventInterface;
use Drupal\jwt\Authentication\Provider\JwtAuth;
use Drupal\Core\Messenger\MessengerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Base STOMP header listener.
*/
class StompHeaderEventSubscriber implements EventSubscriberInterface {
/**
* The JWT auth service.
*
* @var \Drupal\jwt\Authentication\Provider\JwtAuth
*/
protected $auth;
/**
* Constructor.
*/
public function __construct(
JwtAuth $auth
) {
$this->auth = $auth;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
StompHeaderEventInterface::EVENT_NAME => 'baseAuth',
];
}
/**
* Event callback; generate and add base authorization header if none is set.
*/
public function baseAuth(StompHeaderEventInterface $stomp_event) {
$headers = $stomp_event->getHeaders();
if (!$headers->has('Authorization')) {
$token = $this->auth->generateToken();
if (empty($token)) {
// JWT does not seem to be properly configured.
// phpcs:ignore DrupalPractice.General.ExceptionT.ExceptionT
throw new StompHeaderEventException($this->t('Error getting JWT token for message. Check JWT Configuration.'));
}
else {
$headers->set('Authorization', "Bearer $token");
}
}
}
}

6
src/Plugin/Action/AbstractGenerateDerivative.php

@ -2,9 +2,15 @@
namespace Drupal\islandora\Plugin\Action;
use Drupal\islandora\EventGenerator\EmitEvent;
use Drupal\islandora\IslandoraUtils;
use Drupal\islandora\MediaSource\MediaSourceService;
use Drupal\token\TokenInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Emits a Node event.

74
src/Plugin/Action/EmitFileEvent.php

@ -2,17 +2,11 @@
namespace Drupal\islandora\Plugin\Action;
use Drupal\islandora\EventGenerator\EmitEvent;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\StreamWrapperManager;
use Drupal\jwt\Authentication\Provider\JwtAuth;
use Drupal\islandora\EventGenerator\EmitEvent;
use Drupal\islandora\EventGenerator\EventGeneratorInterface;
use Stomp\StatefulStomp;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@ -34,52 +28,9 @@ class EmitFileEvent extends EmitEvent {
protected $fileSystem;
/**
* Constructs a EmitEvent action.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Session\AccountInterface $account
* Current user.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Entity type manager.
* @param \Drupal\islandora\EventGenerator\EventGeneratorInterface $event_generator
* EventGenerator service to serialize AS2 events.
* @param \Stomp\StatefulStomp $stomp
* Stomp client.
* @param \Drupal\jwt\Authentication\Provider\JwtAuth $auth
* JWT Auth client.
* @param \Drupal\Core\File\FileSystemInterface $file_system
* File system service.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
* Setter for the file system service.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
AccountInterface $account,
EntityTypeManagerInterface $entity_type_manager,
EventGeneratorInterface $event_generator,
StatefulStomp $stomp,
JwtAuth $auth,
FileSystemInterface $file_system,
MessengerInterface $messenger
) {
parent::__construct(
$configuration,
$plugin_id,
$plugin_definition,
$account,
$entity_type_manager,
$event_generator,
$stomp,
$auth,
$messenger
);
public function setFileSystemService(FileSystemInterface $file_system) {
$this->fileSystem = $file_system;
}
@ -87,18 +38,11 @@ class EmitFileEvent extends EmitEvent {
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_user'),
$container->get('entity_type.manager'),
$container->get('islandora.eventgenerator'),
$container->get('islandora.stomp'),
$container->get('jwt.authentication.jwt'),
$container->get('file_system'),
$container->get('messenger')
);
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->setFileSystemService($container->get('file_system'));
return $instance;
}
/**

80
src/Plugin/Action/EmitMediaEvent.php

@ -3,14 +3,8 @@
namespace Drupal\islandora\Plugin\Action;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\jwt\Authentication\Provider\JwtAuth;
use Drupal\islandora\EventGenerator\EmitEvent;
use Drupal\islandora\EventGenerator\EventGeneratorInterface;
use Drupal\islandora\MediaSource\MediaSourceService;
use Stomp\StatefulStomp;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@ -31,72 +25,15 @@ class EmitMediaEvent extends EmitEvent {
*/
protected $mediaSource;
/**
* Constructs a EmitEvent action.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Session\AccountInterface $account
* Current user.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Entity type manager.
* @param \Drupal\islandora\EventGenerator\EventGeneratorInterface $event_generator
* EventGenerator service to serialize AS2 events.
* @param \Stomp\StatefulStomp $stomp
* Stomp client.
* @param \Drupal\jwt\Authentication\Provider\JwtAuth $auth
* JWT Auth client.
* @param \Drupal\islandora\MediaSource\MediaSourceService $media_source
* Media source service.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
AccountInterface $account,
EntityTypeManagerInterface $entity_type_manager,
EventGeneratorInterface $event_generator,
StatefulStomp $stomp,
JwtAuth $auth,
MediaSourceService $media_source,
MessengerInterface $messenger
) {
parent::__construct(
$configuration,
$plugin_id,
$plugin_definition,
$account,
$entity_type_manager,
$event_generator,
$stomp,
$auth,
$messenger
);
$this->mediaSource = $media_source;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_user'),
$container->get('entity_type.manager'),
$container->get('islandora.eventgenerator'),
$container->get('islandora.stomp'),
$container->get('jwt.authentication.jwt'),
$container->get('islandora.media_source_service'),
$container->get('messenger')
);
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->setMediaSourceService($container->get('islandora.media_source_service'));
return $instance;
}
/**
@ -108,4 +45,11 @@ class EmitMediaEvent extends EmitEvent {
return $data;
}
/**
* Setter for the media source service.
*/
public function setMediaSourceService(MediaSourceService $media_source) {
$this->mediaSource = $media_source;
}
}

Loading…
Cancel
Save