diff --git a/services/search/pkg/search/scope.go b/services/search/pkg/search/scope.go index ddf966adee..36597ec658 100644 --- a/services/search/pkg/search/scope.go +++ b/services/search/pkg/search/scope.go @@ -15,15 +15,15 @@ var ErrNestedScope = errors.New("scope: must be a top-level restriction") // ExtractScope takes the scope restriction out of the query, together with // the operator that joined it, and returns the remaining nodes and the scope. func ExtractScope(nodes []ast.Node) ([]ast.Node, string, error) { + for _, n := range nodes { + if group, ok := n.(*ast.GroupNode); ok && hasKey(group.Nodes, "scope") { + return nil, "", ErrNestedScope + } + } + for i, n := range nodes { node, ok := n.(*ast.StringNode) - if !ok { - if group, isGroup := n.(*ast.GroupNode); isGroup && hasKey(group.Nodes, "scope") { - return nil, "", ErrNestedScope - } - continue - } - if !strings.EqualFold(node.Key, "scope") { + if !ok || !strings.EqualFold(node.Key, "scope") { continue } diff --git a/services/search/pkg/search/scope_test.go b/services/search/pkg/search/scope_test.go index 80cd6daa3a..aab6451a9a 100644 --- a/services/search/pkg/search/scope_test.go +++ b/services/search/pkg/search/scope_test.go @@ -30,12 +30,15 @@ var _ = DescribeTable("ExtractScope", Entry("a quoted value is not a scope", `name:"scope:1$2!3"`, `name:"scope:1$2!3"`, ``), ) -var _ = Describe("ExtractScope", func() { - It("rejects a scope inside a group", func() { - _, _, err := search.ExtractScope(parse(`name:x AND (scope:1$2!3 OR tag:y)`).Nodes) +var _ = DescribeTable("ExtractScope rejects a nested scope", + func(query string) { + _, _, err := search.ExtractScope(parse(query).Nodes) Expect(err).To(MatchError(search.ErrNestedScope)) - }) -}) + }, + Entry("inside a group", `name:x AND (scope:1$2!3 OR tag:y)`), + Entry("inside a nested group", `name:x AND (tag:y OR (scope:1$2!3))`), + Entry("after a top-level scope", `scope:1$2!3 AND (scope:1$2!4)`), +) var _ = DescribeTable("ExpandFavorites", func(query, want string) {