From 7043521bce0de8a845bf89dfa15f4e88afad49e6 Mon Sep 17 00:00:00 2001 From: Dan Tran Date: Sat, 7 May 2022 18:26:04 +0700 Subject: [PATCH 1/5] JSONAPI assessment - improve JSONAPI output. --- .../jsonapi_assessment.api.php | 21 ++++ .../jsonapi_assessment.info.yml | 12 ++ .../jsonapi_assessment.module | 27 +++++ .../jsonapi_assessment.services.yml | 13 ++ .../EventSubscriber/ResponseSubscriber.php | 113 ++++++++++++++++++ react/api/article.js | 27 ++++- react/pages/index.js | 15 ++- 7 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.api.php create mode 100644 drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.info.yml create mode 100644 drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module create mode 100644 drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml create mode 100644 drupal/web/modules/custom/jsonapi_assessment/src/EventSubscriber/ResponseSubscriber.php diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.api.php b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.api.php new file mode 100644 index 0000000..a563f32 --- /dev/null +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.api.php @@ -0,0 +1,21 @@ + $item) { + if ($item['type'] == 'articles') { + // load node to check permission + $node = \Drupal\node\Entity\Node::load($item['attributes']['internalId']); + $access = $node->access('update', $user); + $jsonapi_response['data'][$key]['attributes']['editable'] = $access; // append attributes to display edit link in front end. + } + } + } +} \ No newline at end of file diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml new file mode 100644 index 0000000..029d413 --- /dev/null +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml @@ -0,0 +1,13 @@ +services: + jsonapi_assessment.normalizer.typed_data: + class: Drupal\jsonapi_assessment\Normalizer\CustomTypedDataNormalizer + arguments: ['@entity.manager'] + tags: + - { name: normalizer, priority: 1 } + jsonapi_response_alter.response_subscriber: + class: Drupal\jsonapi_assessment\EventSubscriber\ResponseSubscriber + arguments: [ '@module_handler' ] + tags: + - { name: event_subscriber } + calls: + - [ setRouteMatch, [ '@current_route_match' ] ] diff --git a/drupal/web/modules/custom/jsonapi_assessment/src/EventSubscriber/ResponseSubscriber.php b/drupal/web/modules/custom/jsonapi_assessment/src/EventSubscriber/ResponseSubscriber.php new file mode 100644 index 0000000..f20b0da --- /dev/null +++ b/drupal/web/modules/custom/jsonapi_assessment/src/EventSubscriber/ResponseSubscriber.php @@ -0,0 +1,113 @@ +moduleHandler = $moduleHandler; + } + + /** + * Create a new instance. + * + * @param \Symfony\Component\DependencyInjection\ContainerInterface $container + * The container. + * + * @return \Drupal\jsonapi_assessment\EventSubscriber\ResponseSubscriber + * The new instance. + */ + public static function create(ContainerInterface $container) { + return new self( + $container->get('module_handler') + ); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[KernelEvents::RESPONSE] = ['onResponse']; + + return $events; + } + + /** + * Set route match service. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match service. + */ + public function setRouteMatch(RouteMatchInterface $route_match) { + $this->routeMatch = $route_match; + } + + /** + * This method is called the KernelEvents::RESPONSE event is dispatched. + * + * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event + * The filter event. + */ + public function onResponse(FilterResponseEvent $event) { + if (!$this->routeMatch->getRouteObject()) { + return; + } + + if ( + $this->routeMatch->getRouteName() === 'jsonapi.resource_list' || + Routes::isJsonApiRequest($this->routeMatch->getRouteObject() + ->getDefaults()) + ) { + + $response = $event->getResponse(); + $content = $response->getContent(); + + $jsonapi_response = json_decode($content, TRUE); + + if (!is_array($jsonapi_response)) { + return; + } + + // call the hook aler + $this->moduleHandler->alter('jsonapi_response', $jsonapi_response, $response); + $response->setContent(json_encode($jsonapi_response)); + } + } + +} diff --git a/react/api/article.js b/react/api/article.js index ea0b667..a352df7 100644 --- a/react/api/article.js +++ b/react/api/article.js @@ -8,9 +8,10 @@ import request from '../utils/request'; */ export const getAll = () => new Promise((resolve, reject) => { request - .get('/api/articles') + .get('/api/articles/') .query({ 'fields[node--article]': 'id', + 'include': 'image' }) // Tell superagent to consider any valid Drupal response as successful. // Later we can capture error codes if needed. @@ -28,3 +29,27 @@ export const getAll = () => new Promise((resolve, reject) => { reject(error); }); }); + +export const getById = (id) => new Promise((resolve, reject) => { + console.log(id); + request + .get('/api/articles/' + id) + .query({ + }) + // Tell superagent to consider any valid Drupal response as successful. + // Later we can capture error codes if needed. + .ok((resp) => resp.statusCode) + .then((response) => { + console.log(response.body); + resolve({ + // eslint-disable-next-line max-len + article: response.statusCode === 200 ? transforms.articleDetail(response.body.data) : {}, + statusCode: response.statusCode, + }); + }) + .catch((error) => { + // eslint-disable-next-line no-console + console.error('Could not fetch the article detail.', error); + reject(error); + }); +}); diff --git a/react/pages/index.js b/react/pages/index.js index 4836264..6bba2b5 100644 --- a/react/pages/index.js +++ b/react/pages/index.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as articleApi from '../api/article'; +import Link from "next/link" class HomePage extends React.Component { static async getInitialProps() { @@ -15,6 +16,7 @@ class HomePage extends React.Component { } catch (e) { // Pass status code as internal properly. It is being checked inside of // render() method of _app.js. + console.log(e); initialProps.statusCode = 500; } @@ -23,12 +25,19 @@ class HomePage extends React.Component { render() { const { articles } = this.props; + return (
Home page is working!

List of articles from Drupal:
); @@ -37,8 +46,10 @@ class HomePage extends React.Component { HomePage.propTypes = { articles: PropTypes.arrayOf(PropTypes.shape({ - title: PropTypes.string, id: PropTypes.string, + title: PropTypes.string, + body: PropTypes.string, + editable: PropTypes.bool })), }; From 073edb14d361421e6cb620e0aece930d4ac8e910 Mon Sep 17 00:00:00 2001 From: Dan Tran Date: Sat, 7 May 2022 18:30:32 +0700 Subject: [PATCH 2/5] JSONAPI assessment - improve JSONAPI output. --- .../custom/jsonapi_assessment/jsonapi_assessment.info.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.info.yml b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.info.yml index e99b981..256f0e8 100644 --- a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.info.yml +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.info.yml @@ -5,7 +5,6 @@ core: 8.x package: Web services dependencies: - jsonapi:jsonapi - - jsonapi_extras:jsonapi_extras version: '8.x-1.0' project: 'jsonapi' From 7467d28018699b8e21e85120cdb1f0b355b06c1a Mon Sep 17 00:00:00 2001 From: Dan Tran Date: Sat, 7 May 2022 18:31:41 +0700 Subject: [PATCH 3/5] JSONAPI assessment - improve JSONAPI output. --- .../jsonapi_assessment/jsonapi_assessment.services.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml index 029d413..77b44a2 100644 --- a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.services.yml @@ -1,10 +1,5 @@ services: - jsonapi_assessment.normalizer.typed_data: - class: Drupal\jsonapi_assessment\Normalizer\CustomTypedDataNormalizer - arguments: ['@entity.manager'] - tags: - - { name: normalizer, priority: 1 } - jsonapi_response_alter.response_subscriber: + jsonapi_assessment.response_subscriber: class: Drupal\jsonapi_assessment\EventSubscriber\ResponseSubscriber arguments: [ '@module_handler' ] tags: From 62d47ee657fa4ba0e20e0b171c6ecb9d95820cbe Mon Sep 17 00:00:00 2001 From: Dan Tran Date: Sat, 7 May 2022 20:52:41 +0700 Subject: [PATCH 4/5] update access check. --- .../custom/jsonapi_assessment/jsonapi_assessment.module | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module index 9a584d2..2e776fd 100644 --- a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module @@ -15,11 +15,12 @@ function jsonapi_assessment_jsonapi_response_alter(array &$jsonapi_response, Res if (isset($jsonapi_response['data']) && is_Array($jsonapi_response['data'])) { $user = \Drupal::currentUser(); + $entity_manager = \Drupal::entityTypeManager(); + $access_handler = $entity_manager->getAccessControlHandler('node'); + $access = $access_handler->createAccess('article'); + foreach ($jsonapi_response['data'] as $key => $item) { if ($item['type'] == 'articles') { - // load node to check permission - $node = \Drupal\node\Entity\Node::load($item['attributes']['internalId']); - $access = $node->access('update', $user); $jsonapi_response['data'][$key]['attributes']['editable'] = $access; // append attributes to display edit link in front end. } } From ddaf28f7e5946ab2888fc76b8849fe252ab0c1fd Mon Sep 17 00:00:00 2001 From: Dan Tran Date: Sun, 8 May 2022 10:29:00 +0700 Subject: [PATCH 5/5] remove unuse variable --- .../modules/custom/jsonapi_assessment/jsonapi_assessment.module | 2 -- 1 file changed, 2 deletions(-) diff --git a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module index 2e776fd..6a12b60 100644 --- a/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module +++ b/drupal/web/modules/custom/jsonapi_assessment/jsonapi_assessment.module @@ -13,8 +13,6 @@ use Symfony\Component\HttpFoundation\Response; function jsonapi_assessment_jsonapi_response_alter(array &$jsonapi_response, Response $response) { // loop data to alter if (isset($jsonapi_response['data']) && is_Array($jsonapi_response['data'])) { - $user = \Drupal::currentUser(); - $entity_manager = \Drupal::entityTypeManager(); $access_handler = $entity_manager->getAccessControlHandler('node'); $access = $access_handler->createAccess('article');