From abc745b543acdb711b440fc9dc9ff42f82c6c95c Mon Sep 17 00:00:00 2001 From: Santeri Hurnanen Date: Tue, 19 Nov 2024 08:15:43 +0200 Subject: [PATCH 1/3] UHF-10941: Fix elasticsearch index --- conf/cmi/search_api.index.job_listings.yml | 10 +-- .../processor/LanguageFieldProcessor.php | 73 +++++++++++++++++++ 2 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 public/modules/custom/helfi_rekry_content/src/Plugin/search_api/processor/LanguageFieldProcessor.php diff --git a/conf/cmi/search_api.index.job_listings.yml b/conf/cmi/search_api.index.job_listings.yml index ed21acc4..1c4a2c9a 100644 --- a/conf/cmi/search_api.index.job_listings.yml +++ b/conf/cmi/search_api.index.job_listings.yml @@ -26,19 +26,16 @@ dependencies: - scheduler - search_api - helfi_react_search + - helfi_rekry_content id: job_listings name: 'Job listings' description: '' read_only: false field_settings: _language: - label: 'Legacy Language' - datasource_id: 'entity:node' - property_path: langcode + label: Language + property_path: _language type: string - dependencies: - module: - - node employment_id: label: 'Employment » Luokittelutermi » Termin ID' datasource_id: 'entity:node' @@ -343,6 +340,7 @@ processor_settings: - field_recruitment_id - field_search_id - langcode + language_field: { } language_with_fallback: { } project_execution_schedule: { } project_image_absolute_url: { } diff --git a/public/modules/custom/helfi_rekry_content/src/Plugin/search_api/processor/LanguageFieldProcessor.php b/public/modules/custom/helfi_rekry_content/src/Plugin/search_api/processor/LanguageFieldProcessor.php new file mode 100644 index 00000000..449f0e63 --- /dev/null +++ b/public/modules/custom/helfi_rekry_content/src/Plugin/search_api/processor/LanguageFieldProcessor.php @@ -0,0 +1,73 @@ + $this->t('Language'), + 'description' => $this->t('The legacy _language field.'), + 'type' => 'string', + 'processor_id' => $this->getPluginId(), + ]; + $properties['_language'] = new ProcessorProperty($definition); + } + + return $properties; + } + + /** + * {@inheritdoc} + */ + public function addFieldValues(ItemInterface $item): void { + $object = $item->getOriginalObject()->getValue(); + + if ($object instanceof EntityInterface) { + $indexableValue = $object->language()->getId(); + + $itemFields = $item->getFields(); + $itemFields = $this->getFieldsHelper() + ->filterForPropertyPath($itemFields, NULL, '_language'); + + foreach ($itemFields as $itemField) { + $itemField->addValue($indexableValue); + } + + } + } + +} From e306bcbe902f5ddb568b8b9d7397c1f47ce381d5 Mon Sep 17 00:00:00 2001 From: Santeri Hurnanen Date: Tue, 19 Nov 2024 08:15:44 +0200 Subject: [PATCH 2/3] UHF-10941: Do not log 404 confirmation errors to Sentry --- .../helfi_hakuvahti/helfi_hakuvahti.module | 2 +- .../Controller/HelfiHakuvahtiController.php | 61 +++++++++++-------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/public/modules/custom/helfi_hakuvahti/helfi_hakuvahti.module b/public/modules/custom/helfi_hakuvahti/helfi_hakuvahti.module index b9086c6a..2d14e141 100644 --- a/public/modules/custom/helfi_hakuvahti/helfi_hakuvahti.module +++ b/public/modules/custom/helfi_hakuvahti/helfi_hakuvahti.module @@ -12,7 +12,7 @@ declare(strict_types=1); /** * Implements hook_theme(). */ -function helfi_hakuvahti_theme() { +function helfi_hakuvahti_theme(): array { return [ 'hakuvahti_form' => [ 'variables' => [ diff --git a/public/modules/custom/helfi_hakuvahti/src/Controller/HelfiHakuvahtiController.php b/public/modules/custom/helfi_hakuvahti/src/Controller/HelfiHakuvahtiController.php index 6f7fc15f..38709d20 100644 --- a/public/modules/custom/helfi_hakuvahti/src/Controller/HelfiHakuvahtiController.php +++ b/public/modules/custom/helfi_hakuvahti/src/Controller/HelfiHakuvahtiController.php @@ -9,9 +9,9 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; use Drupal\Core\Utility\Token; -use GuzzleHttp\Client; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\GuzzleException; +use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -78,9 +78,28 @@ public function confirm(): array { * A render array for the confirmation result. */ private function handleConfirmFormSubmission(string $hash, string $subscription): array { - return $this->sendConfirmationRequest($hash, $subscription) - ? $this->buildConfirmationSuccess() - : $this->buildConfirmationFailure(); + try { + $response = $this->sendConfirmationRequest($hash, $subscription); + + if ($response->getBody()->getContents() !== '') { + return $this->buildConfirmationSuccess(); + } + } + catch (GuzzleException $exception) { + // 404 error is returned if: + // * Submission has been deleted after it expired. + // * Submission has already been confirmed. + // * Submission does not exist. + if ($exception->getCode() === 404) { + $this->logger->info('Hakuvahti confirmation request failed: ' . $exception->getMessage()); + + return $this->buildConfirmationFailure(); + } + + $this->logger->error('Hakuvahti confirmation request failed: ' . $exception->getMessage()); + } + + return $this->buildConfirmationFailure(); } /** @@ -138,27 +157,20 @@ private function buildConfirmationFailure(): array { * @param string $subscriptionId * The subscription ID. * - * @return bool - * TRUE if the confirmation request was successful, FALSE otherwise. + * @return \Psr\Http\Message\ResponseInterface + * API response object. + * + * @throws \GuzzleHttp\Exception\GuzzleException */ - protected function sendConfirmationRequest(string $subscriptionHash, string $subscriptionId): bool { + protected function sendConfirmationRequest(string $subscriptionHash, string $subscriptionId): ResponseInterface { $csrfTokenService = $this->container->get('csrf_token'); - $httpClient = new Client([ + + return $this->httpClient->request('GET', getenv('HAKUVAHTI_URL') . "/subscription/confirm/{$subscriptionId}/{$subscriptionHash}", [ 'headers' => [ 'Content-Type' => 'application/json', 'token' => $csrfTokenService->get('session'), ], ]); - - try { - $response = $httpClient->get(getenv('HAKUVAHTI_URL') . "/subscription/confirm/{$subscriptionId}/{$subscriptionHash}"); - return $response->getBody()->getContents() !== ''; - } - catch (GuzzleException $exception) { - $this->logger - ->error('Hakuvahti confirmation request failed: ' . $exception->getMessage()); - return FALSE; - } } /** @@ -256,15 +268,14 @@ private function buildUnsubscribeFailedSubmission(): array { */ protected function sendUnsubscribeRequest(string $hash, string $subscription): bool { $csrfTokenService = $this->container->get('csrf_token'); - $httpClient = new Client([ - 'headers' => [ - 'Content-Type' => 'application/json', - 'token' => $csrfTokenService->get('session'), - ], - ]); try { - $response = $httpClient->delete(getenv('HAKUVAHTI_URL') . "/subscription/delete/{$subscription}/{$hash}"); + $response = $this->httpClient->request('DELETE', getenv('HAKUVAHTI_URL') . "/subscription/delete/{$subscription}/{$hash}", [ + 'headers' => [ + 'Content-Type' => 'application/json', + 'token' => $csrfTokenService->get('session'), + ], + ]); return $response->getStatusCode() >= 200 && $response->getStatusCode() < 300; } catch (GuzzleException $exception) { From e3547805b2f16adaed8b087b90db561331f3ece9 Mon Sep 17 00:00:00 2001 From: Santeri Hurnanen Date: Tue, 19 Nov 2024 08:15:44 +0200 Subject: [PATCH 3/3] UHF-10941: Add test --- .../hakuvahti-confirmation.html.twig | 2 + .../templates/hakuvahti-form.html.twig | 2 + .../src/Kernel/HakuvahtiControllerTest.php | 109 ++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 public/modules/custom/helfi_hakuvahti/templates/hakuvahti-confirmation.html.twig create mode 100644 public/modules/custom/helfi_hakuvahti/templates/hakuvahti-form.html.twig create mode 100644 public/modules/custom/helfi_hakuvahti/tests/src/Kernel/HakuvahtiControllerTest.php diff --git a/public/modules/custom/helfi_hakuvahti/templates/hakuvahti-confirmation.html.twig b/public/modules/custom/helfi_hakuvahti/templates/hakuvahti-confirmation.html.twig new file mode 100644 index 00000000..f2fde537 --- /dev/null +++ b/public/modules/custom/helfi_hakuvahti/templates/hakuvahti-confirmation.html.twig @@ -0,0 +1,2 @@ +{{ title }} +{{ message }} diff --git a/public/modules/custom/helfi_hakuvahti/templates/hakuvahti-form.html.twig b/public/modules/custom/helfi_hakuvahti/templates/hakuvahti-form.html.twig new file mode 100644 index 00000000..f2fde537 --- /dev/null +++ b/public/modules/custom/helfi_hakuvahti/templates/hakuvahti-form.html.twig @@ -0,0 +1,2 @@ +{{ title }} +{{ message }} diff --git a/public/modules/custom/helfi_hakuvahti/tests/src/Kernel/HakuvahtiControllerTest.php b/public/modules/custom/helfi_hakuvahti/tests/src/Kernel/HakuvahtiControllerTest.php new file mode 100644 index 00000000..abbbbfb2 --- /dev/null +++ b/public/modules/custom/helfi_hakuvahti/tests/src/Kernel/HakuvahtiControllerTest.php @@ -0,0 +1,109 @@ +setUpCurrentUser(permissions: ['access content']); + } + + /** + * Tests handleConfirmFormSubmission. + */ + public function testHandleConfirmFormSubmission(): void { + $this->container->set(ClientInterface::class, $this->createMockHttpClient([ + new Response(200, body: 'success'), + new Response(404, body: 'not found'), + new Response(500, body: 'fail'), + new RequestException("womp womp", new Request('POST', 'test')), + ])); + + $logger = $this->prophesize(LoggerInterface::class); + $this->container->set('logger.channel.helfi_hakuvahti', $logger->reveal()); + + // Get request. + $response = $this->makeRequest('GET', 'helfi_hakuvahti.confirm', ['hash' => 'a', 'subscription' => 'b']); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertStringContainsString('Confirm saved search', $response->getContent() ?? ''); + + // Success. + $response = $this->makeRequest('POST', 'helfi_hakuvahti.confirm', ['hash' => 'a', 'subscription' => 'b']); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertStringContainsString('Search saved successfully', $response->getContent() ?? ''); + + // Not found. + $response = $this->makeRequest('POST', 'helfi_hakuvahti.confirm', ['hash' => 'a', 'subscription' => 'b']); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertStringContainsString('Confirmation failed', $response->getContent() ?? ''); + + // Server error. + $response = $this->makeRequest('POST', 'helfi_hakuvahti.confirm', ['hash' => 'a', 'subscription' => 'b']); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertStringContainsString('Confirmation failed', $response->getContent() ?? ''); + + // Guzzle exception. + $response = $this->makeRequest('POST', 'helfi_hakuvahti.confirm', ['hash' => 'a', 'subscription' => 'b']); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertStringContainsString('Confirmation failed', $response->getContent() ?? ''); + } + + /** + * Process a request. + * + * @param string $method + * HTTP method. + * @param string $route + * Drupal route. + * @param array $query + * Query parameters. + * + * @return \Symfony\Component\HttpFoundation\Response + * Controller response. + */ + private function makeRequest(string $method, string $route, array $query = []): SymfonyResponse { + $url = Url::fromRoute($route, options: [ + 'query' => $query, + ]); + + $request = $this->getMockedRequest($url->toString(), $method); + + return $this->processRequest($request); + } + +}