diff --git a/core/modules/rest/rest.services.yml b/core/modules/rest/rest.services.yml index 43a8359..81a281c 100644 --- a/core/modules/rest/rest.services.yml +++ b/core/modules/rest/rest.services.yml @@ -29,6 +29,6 @@ services: - { name: 'event_subscriber' } rest.options_subscriber: class: Drupal\rest\Routing\OptionsRequestSubscriber + arguments: ['@access_manager', '@current_user'] tags: - {name: event_subscriber} - diff --git a/core/modules/rest/src/Routing/OptionsRequestSubscriber.php b/core/modules/rest/src/Routing/OptionsRequestSubscriber.php index e60e3e8..4539247 100644 --- a/core/modules/rest/src/Routing/OptionsRequestSubscriber.php +++ b/core/modules/rest/src/Routing/OptionsRequestSubscriber.php @@ -7,6 +7,9 @@ namespace Drupal\rest\Routing; +use Drupal\Core\Access\AccessManager; +use Drupal\Core\Session\AccountInterface; +use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -19,12 +22,53 @@ class OptionsRequestSubscriber implements EventSubscriberInterface { /** + * The access manager. + * + * @var \Drupal\Core\Access\AccessManager + */ + protected $accessManager; + + /** + * The current user account. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $account; + + /** + * The http methods that are available to check. + * + * @var string[] + */ + protected $availableMethods = array( + 'GET', + 'POST', + 'PUT', + 'DELETE', + 'HEAD', + 'PATCH', + ); + + /** + * Constructs an options request subscriber. + * + * @param \Drupal\Core\Access\AccessManager $access_manager + * The access manager. + * @param \Drupal\Core\Session\AccountInterface $account + * The current user account. + */ + public function __construct(AccessManager $access_manager, AccountInterface $account) { + $this->accessManager = $access_manager; + $this->account = $account; + } + + /** * Handles OPTIONS requests. */ public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); if ($request->getMethod() == 'OPTIONS') { - $allowed_methods = $this->getAllowedMethods($request); + $allowed_methods = implode(' ', $this->getAllowedMethods($request)); $response = new Response(NULL, 200, array('Allow' => $allowed_methods)); $event->setResponse($response); } @@ -34,15 +78,24 @@ public function onKernelRequest(GetResponseEvent $event) { * Check which methods are allowed for the current request. */ protected function getAllowedMethods(Request $request) { - // @todo actually check access. - return 'OPTIONS GET HEAD PUT POST DELETE'; + $allow = array(); + $route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT); + if (isset($route)) { + foreach ($this->availableMethods as $method) { + $request->setMethod($method); + if ($this->accessManager->check($route, $request, $this->account)) { + $allow[] = $method; + } + } + } + return $allow; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { - return array(KernelEvents::REQUEST => array(array('onKernelRequest', 33))); + return array(KernelEvents::REQUEST => array(array('onKernelRequest', -10000))); } }