From 7de18436f2a0f87f7e3d23ed54e5dd95ab8207b1 Mon Sep 17 00:00:00 2001 From: Ilias Dimopoulos Date: Fri, 19 Mar 2021 14:00:35 +0200 Subject: [PATCH 1/7] ISAICP-6416: Handle the uuid of namespaces before the controller. --- .../joinup_core/joinup_core.services.yml | 6 ++++ .../joinup_core/src/Controller/IdRedirect.php | 1 + .../PathProcessor/NamespacePathProcessor.php | 30 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php diff --git a/web/modules/custom/joinup_core/joinup_core.services.yml b/web/modules/custom/joinup_core/joinup_core.services.yml index 786cf4b781..c21dfe2ed4 100644 --- a/web/modules/custom/joinup_core/joinup_core.services.yml +++ b/web/modules/custom/joinup_core/joinup_core.services.yml @@ -10,3 +10,9 @@ services: joinup_core.local_task_links_helper: class: Drupal\joinup_core\LocalTaskLinksHelper arguments: ['@entity_type.manager'] + + path_processor.joinup_core: + class: Drupal\joinup_core\PathProcessor\NamespacePathProcessor + tags: + - { name: path_processor_inbound, priority: 1000 } + - { name: path_processor_outbound, priority: 1000 } diff --git a/web/modules/custom/joinup_core/src/Controller/IdRedirect.php b/web/modules/custom/joinup_core/src/Controller/IdRedirect.php index 0468b5a49e..8987b798e9 100644 --- a/web/modules/custom/joinup_core/src/Controller/IdRedirect.php +++ b/web/modules/custom/joinup_core/src/Controller/IdRedirect.php @@ -28,6 +28,7 @@ public function redirectToRdfEntity(string $namespace, string $uuid): RedirectRe return $this->redirect('joinup_core.not_found', [], [], 404); } + $uuid = urldecode($uuid); return $this->redirect("entity.$entity_type_id.canonical", [ $entity_type_id => "http://data.europa.eu/$namespace/$uuid", ], [], 301); diff --git a/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php b/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php new file mode 100644 index 0000000000..d95e16ee67 --- /dev/null +++ b/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php @@ -0,0 +1,30 @@ +query->has('uuid')) { + preg_match_all('#/data/(?[^/]+)/(?.+)#', $path, $matches); + if (!empty($matches)) { + return '/data/' . $matches['namespace'] . '/' . urlencode($matches['uuid']); + } + } + return $path; + } + +} From 1f40e66e6b8b29fd677f511ffd32428b4e49950c Mon Sep 17 00:00:00 2001 From: Ilias Dimopoulos Date: Thu, 18 Mar 2021 16:15:24 +0200 Subject: [PATCH 2/7] ISAICP-6416: Provide a test for slashes in the persistent URLs. --- .../joinup_core/persistent_uris.feature | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/tests/features/joinup_core/persistent_uris.feature b/tests/features/joinup_core/persistent_uris.feature index 7bea4309d2..8384eca5c4 100644 --- a/tests/features/joinup_core/persistent_uris.feature +++ b/tests/features/joinup_core/persistent_uris.feature @@ -45,7 +45,7 @@ Feature: And "eira" terms: | tid | name | description | - | http://data.europa.eu/dr8/DreamDomain | Dream Domain | You're safe from pain in the dream domain. | + | http://data.europa.eu/dr8/Dream/Domain | Dream Domain | You're safe from pain in the dream domain. | And discussion content: | title | body | collection | state | @@ -103,34 +103,23 @@ Feature: # Our semantic content has a persistent canonical path at Europe's # official data portal: "http://data.europa.eu/w21/{uuid}". The data portal - # links back to the Joinup servers. In order to resolve the UUIDs we employ - # the intermediate path '/data/{uuid}' which will forward the request to the - # actual page that contains the content in human digestible format. - Given I am on "data/ffb0ffc9-7704-45d3-95b3-42706b6320e5" - Then I should see the heading "Persistent solution" - And I am on "data/w21/ffb0ffc9-7704-45d3-95b3-42706b6320e5" + # links back to the Joinup servers. + Given I am on "data/w21/ffb0ffc9-7704-45d3-95b3-42706b6320e5" Then I should see the heading "Persistent solution" - Given I am on "data/37b8103e-26e5-4c81-8ce5-43ced02ff7d0" - Then I should see the heading "Persistent collection" - And I am on "data/w21/37b8103e-26e5-4c81-8ce5-43ced02ff7d0" + Given I am on "data/w21/37b8103e-26e5-4c81-8ce5-43ced02ff7d0" Then I should see the heading "Persistent collection" - Given I am on "data/98004ec9-62f3-4734-a1b6-af7e4838b09c" - Then I should see the heading "Persistent release 23" - And I am on "data/w21/98004ec9-62f3-4734-a1b6-af7e4838b09c" + Given I am on "data/w21/98004ec9-62f3-4734-a1b6-af7e4838b09c" Then I should see the heading "Persistent release 23" - Given I am on "data/643a2a52-da3b-4594-92bb-295d8134e1fb" - Then I should see the heading "Persistent distribution" - And I am on "data/w21/643a2a52-da3b-4594-92bb-295d8134e1fb" + Given I am on "data/w21/643a2a52-da3b-4594-92bb-295d8134e1fb" Then I should see the heading "Persistent distribution" - Given I am on "data/4205229d-92b6-4cac-80af-d8c2296d923c" - Then I should see the heading "Persistent licence" - And I am on "data/w21/4205229d-92b6-4cac-80af-d8c2296d923c" + Given I am on "data/w21/4205229d-92b6-4cac-80af-d8c2296d923c" Then I should see the heading "Persistent licence" - Given I am on "data/dr8/DreamDomain" + Given I am on "data/dr8/Dream/Domain" Then I should see the heading "Dream Domain" And I should see "You're safe from pain in the dream domain." + And the url should match "/taxonomy/term/http_e_f_fdata_ceuropa_ceu_fdr8_fDream_fDomain" From 8f8b071d2f2e797c3fc86d8c514b32d09ee6ca1e Mon Sep 17 00:00:00 2001 From: Ilias Dimopoulos Date: Fri, 19 Mar 2021 15:12:07 +0200 Subject: [PATCH 3/7] ISAICP-6414: Allow '/' in URLs. --- .../custom/joinup_core/joinup_core.routing.yml | 13 ++++--------- .../custom/joinup_core/joinup_core.services.yml | 3 +-- .../src/PathProcessor/NamespacePathProcessor.php | 11 ++++++----- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/web/modules/custom/joinup_core/joinup_core.routing.yml b/web/modules/custom/joinup_core/joinup_core.routing.yml index 97c137a777..e91608b615 100644 --- a/web/modules/custom/joinup_core/joinup_core.routing.yml +++ b/web/modules/custom/joinup_core/joinup_core.routing.yml @@ -14,21 +14,16 @@ joinup_core.file_field_info: requirements: _permission: 'administer content types' -# @todo Remove this when the w21 redirect has been updated. -joinup_core.id_redirect.deprecated: - path: '/data/{uuid}' - defaults: - _controller: '\Drupal\joinup_core\Controller\IdRedirect::redirectToRdfEntity' - namespace: w21 - requirements: - _access: 'TRUE' - joinup_core.id_redirect: path: '/data/{namespace}/{uuid}' defaults: _controller: '\Drupal\joinup_core\Controller\IdRedirect::redirectToRdfEntity' requirements: _access: 'TRUE' + # Even though we are using a custom processor to alter the UUID value to not include the /, we need to set the value + # of UUID to match '.+' because the Drupal routing system uses by default the '[^/]' for route parameters. + # @see \Drupal\Core\Routing\Router::doMatchCollection + uuid: '.+' joinup_core.rdf_entity_uri_web_converter_page: path: '/rdf' diff --git a/web/modules/custom/joinup_core/joinup_core.services.yml b/web/modules/custom/joinup_core/joinup_core.services.yml index c21dfe2ed4..7769f1349f 100644 --- a/web/modules/custom/joinup_core/joinup_core.services.yml +++ b/web/modules/custom/joinup_core/joinup_core.services.yml @@ -14,5 +14,4 @@ services: path_processor.joinup_core: class: Drupal\joinup_core\PathProcessor\NamespacePathProcessor tags: - - { name: path_processor_inbound, priority: 1000 } - - { name: path_processor_outbound, priority: 1000 } + - { name: path_processor_inbound, priority: 200 } diff --git a/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php b/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php index d95e16ee67..71c8adf2a5 100644 --- a/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php +++ b/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php @@ -5,23 +5,24 @@ namespace Drupal\joinup_core\PathProcessor; use Drupal\Core\PathProcessor\InboundPathProcessorInterface; -use Drupal\Core\PathProcessor\OutboundPathProcessorInterface; -use Drupal\Core\Render\BubbleableMetadata; +use Drupal\joinup_core\Controller\IdRedirect; use Symfony\Component\HttpFoundation\Request; /** * Path processor to handle cases where the EC namespace ID contains a '/'. */ -class NamespacePathProcessor implements InboundPathProcessorInterface, OutboundPathProcessorInterface { +class NamespacePathProcessor implements InboundPathProcessorInterface { /** * {@inheritdoc} + * + * @see \Drupal\joinup_core\Controller\IdRedirect::redirectToRdfEntity */ public function processInbound($path, Request $request) { if (strpos($path, '/data/') === 0 && !$request->query->has('uuid')) { preg_match_all('#/data/(?[^/]+)/(?.+)#', $path, $matches); - if (!empty($matches)) { - return '/data/' . $matches['namespace'] . '/' . urlencode($matches['uuid']); + if (!empty($matches['namespace'][0]) && !empty($matches['uuid'][0]) && IdRedirect::getEntityTypeFromPersistentUriNamespace($matches['namespace'][0])) { + return '/data/' . $matches['namespace'][0] . '/' . urlencode($matches['uuid'][0]); } } return $path; From d00cf1d46de5f1f8f3c665eb82bce890e4ab1942 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea Date: Mon, 22 Mar 2021 12:59:05 +0200 Subject: [PATCH 4/7] ISAICP-6414: QA remarks. --- .../joinup_core/joinup_core.routing.yml | 7 ++-- .../joinup_core/joinup_core.services.yml | 6 ++- .../joinup_core/src/Controller/IdRedirect.php | 2 + .../IdRedirectNamespaceProcessor.php | 38 +++++++++++++++++++ .../PathProcessor/NamespacePathProcessor.php | 31 --------------- 5 files changed, 49 insertions(+), 35 deletions(-) create mode 100644 web/modules/custom/joinup_core/src/PathProcessor/IdRedirectNamespaceProcessor.php delete mode 100644 web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php diff --git a/web/modules/custom/joinup_core/joinup_core.routing.yml b/web/modules/custom/joinup_core/joinup_core.routing.yml index e91608b615..f1c434de0f 100644 --- a/web/modules/custom/joinup_core/joinup_core.routing.yml +++ b/web/modules/custom/joinup_core/joinup_core.routing.yml @@ -20,9 +20,10 @@ joinup_core.id_redirect: _controller: '\Drupal\joinup_core\Controller\IdRedirect::redirectToRdfEntity' requirements: _access: 'TRUE' - # Even though we are using a custom processor to alter the UUID value to not include the /, we need to set the value - # of UUID to match '.+' because the Drupal routing system uses by default the '[^/]' for route parameters. - # @see \Drupal\Core\Routing\Router::doMatchCollection + # Even though we are using a custom processor to alter the UUID value to not + # include the /, we need to set the value of UUID to match '.+' because the + # Drupal routing system uses by default the '[^/]' for route parameters. + # @see \Drupal\Core\Routing\Router::doMatchCollection() uuid: '.+' joinup_core.rdf_entity_uri_web_converter_page: diff --git a/web/modules/custom/joinup_core/joinup_core.services.yml b/web/modules/custom/joinup_core/joinup_core.services.yml index 7769f1349f..41313d6a5e 100644 --- a/web/modules/custom/joinup_core/joinup_core.services.yml +++ b/web/modules/custom/joinup_core/joinup_core.services.yml @@ -1,17 +1,21 @@ services: + joinup_core.joinup_version: class: Drupal\joinup_core\JoinupVersion + logger.channel.joinup_core: parent: logger.channel_base arguments: ['joinup_core'] + joinup_core.requirements_helper: class: Drupal\joinup_core\RequirementsHelper arguments: ['@database'] + joinup_core.local_task_links_helper: class: Drupal\joinup_core\LocalTaskLinksHelper arguments: ['@entity_type.manager'] path_processor.joinup_core: - class: Drupal\joinup_core\PathProcessor\NamespacePathProcessor + class: Drupal\joinup_core\PathProcessor\IdRedirectNamespaceProcessor tags: - { name: path_processor_inbound, priority: 200 } diff --git a/web/modules/custom/joinup_core/src/Controller/IdRedirect.php b/web/modules/custom/joinup_core/src/Controller/IdRedirect.php index 8987b798e9..8c86c91bcf 100644 --- a/web/modules/custom/joinup_core/src/Controller/IdRedirect.php +++ b/web/modules/custom/joinup_core/src/Controller/IdRedirect.php @@ -28,6 +28,8 @@ public function redirectToRdfEntity(string $namespace, string $uuid): RedirectRe return $this->redirect('joinup_core.not_found', [], [], 404); } + // The UUID has been encoded early to allow slashes. + // @see \Drupal\joinup_core\PathProcessor\IdRedirectNamespaceProcessor::processInbound() $uuid = urldecode($uuid); return $this->redirect("entity.$entity_type_id.canonical", [ $entity_type_id => "http://data.europa.eu/$namespace/$uuid", diff --git a/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectNamespaceProcessor.php b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectNamespaceProcessor.php new file mode 100644 index 0000000000..5aea2bdbf7 --- /dev/null +++ b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectNamespaceProcessor.php @@ -0,0 +1,38 @@ +query->has('uuid')) { + preg_match('#/data/(?[^/]+)/(?.+)#', $path, $matches); + if (!empty($matches['namespace']) && !empty($matches['uuid'][0]) && IdRedirect::getEntityTypeFromPersistentUriNamespace($matches['namespace'])) { + return '/data/' . $matches['namespace'] . '/' . urlencode($matches['uuid']); + } + } + return $path; + } + +} diff --git a/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php b/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php deleted file mode 100644 index 71c8adf2a5..0000000000 --- a/web/modules/custom/joinup_core/src/PathProcessor/NamespacePathProcessor.php +++ /dev/null @@ -1,31 +0,0 @@ -query->has('uuid')) { - preg_match_all('#/data/(?[^/]+)/(?.+)#', $path, $matches); - if (!empty($matches['namespace'][0]) && !empty($matches['uuid'][0]) && IdRedirect::getEntityTypeFromPersistentUriNamespace($matches['namespace'][0])) { - return '/data/' . $matches['namespace'][0] . '/' . urlencode($matches['uuid'][0]); - } - } - return $path; - } - -} From 17465da5a883a5fee85e3584116549a3c26170d3 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea Date: Mon, 22 Mar 2021 13:06:05 +0200 Subject: [PATCH 5/7] ISAICP-6414: Actually it's IdRedirectUuidProcessor. --- web/modules/custom/joinup_core/joinup_core.services.yml | 2 +- ...directNamespaceProcessor.php => IdRedirectUuidProcessor.php} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename web/modules/custom/joinup_core/src/PathProcessor/{IdRedirectNamespaceProcessor.php => IdRedirectUuidProcessor.php} (94%) diff --git a/web/modules/custom/joinup_core/joinup_core.services.yml b/web/modules/custom/joinup_core/joinup_core.services.yml index 41313d6a5e..5c2bf78af3 100644 --- a/web/modules/custom/joinup_core/joinup_core.services.yml +++ b/web/modules/custom/joinup_core/joinup_core.services.yml @@ -16,6 +16,6 @@ services: arguments: ['@entity_type.manager'] path_processor.joinup_core: - class: Drupal\joinup_core\PathProcessor\IdRedirectNamespaceProcessor + class: Drupal\joinup_core\PathProcessor\IdRedirectUuidProcessor tags: - { name: path_processor_inbound, priority: 200 } diff --git a/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectNamespaceProcessor.php b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php similarity index 94% rename from web/modules/custom/joinup_core/src/PathProcessor/IdRedirectNamespaceProcessor.php rename to web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php index 5aea2bdbf7..ff6cdababd 100644 --- a/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectNamespaceProcessor.php +++ b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php @@ -20,7 +20,7 @@ * @see https://symfony.com/doc/3.4/routing/slash_in_parameter.html * @see \Drupal\joinup_core\Controller\IdRedirect::redirectToRdfEntity() */ -class IdRedirectNamespaceProcessor implements InboundPathProcessorInterface { +class IdRedirectUuidProcessor implements InboundPathProcessorInterface { /** * {@inheritdoc} From 0c60316f67865b1452b15f8ed8b76cdf47caa365 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea Date: Mon, 22 Mar 2021 13:09:42 +0200 Subject: [PATCH 6/7] ISAICP-6414: Tiny docs fix. --- .../src/PathProcessor/IdRedirectUuidProcessor.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php index ff6cdababd..a388b3b8e7 100644 --- a/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php +++ b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php @@ -12,9 +12,9 @@ * Handles joinup_core.id_redirect route case when {uuid} param contains a '/'. * * Because the joinup_core.id_redirect route's {uuid} parameter may contain one - * or more slashes, we encode the URL parameter because Drupal doesn't allow - * slashes in parameters, as opposed to Symfony. We revert the variable in - * IdRedirect::redirectToRdfEntity(). + * or more slashes, we encode the URL parameter as Drupal doesn't allow slashes + * in parameters, as opposed to Symfony. We revert the parameter encoding, + * later, in IdRedirect::redirectToRdfEntity(). * * @see https://www.drupal.org/project/drupal/issues/2741939 * @see https://symfony.com/doc/3.4/routing/slash_in_parameter.html From 140fe7db2951fa783aca00b3707ca4290cbb9f6f Mon Sep 17 00:00:00 2001 From: Claudiu Cristea Date: Mon, 22 Mar 2021 13:12:38 +0200 Subject: [PATCH 7/7] ISAICP-6414: Stronger regex. --- .../joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php index a388b3b8e7..f5f34a7557 100644 --- a/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php +++ b/web/modules/custom/joinup_core/src/PathProcessor/IdRedirectUuidProcessor.php @@ -27,7 +27,7 @@ class IdRedirectUuidProcessor implements InboundPathProcessorInterface { */ public function processInbound($path, Request $request): string { if (strpos($path, '/data/') === 0 && !$request->query->has('uuid')) { - preg_match('#/data/(?[^/]+)/(?.+)#', $path, $matches); + preg_match('#^/data/(?[^/]+)/(?.+)$#', $path, $matches); if (!empty($matches['namespace']) && !empty($matches['uuid'][0]) && IdRedirect::getEntityTypeFromPersistentUriNamespace($matches['namespace'])) { return '/data/' . $matches['namespace'] . '/' . urlencode($matches['uuid']); }