Unverified Commit d84f620c authored by alexpott's avatar alexpott

Issue #3171827 by mohit_aghera, ankithashetty, jmeijer, jibran:...

Issue #3171827 by mohit_aghera, ankithashetty, jmeijer, jibran: RouteNotFoundException: Route "jsonapi.[entity].[field_name].related" does not exist
parent 12c6bfe2
......@@ -106,16 +106,18 @@ protected function resolveIncludeTree(array $include_tree, Data $data, Data $inc
// Some objects in the collection may be LabelOnlyResourceObjects or
// EntityAccessDeniedHttpException objects.
assert($resource_object instanceof ResourceIdentifierInterface);
$public_field_name = $resource_object->getResourceType()->getPublicName($field_name);
if ($resource_object instanceof LabelOnlyResourceObject) {
$message = "The current user is not allowed to view this relationship.";
$exception = new EntityAccessDeniedHttpException($resource_object->getEntity(), AccessResult::forbidden("The user only has authorization for the 'view label' operation."), '', $message, $field_name);
$exception = new EntityAccessDeniedHttpException($resource_object->getEntity(), AccessResult::forbidden("The user only has authorization for the 'view label' operation."), '', $message, $public_field_name);
$includes = IncludedData::merge($includes, new IncludedData([$exception]));
continue;
}
elseif (!$resource_object instanceof ResourceObject) {
continue;
}
$public_field_name = $resource_object->getResourceType()->getPublicName($field_name);
// Not all entities in $entity_collection will be of the same bundle and
// may not have all of the same fields. Therefore, calling
// $resource_object->get($a_missing_field_name) will result in an
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\jsonapi\JsonApiResource\ErrorCollection;
use Drupal\jsonapi\JsonApiResource\LabelOnlyResourceObject;
use Drupal\jsonapi\JsonApiResource\LinkCollection;
use Drupal\jsonapi\JsonApiResource\NullIncludedData;
use Drupal\jsonapi\JsonApiResource\ResourceObject;
......@@ -54,6 +55,7 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase {
'file',
'image',
'jsonapi_test_normalizers_kernel',
'jsonapi_test_resource_type_building',
];
/**
......@@ -77,6 +79,13 @@ class JsonApiDocumentTopLevelNormalizerTest extends JsonapiKernelTestBase {
*/
protected $includeResolver;
/**
* The JSON:API resource type repository under test.
*
* @var \Drupal\jsonapi\ResourceType\ResourceTypeRepository
*/
protected $resourceTypeRepository;
/**
* {@inheritdoc}
*/
......@@ -178,6 +187,7 @@ protected function setUp(): void {
])->save();
$this->includeResolver = $this->container->get('jsonapi.include_resolver');
$this->resourceTypeRepository = $this->container->get('jsonapi.resource_type.repository');
}
/**
......@@ -408,6 +418,70 @@ public function testNormalizeException() {
], $normalized['errors'][0]['links']);
}
/**
* Test the message and exceptions thrown when we are requesting additional
* field values for Label only resource.
*/
public function testAliasFieldRouteException() {
$this->assertSame('uid', $this->resourceTypeRepository->getByTypeName('node--article')->getPublicName('uid'));
$this->assertSame('roles', $this->resourceTypeRepository->getByTypeName('user--user')->getPublicName('roles'));
$resource_type_field_aliases = [
'node--article' => [
'uid' => 'author',
],
'user--user' => [
'roles' => 'user_roles',
],
];
\Drupal::state()->set('jsonapi_test_resource_type_builder.resource_type_field_aliases', $resource_type_field_aliases);
Cache::invalidateTags(['jsonapi_resource_types']);
$this->assertSame('author', $this->resourceTypeRepository->getByTypeName('node--article')->getPublicName('uid'));
$this->assertSame('user_roles', $this->resourceTypeRepository->getByTypeName('user--user')->getPublicName('roles'));
// Create the request to fetch the articles and fetch included user.
list($request, $resource_type) = $this->generateProphecies('node', 'article');
$user = User::load($this->node->getOwnerId());
$resource_object = ResourceObject::createFromEntity($resource_type, $this->node);
list($request, $user_resource_type) = $this->generateProphecies('user', 'user');
$resource_object_user = LabelOnlyResourceObject::createFromEntity($user_resource_type, $user);
$includes = $this->includeResolver->resolve($resource_object_user, 'user_roles');
/** @var \Drupal\jsonapi\Normalizer\Value\CacheableNormalization $jsonapi_doc_object */
$jsonapi_doc_object = $this
->getNormalizer()
->normalize(
new JsonApiDocumentTopLevel(new ResourceObjectData([$resource_object, $resource_object_user], 2), $includes, new LinkCollection([])),
'api_json',
[
'resource_type' => $resource_type,
'account' => NULL,
'sparse_fieldset' => [
'node--article' => [
'title',
'node_type',
'uid',
],
'user--user' => [
'user_roles',
],
],
'include' => [
'user_roles',
],
],
)->getNormalization();
$this->assertNotEmpty($jsonapi_doc_object['meta']['omitted']);
foreach ($jsonapi_doc_object['meta']['omitted']['links'] as $key => $link) {
if (strpos($key, 'item--') === 0) {
// Ensure that resource link contains url with the alias field.
$resource_link = Url::fromUri('internal:/jsonapi/user/user/' . $user->uuid() . '/user_roles')->setAbsolute()->toString(TRUE);
$this->assertEquals($resource_link->getGeneratedUrl(), $link['href']);
$this->assertEquals("The current user is not allowed to view this relationship. The user only has authorization for the 'view label' operation.", $link['meta']['detail']);
}
}
}
/**
* @covers ::normalize
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment