From 14efb89380b8ebc4d41b77d7f030dd5feda44151 Mon Sep 17 00:00:00 2001 From: Alberto Islas Date: Fri, 10 Jan 2025 09:32:35 -0600 Subject: [PATCH] fix(search): Ensure additional search connectors apply for the Search API --- .../commands/cl_send_recap_alerts.py | 2 + cl/lib/elasticsearch_utils.py | 1 + cl/search/exception.py | 2 +- cl/search/feeds.py | 2 + cl/search/tests/tests.py | 64 ++++++++++++++++++- 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/cl/alerts/management/commands/cl_send_recap_alerts.py b/cl/alerts/management/commands/cl_send_recap_alerts.py index b3f44f216e..7c4a3d9441 100644 --- a/cl/alerts/management/commands/cl_send_recap_alerts.py +++ b/cl/alerts/management/commands/cl_send_recap_alerts.py @@ -38,6 +38,7 @@ ) from cl.search.exception import ( BadProximityQuery, + DisallowedWildcardPattern, UnbalancedParenthesesQuery, UnbalancedQuotesQuery, ) @@ -455,6 +456,7 @@ def query_alerts( UnbalancedParenthesesQuery, UnbalancedQuotesQuery, BadProximityQuery, + DisallowedWildcardPattern, TransportError, ConnectionError, RequestError, diff --git a/cl/lib/elasticsearch_utils.py b/cl/lib/elasticsearch_utils.py index d23e4b8288..a33118310b 100644 --- a/cl/lib/elasticsearch_utils.py +++ b/cl/lib/elasticsearch_utils.py @@ -3094,6 +3094,7 @@ def do_es_api_query( UnbalancedParenthesesQuery, UnbalancedQuotesQuery, BadProximityQuery, + DisallowedWildcardPattern, ) as e: raise ElasticBadRequestError(detail=e.message) diff --git a/cl/search/exception.py b/cl/search/exception.py index 926ae17495..0d51d152d3 100644 --- a/cl/search/exception.py +++ b/cl/search/exception.py @@ -61,4 +61,4 @@ class ElasticBadRequestError(APIException): class DisallowedWildcardPattern(SyntaxQueryError): """Query contains a disallowed wildcard pattern""" - message = "The query contains a disallowed wildcard pattern." + message = "The query contains a disallowed expensive wildcard pattern." diff --git a/cl/search/feeds.py b/cl/search/feeds.py index 435506cf5d..0e42d955ba 100644 --- a/cl/search/feeds.py +++ b/cl/search/feeds.py @@ -19,6 +19,7 @@ from cl.search.documents import ESRECAPDocument, OpinionClusterDocument from cl.search.exception import ( BadProximityQuery, + DisallowedWildcardPattern, UnbalancedParenthesesQuery, UnbalancedQuotesQuery, ) @@ -255,6 +256,7 @@ def wrapped_view(request, *args, **kwargs): UnbalancedParenthesesQuery, UnbalancedQuotesQuery, BadProximityQuery, + DisallowedWildcardPattern, ApiError, ) as e: logger.warning("Couldn't load the feed page. Error was: %s", e) diff --git a/cl/search/tests/tests.py b/cl/search/tests/tests.py index 9e38f46b49..9c06e7e6e0 100644 --- a/cl/search/tests/tests.py +++ b/cl/search/tests/tests.py @@ -1069,6 +1069,7 @@ def test_support_search_connectors(self) -> None: for test_case in tests: with self.subTest(label=test_case["label"]): + # Frontend response = self.client.get( reverse("show_results"), test_case["search_params"], @@ -1087,6 +1088,24 @@ def test_support_search_connectors(self) -> None: msg=f"Failed on: {test_case['label']} missing {expected_str}", ) + # API + api_response = self.client.get( + reverse("search-list", kwargs={"version": "v4"}), + test_case["search_params"], + ) + self.assertEqual( + len(api_response.data["results"]), + test_case["expected_count"], + msg=f"Failed on API: {test_case['label']}", + ) + decoded_content = api_response.content.decode() + for expected_str in test_case["expected_in_content"]: + self.assertIn( + expected_str, + decoded_content, + msg=f"Failed on Frontend: {test_case['label']} missing {expected_str}", + ) + def test_support_search_connectors_filters(self) -> None: """Verify that new supported custom search connectors yield the expected results. @@ -1137,6 +1156,7 @@ def test_support_search_connectors_filters(self) -> None: for test_case in tests: with self.subTest(label=test_case["label"]): + # Frontend response = self.client.get( reverse("show_results"), test_case["search_params"], @@ -1152,7 +1172,25 @@ def test_support_search_connectors_filters(self) -> None: self.assertIn( expected_str, decoded_content, - msg=f"Failed on: {test_case['label']} missing {expected_str}", + msg=f"Failed on Frontend: {test_case['label']} missing {expected_str}", + ) + + # API + api_response = self.client.get( + reverse("search-list", kwargs={"version": "v4"}), + test_case["search_params"], + ) + self.assertEqual( + len(api_response.data["results"]), + test_case["expected_count"], + msg=f"Failed on API: {test_case['label']}", + ) + decoded_content = api_response.content.decode() + for expected_str in test_case["expected_in_content"]: + self.assertIn( + expected_str, + decoded_content, + msg=f"Failed on Frontend: {test_case['label']} missing {expected_str}", ) def test_disallowed_wildcard_pattern(self) -> None: @@ -1210,6 +1248,30 @@ def test_disallowed_wildcard_pattern(self) -> None: msg=f"Failed on: {test_case['label']}, no disallowed wildcard pattern error.", ) + # API V4 + api_response = self.client.get( + reverse("search-list", kwargs={"version": "v4"}), + test_case["search_params"], + ) + self.assertEqual(api_response.status_code, 400) + self.assertEqual( + api_response.data["detail"], + "The query contains a disallowed expensive wildcard pattern.", + msg="Failed for V4", + ) + + # API V3 + api_response = self.client.get( + reverse("search-list", kwargs={"version": "v3"}), + test_case["search_params"], + ) + self.assertEqual(api_response.status_code, 400) + self.assertEqual( + api_response.data["detail"], + "The query contains a disallowed expensive wildcard pattern.", + msg="Failed for V3", + ) + class SearchAPIV4CommonTest(ESIndexTestCase, TestCase): """Common tests for the Search API V4 endpoints."""