From 3675e39b9212d80bc2b38712a9c14bd08fdcdd94 Mon Sep 17 00:00:00 2001 From: Himank Chaudhary Date: Wed, 17 Aug 2022 19:00:03 -0700 Subject: [PATCH] fix: disable additional properties on nested objects as well --- schema/collection.go | 10 +++++ schema/collection_test.go | 57 +++++++++++++++++++++++++++++ server/services/v1/observability.go | 1 - 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/schema/collection.go b/schema/collection.go index 870c2785c..911303a9f 100644 --- a/schema/collection.go +++ b/schema/collection.go @@ -60,6 +60,15 @@ type DefaultCollection struct { QueryableFields []*QueryableField } +func disableAdditionalProperties(properties map[string]*jsonschema.Schema) { + for _, p := range properties { + p.AdditionalProperties = false + if len(p.Properties) > 0 { + disableAdditionalProperties(p.Properties) + } + } +} + func NewDefaultCollection(name string, id uint32, schVer int, fields []*Field, indexes *Indexes, schema jsoniter.RawMessage, searchCollectionName string) *DefaultCollection { url := name + ".json" compiler := jsonschema.NewCompiler() @@ -76,6 +85,7 @@ func NewDefaultCollection(name string, id uint32, schVer int, fields []*Field, i // Tigris doesn't allow additional fields as part of the write requests. Setting it to false ensures strict // schema validation. validator.AdditionalProperties = false + disableAdditionalProperties(validator.Properties) queryableFields := buildQueryableFields(fields) diff --git a/schema/collection_test.go b/schema/collection_test.go index 6ef5db66c..aab7db91f 100644 --- a/schema/collection_test.go +++ b/schema/collection_test.go @@ -292,3 +292,60 @@ func TestCollection_SearchSchema(t *testing.T) { require.Equal(t, expFlattenedFields[i], f.Name) } } + +func TestCollection_AdditionalProperties(t *testing.T) { + reqSchema := []byte(`{ + "title": "t1", + "properties": { + "id": { + "type": "integer" + }, + "simple_object": { + "type": "object", + "properties": { + "name": { "type": "string" } + } + }, + "complex_object": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "obj": { + "type": "object", + "properties": { + "name": { "type": "string" } + } + } + } + } + }, + "primary_key": ["id"] + }`) + + cases := []struct { + document []byte + expError string + }{ + { + document: []byte(`{"id": 1, "simple_object": {"name": "hello", "price": 1.01}}`), + expError: "json schema validation failed for field 'simple_object' reason 'additionalProperties 'price' not allowed'", + }, { + document: []byte(`{"id": 1, "complex_object": {"name": "hello", "price": 1.01}}`), + expError: "json schema validation failed for field 'complex_object' reason 'additionalProperties 'price' not allowed'", + }, { + document: []byte(`{"id": 1, "complex_object": {"name": "hello", "obj": {"name": "hello", "price": 1.01}}}`), + expError: "json schema validation failed for field 'complex_object/obj' reason 'additionalProperties 'price' not allowed'", + }, + } + for _, c := range cases { + schFactory, err := Build("t1", reqSchema) + require.NoError(t, err) + coll := NewDefaultCollection("t1", 1, 1, schFactory.Fields, schFactory.Indexes, schFactory.Schema, "t1") + + dec := jsoniter.NewDecoder(bytes.NewReader(c.document)) + dec.UseNumber() + var v interface{} + require.NoError(t, dec.Decode(&v)) + require.Equal(t, c.expError, coll.Validate(v).Error()) + } +} diff --git a/server/services/v1/observability.go b/server/services/v1/observability.go index 249b68639..0b7976c25 100644 --- a/server/services/v1/observability.go +++ b/server/services/v1/observability.go @@ -84,7 +84,6 @@ func (dd Datadog) QueryTimeSeriesMetrics(ctx context.Context, req *api.QueryTime if err != nil { return nil, api.Errorf(api.Code_INTERNAL, "Failed to query metrics: reason = "+err.Error()) } - fmt.Println(ddQuery) q.Add("query", ddQuery) ddReq.URL.RawQuery = q.Encode() ddReq.Header.Add(AcceptHeader, ApplicationJsonHeaderVal)