diff --git a/services/search/pkg/opensearch/backend.go b/services/search/pkg/opensearch/backend.go index 24936217ac..000b24ebf1 100644 --- a/services/search/pkg/opensearch/backend.go +++ b/services/search/pkg/opensearch/backend.go @@ -9,6 +9,7 @@ import ( storageProvider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" opensearchgoAPI "github.com/opensearch-project/opensearch-go/v4/opensearchapi" + "github.com/opencloud-eu/reva/v2/pkg/errtypes" "github.com/opencloud-eu/reva/v2/pkg/storagespace" "github.com/opencloud-eu/reva/v2/pkg/utils" @@ -17,6 +18,7 @@ import ( searchService "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/search/v0" "github.com/opencloud-eu/opencloud/services/search/pkg/opensearch/internal/convert" "github.com/opencloud-eu/opencloud/services/search/pkg/opensearch/internal/osu" + searchQuery "github.com/opencloud-eu/opencloud/services/search/pkg/query" "github.com/opencloud-eu/opencloud/services/search/pkg/search" ) @@ -68,7 +70,10 @@ func NewBackend(index string, client *opensearchgoAPI.Client) (*Backend, error) func (b *Backend) Search(ctx context.Context, sir *searchService.SearchIndexRequest) (*searchService.SearchIndexResponse, error) { boolQuery, err := convert.KQLToOpenSearchBoolQuery(sir.Query) - if err != nil { + switch { + case searchQuery.IsValidationError(err): + return nil, errtypes.BadRequest(err.Error()) + case err != nil: return nil, fmt.Errorf("failed to convert KQL query to OpenSearch bool query: %w", err) } diff --git a/services/search/pkg/opensearch/backend_test.go b/services/search/pkg/opensearch/backend_test.go index 74b41fa674..a8579180ac 100644 --- a/services/search/pkg/opensearch/backend_test.go +++ b/services/search/pkg/opensearch/backend_test.go @@ -11,6 +11,8 @@ import ( opensearchgo "github.com/opensearch-project/opensearch-go/v4" opensearchgoAPI "github.com/opensearch-project/opensearch-go/v4/opensearchapi" + "github.com/opencloud-eu/reva/v2/pkg/errtypes" + searchService "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/search/v0" "github.com/opencloud-eu/opencloud/services/search/pkg/opensearch" opensearchtest "github.com/opencloud-eu/opencloud/services/search/pkg/opensearch/internal/test" @@ -595,4 +597,17 @@ var _ = Describe("Backend", func() { ) }) + Describe("SearchWithAnInvalidQuery", func() { + const indexName = "opencloud-test-engine-search-invalid-query" + + It("answers with a bad request", func() { + backend, tc := newBackend(indexName) + deleteIndexOnCleanup(tc, indexName) + + _, err := backend.Search(context.Background(), &searchService.SearchIndexRequest{Query: "AND mediatype:document"}) + Expect(err).To(HaveOccurred()) + Expect(err).To(BeAssignableToTypeOf(errtypes.BadRequest(""))) + Expect(err.Error()).To(Equal(`error: bad request: the expression can't begin from a binary operator: 'AND'`)) + }) + }) }) diff --git a/services/search/pkg/opensearch/internal/convert/kql_query.go b/services/search/pkg/opensearch/internal/convert/kql_query.go index f04e577077..f824990e6d 100644 --- a/services/search/pkg/opensearch/internal/convert/kql_query.go +++ b/services/search/pkg/opensearch/internal/convert/kql_query.go @@ -14,7 +14,7 @@ var ( func KQLToOpenSearchBoolQuery(kqlQuery string) (*osu.BoolQuery, error) { kqlAst, err := kql.Builder{}.Build(kqlQuery) if err != nil { - return nil, fmt.Errorf("failed to build query: %w", err) + return nil, err } kqlNodes, err := ExpandKQL(kqlAst.Nodes) diff --git a/services/search/pkg/query/error.go b/services/search/pkg/query/error.go index a25148d977..27fde9541e 100644 --- a/services/search/pkg/query/error.go +++ b/services/search/pkg/query/error.go @@ -1,6 +1,7 @@ package query import ( + "errors" "fmt" "github.com/opencloud-eu/opencloud/pkg/ast" @@ -38,10 +39,16 @@ func (e UnsupportedTimeRangeError) Error() string { return fmt.Sprintf("unable to convert '%v' to a time range", e.Value) } +// IsValidationError says whether the query itself is at fault, which makes it a +// bad request and not an error of ours. func IsValidationError(err error) bool { - switch err.(type) { - case *StartsWithBinaryOperatorError, *NamedGroupInvalidNodesError, *UnsupportedTimeRangeError: - return true - } - return false + var ( + startsWithBinaryOperator *StartsWithBinaryOperatorError + namedGroupInvalidNodes *NamedGroupInvalidNodesError + unsupportedTimeRange *UnsupportedTimeRangeError + ) + + return errors.As(err, &startsWithBinaryOperator) || + errors.As(err, &namedGroupInvalidNodes) || + errors.As(err, &unsupportedTimeRange) }