Browse Source

fix(search): We don't currently support bool operators (#18944)

- This causes an error when a query is interpreted as a boolean
  operator. eg. `user.email:test OR user.email:foo`
- This impacts: alerts, discover, issue events search
- Previously these wouldn't error, but appear to run as if there was no
  query.
William Mak 4 years ago
parent
commit
887bb45c54

+ 11 - 3
src/sentry/api/event_search.py

@@ -279,6 +279,10 @@ class SearchVisitor(NodeVisitor):
 
     unwrapped_exceptions = (InvalidSearchQuery,)
 
+    def __init__(self, allow_boolean=True):
+        self.allow_boolean = allow_boolean
+        super(SearchVisitor, self).__init__()
+
     @cached_property
     def key_mappings_lookup(self):
         lookup = {}
@@ -619,6 +623,10 @@ class SearchVisitor(NodeVisitor):
         return node.text
 
     def visit_boolean_operator(self, node, children):
+        if not self.allow_boolean:
+            raise InvalidSearchQuery(
+                'Boolean statements containing "OR" or "AND" are not supported in this search'
+            )
         return node.text
 
     def visit_value(self, node, children):
@@ -657,7 +665,7 @@ class SearchVisitor(NodeVisitor):
         return children or node
 
 
-def parse_search_query(query):
+def parse_search_query(query, allow_boolean=True):
     try:
         tree = event_search_grammar.parse(query)
     except IncompleteParseError as e:
@@ -670,7 +678,7 @@ def parse_search_query(query):
                 "This is commonly caused by unmatched parentheses. Enclose any text in double quotes.",
             )
         )
-    return SearchVisitor().visit(tree)
+    return SearchVisitor(allow_boolean).visit(tree)
 
 
 def convert_aggregate_filter_to_snuba_query(aggregate_filter, params):
@@ -806,7 +814,7 @@ def get_filter(query=None, params=None):
     parsed_terms = []
     if query is not None:
         try:
-            parsed_terms = parse_search_query(query)
+            parsed_terms = parse_search_query(query, allow_boolean=False)
         except ParseError as e:
             raise InvalidSearchQuery(
                 u"Parse error: {} (column {:d})".format(e.expr.name, e.column())

+ 13 - 0
tests/snuba/api/endpoints/test_organization_events_v2.py

@@ -42,6 +42,19 @@ class OrganizationEventsV2EndpointTest(APITestCase, SnubaTestCase):
         assert response.status_code == 200, response.content
         assert len(response.data) == 0
 
+    def test_or_errors(self):
+        self.login_as(user=self.user)
+        self.create_project()
+
+        with self.feature("organizations:discover-basic"):
+            response = self.client.get(
+                self.url,
+                {"field": ["id"], "query": "user.email:test OR user.email:foo"},
+                format="json",
+            )
+
+        assert response.status_code == 400
+
     def test_multi_project_feature_gate_rejection(self):
         self.login_as(user=self.user)
         team = self.create_team(organization=self.organization, members=[self.user])