diff --git a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php index 62f5486..be3f55e 100644 --- a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php @@ -96,7 +96,7 @@ public function onKernelRequestFilterProvider(GetResponseEvent $event) { if (isset($this->filter) && $event->getRequestType() === HttpKernelInterface::MASTER_REQUEST) { $request = $event->getRequest(); if ($this->authenticationProvider->applies($request) && !$this->filter->appliesToRoutedRequest($request, TRUE)) { - throw new AccessDeniedHttpException(); + throw new AccessDeniedHttpException('The used authentication method is not allowed on this route.'); } } } diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php index a5cb361..4b7854f 100644 --- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php @@ -106,7 +106,7 @@ public static function create(ContainerInterface $container, array $configuratio public function get(EntityInterface $entity) { $entity_access = $entity->access('view', NULL, TRUE); if (!$entity_access->isAllowed()) { - throw new AccessDeniedHttpException(); + throw new AccessDeniedHttpException($this->accessDeniedExceptionMessage($entity, "view")); } $response = new ResourceResponse($entity, 200); @@ -145,7 +145,7 @@ public function post(EntityInterface $entity = NULL) { } if (!$entity->access('create')) { - throw new AccessDeniedHttpException(); + throw new AccessDeniedHttpException($this->accessDeniedExceptionMessage($entity, "create")); } $definition = $this->getPluginDefinition(); // Verify that the deserialized entity is of the type that we expect to @@ -200,7 +200,7 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity throw new BadRequestHttpException('Invalid entity type'); } if (!$original_entity->access('update')) { - throw new AccessDeniedHttpException(); + throw new AccessDeniedHttpException($this->accessDeniedExceptionMessage($entity, "update")); } // Overwrite the received properties. @@ -264,7 +264,7 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity */ public function delete(EntityInterface $entity) { if (!$entity->access('delete')) { - throw new AccessDeniedHttpException(); + throw new AccessDeniedHttpException($this->accessDeniedExceptionMessage($entity, "delete")); } try { $entity->delete(); @@ -278,6 +278,27 @@ public function delete(EntityInterface $entity) { } } + + /** + * Return the proper message checking if the entity is bundleable. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity object. + * + * @param string + * The action executed before to call the exception. + * @return string + * The proper message to display in the AccessDeniedHttpException. + */ + public function accessDeniedExceptionMessage(EntityInterface $entity, $action) { + $message = "You are not authorized to {$action} this {$entity->getEntityTypeId()} entity"; + + if ($entity->bundle() !== $entity->getEntityTypeId()) { + $message .= " of bundle {$entity->bundle()}"; + } + return "{$message}."; + } + /** * {@inheritdoc} */ diff --git a/core/modules/rest/tests/src/Functional/CookieResourceTestTrait.php b/core/modules/rest/tests/src/Functional/CookieResourceTestTrait.php index 18dc296..c187b65 100644 --- a/core/modules/rest/tests/src/Functional/CookieResourceTestTrait.php +++ b/core/modules/rest/tests/src/Functional/CookieResourceTestTrait.php @@ -92,7 +92,9 @@ protected function getAuthenticationRequestOptions($method) { * {@inheritdoc} */ protected function assertResponseWhenMissingAuthentication(ResponseInterface $response) { - $this->assertResourceErrorResponse(403, '', $response); + // Requests needing cookie authentication but missing it results in a 403 + // response. The cookie authentication mechanism sets no response message. + $this->assertResourceErrorResponse(403, FALSE, $response); } /** diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index e154a75..5418d46 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -339,8 +339,7 @@ public function testGet() { // DX: 403 when unauthorized. $response = $this->request('GET', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. - $this->assertResourceErrorResponse(403, '', $response); + $this->assertResourceErrorResponse(403, "You are not authorized to view this {$this->entity->getEntityTypeId()} entity" . (($this->entity->bundle() !== $this->entity->getEntityTypeId()) ? " of bundle {$this->entity->bundle()}." : "."), $response); $this->setUpAuthorization('GET'); @@ -401,7 +400,8 @@ public function testGet() { // DX: 403 when unauthorized. $response = $this->request('GET', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. + // In case we have a BC layer, permissions are used, which don't have a good + // error message. $this->assertResourceErrorResponse(403, '', $response); @@ -556,8 +556,7 @@ public function testPost() { // DX: 403 when unauthorized. $response = $this->request('POST', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. - $this->assertResourceErrorResponse(403, '', $response); + $this->assertResourceErrorResponse(403, "You are not authorized to create this {$this->entity->getEntityTypeId()} entity" . (($this->entity->bundle() !== $this->entity->getEntityTypeId()) ? " of bundle {$this->entity->bundle()}." : "."), $response); $this->setUpAuthorization('POST'); @@ -624,7 +623,8 @@ public function testPost() { // DX: 403 when unauthorized. $response = $this->request('POST', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. + // In case we have a BC layer, permissions are used, which don't have a good + // error message. $this->assertResourceErrorResponse(403, '', $response); @@ -748,8 +748,7 @@ public function testPatch() { // DX: 403 when unauthorized. $response = $this->request('PATCH', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. - $this->assertResourceErrorResponse(403, '', $response); + $this->assertResourceErrorResponse(403, "You are not authorized to update this {$this->entity->getEntityTypeId()} entity" . (($this->entity->bundle() !== $this->entity->getEntityTypeId()) ? " of bundle {$this->entity->bundle()}." : "."), $response); $this->setUpAuthorization('PATCH'); @@ -831,7 +830,8 @@ public function testPatch() { // DX: 403 when unauthorized. $response = $this->request('PATCH', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. + // In case we have a BC layer, permissions are used, which don't have a good + // error message. $this->assertResourceErrorResponse(403, '', $response); @@ -901,8 +901,7 @@ public function testDelete() { // DX: 403 when unauthorized. $response = $this->request('DELETE', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. - $this->assertResourceErrorResponse(403, '', $response); + $this->assertResourceErrorResponse(403, "You are not authorized to delete this {$this->entity->getEntityTypeId()} entity" . (($this->entity->bundle() !== $this->entity->getEntityTypeId()) ? " of bundle {$this->entity->bundle()}." : "."), $response); $this->setUpAuthorization('DELETE'); @@ -931,7 +930,8 @@ public function testDelete() { // DX: 403 when unauthorized. $response = $this->request('DELETE', $url, $request_options); - // @todo Update the message in https://www.drupal.org/node/2808233. + // In case we have a BC layer, permissions are used, which don't have a good + // error message. $this->assertResourceErrorResponse(403, '', $response); diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php index 218e96f..6a3874b 100644 --- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php @@ -321,7 +321,7 @@ protected function assertResourceResponse($expected_status_code, $expected_body, * The error response to assert. */ protected function assertResourceErrorResponse($expected_status_code, $expected_message, ResponseInterface $response) { - $expected_body = $this->serializer->encode(['message' => $expected_message], static::$format); + $expected_body = ($expected_message !== FALSE) ? $this->serializer->encode(['message' => $expected_message], static::$format) : FALSE; $this->assertResourceResponse($expected_status_code, $expected_body, $response); }