diff --git a/composer.json b/composer.json index 970aa03..270bbc8 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,6 @@ "type": "drupal-module", "license": "GPL-2.0+", "require-dev": { - "justinrainbow/json-schema": "^5.2", - "drupal/schemata": "1.x-dev#8325d172e1d6880aa24073f8f751ef089282cf9a" + "justinrainbow/json-schema": "^5.2" } } diff --git a/jsonapi.info.yml b/jsonapi.info.yml index 9e77ac2..a333090 100644 --- a/jsonapi.info.yml +++ b/jsonapi.info.yml @@ -5,5 +5,3 @@ core: 8.x package: Web services dependencies: - drupal:serialization -test_dependencies: - - schemata:schemata_json_schema diff --git a/jsonapi.services.yml b/jsonapi.services.yml index 44309dc..ca8ef22 100644 --- a/jsonapi.services.yml +++ b/jsonapi.services.yml @@ -210,7 +210,6 @@ services: arguments: ['@jsonapi.serializer_do_not_use_removal_imminent', '@logger.channel.jsonapi', '@module_handler', '@app.root'] calls: - [setValidator, []] - - [setSchemaFactory, ['@?schemata.schema_factory']] # This is only injected when the service is available. tags: - { name: event_subscriber, priority: 1000 } diff --git a/src/EventSubscriber/ResourceResponseValidator.php b/src/EventSubscriber/ResourceResponseValidator.php index 6823498..af306dd 100644 --- a/src/EventSubscriber/ResourceResponseValidator.php +++ b/src/EventSubscriber/ResourceResponseValidator.php @@ -4,16 +4,11 @@ namespace Drupal\jsonapi\EventSubscriber; use Drupal\Component\Serialization\Json; use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\jsonapi\ResourceResponse; -use Drupal\jsonapi\Routing\Routes; -use Drupal\schemata\SchemaFactory; use JsonSchema\Validator; use Psr\Log\LoggerInterface; -use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Serializer\SerializerInterface; @@ -50,15 +45,6 @@ class ResourceResponseValidator implements EventSubscriberInterface { */ protected $validator; - /** - * The schemata schema factory. - * - * This property will only be set if the schemata module is installed. - * - * @var \Drupal\schemata\SchemaFactory|null - */ - protected $schemaFactory; - /** * The module handler. * @@ -112,31 +98,6 @@ class ResourceResponseValidator implements EventSubscriberInterface { } } - /** - * Injects the schema factory. - * - * @param \Drupal\schemata\SchemaFactory $schema_factory - * The schema factory service. - */ - public function setSchemaFactory(SchemaFactory $schema_factory) { - $this->schemaFactory = $schema_factory; - } - - /** - * Validates JSON:API responses. - * - * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event - * The event to process. - */ - public function onResponse(FilterResponseEvent $event) { - $response = $event->getResponse(); - if (!$response instanceof ResourceResponse) { - return; - } - - $this->doValidateResponse($response, $event->getRequest()); - } - /** * Wraps validation in an assert to prevent execution in production. * @@ -180,56 +141,8 @@ class ResourceResponseValidator implements EventSubscriberInterface { ]) ); $generic_jsonapi_schema = (object) ['$ref' => $schema_ref]; - $is_valid = $this->validateSchema($generic_jsonapi_schema, $response_data); - if (!$is_valid) { - return FALSE; - } - - // This will be set if the schemata module is present. - if (!$this->schemaFactory) { - // Fall back the valid generic result since schemata is absent. - return TRUE; - } - // Get the schema for the current resource. For that we will need to - // introspect the request to find the entity type and bundle matched by the - // router. - $resource_type = $request->get(Routes::RESOURCE_TYPE_KEY); - $route_name = $request->attributes->get(RouteObjectInterface::ROUTE_NAME); - - // We shouldn't validate related/relationships. - $is_related = strpos($route_name, '.related') !== FALSE; - $is_relationship = strpos($route_name, '.relationship') !== FALSE; - if ($is_related || $is_relationship) { - // Fall back the valid generic result since schemata is absent. - return TRUE; - } - - $entity_type_id = $resource_type->getEntityTypeId(); - $bundle = $resource_type->getBundle(); - $output_format = 'schema_json'; - $described_format = 'api_json'; - - $schema_object = $this->schemaFactory->create($entity_type_id, $bundle); - $format = $output_format . ':' . $described_format; - $output = $this->serializer->serialize($schema_object, $format); - $specific_schema = Json::decode($output); - if (!$specific_schema) { - return $is_valid; - } - - // We need to individually validate each collection resource object. - $is_collection = strpos($route_name, '.collection') !== FALSE; - - // Iterate over each resource object and check the schema. - return array_reduce( - $is_collection ? $response_data->data : [$response_data->data], - function ($valid, $resource_object) use ($specific_schema) { - // Validating the schema first ensures that every object is processed. - return $this->validateSchema($specific_schema, $resource_object) && $valid; - }, - TRUE - ); + return $this->validateSchema($generic_jsonapi_schema, $response_data); } /** diff --git a/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php b/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php index e3dfba6..7e79c18 100644 --- a/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php +++ b/tests/src/Unit/EventSubscriber/ResourceResponseValidatorTest.php @@ -10,8 +10,6 @@ use JsonSchema\Validator; use Drupal\Core\Extension\Extension; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\rest\ResourceResponse; -use Drupal\schemata\SchemaFactory; -use Drupal\schemata\Encoder\JsonSchemaEncoder; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; use Psr\Log\LoggerInterface; @@ -104,76 +102,6 @@ class ResourceResponseValidatorTest extends UnitTestCase { assert_options(ASSERT_ACTIVE, $assert_active_default); } - /** - * @covers ::onResponse - * @requires function Drupal\schemata\SchemaFactory::__construct - */ - public function testValidateResponseSchemata() { - $request = $this->createRequest( - 'jsonapi.node--article.individual', - new ResourceType('node', 'article', NULL) - ); - - $response = $this->createResponse('{"data":null}'); - - // The validator should be called *once* if schemata is *not* installed. - $validator = $this->prophesize(Validator::class); - $validator->check(Argument::any(), Argument::any())->shouldBeCalledTimes(1); - $validator->isValid()->willReturn(TRUE); - $this->subscriber->setValidator($validator->reveal()); - - // Run validations. - $this->subscriber->doValidateResponse($response, $request); - - // The validator should be called *twice* if schemata is installed. - $validator = $this->prophesize(Validator::class); - $validator->check(Argument::any(), Argument::any())->shouldBeCalledTimes(2); - $validator->isValid()->willReturn(TRUE); - $this->subscriber->setValidator($validator->reveal()); - - // Make the schemata factory available. - $schema_factory = $this->prophesize(SchemaFactory::class); - $schema_factory->create('node', 'article')->willReturn('{}'); - $this->subscriber->setSchemaFactory($schema_factory->reveal()); - - // Run validations. - $this->subscriber->doValidateResponse($response, $request); - - // The validator resource specific schema should *not* be validated on - // 'related' routes. - $request = $this->createRequest( - 'jsonapi.node--article.related', - new ResourceType('node', 'article', NULL) - ); - - // Since only the generic schema should be validated, the validator should - // only be called once. - $validator = $this->prophesize(Validator::class); - $validator->check(Argument::any(), Argument::any())->shouldBeCalledTimes(1); - $validator->isValid()->willReturn(TRUE); - $this->subscriber->setValidator($validator->reveal()); - - // Run validations. - $this->subscriber->doValidateResponse($response, $request); - - // The validator resource specific schema should *not* be validated on - // 'relationship' routes. - $request = $this->createRequest( - 'jsonapi.node--article.relationship', - new ResourceType('node', 'article', NULL) - ); - - // Since only the generic schema should be validated, the validator should - // only be called once. - $validator = $this->prophesize(Validator::class); - $validator->check(Argument::any(), Argument::any())->shouldBeCalledTimes(1); - $validator->isValid()->willReturn(TRUE); - $this->subscriber->setValidator($validator->reveal()); - - // Run validations. - $this->subscriber->doValidateResponse($response, $request); - } - /** * @covers ::validateResponse * @dataProvider validateResponseProvider