From f528a6b39c546bc23a7e98ed45ef2fba0b8bf719 Mon Sep 17 00:00:00 2001 From: Keenan Nemetz Date: Thu, 17 Oct 2024 10:38:54 -0700 Subject: [PATCH] fix(i): Panic in object equal filter (#3143) ## Relevant issue(s) Resolves #3141 ## Description This PR fixes a bug where the object equality check would panic when comparing with a non object type. ## Tasks - [x] I made sure the code is well commented, particularly hard-to-understand areas. - [x] I made sure the repository-held documentation is changed accordingly. - [x] I made sure the pull request title adheres to the conventional commit style (the subset used in the project can be found in [tools/configs/chglog/config.yml](tools/configs/chglog/config.yml)). - [x] I made sure to discuss its limitations such as threats to validity, vulnerability to mistake and misuse, robustness to invalidation of assumptions, resource requirements, ... ## How has this been tested? Added integration test. Specify the platform(s) on which this was tested: - MacOS --- internal/connor/connor.go | 13 ++-- internal/connor/eq.go | 4 +- tests/integration/query/json/with_eq_test.go | 62 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/internal/connor/connor.go b/internal/connor/connor.go index a7a8290dbe..da4f7f5b4d 100644 --- a/internal/connor/connor.go +++ b/internal/connor/connor.go @@ -1,8 +1,11 @@ -/* -Package connor provides a domain-specific language to express conditions against data. - -It is derived from https://github.com/SierraSoftworks/connor. -*/ +// Package connor provides a domain-specific language to express conditions against data. +// +// It is derived from https://github.com/SierraSoftworks/connor. +// +// Note to developers: +// Never assume that the data given to an operator is of a certain type. +// Operators should work with any data type so that untyped data +// such as JSON can be filtered as expected. package connor const ( diff --git a/internal/connor/eq.go b/internal/connor/eq.go index 6b9f56293a..65c17356f0 100644 --- a/internal/connor/eq.go +++ b/internal/connor/eq.go @@ -75,8 +75,8 @@ func objectsEqual(condition map[string]any, data any) (bool, error) { if data == nil { return condition == nil, nil } - d := data.(map[string]any) - if len(d) != len(condition) { + d, ok := data.(map[string]any) + if !ok || len(d) != len(condition) { return false, nil } for k, v := range d { diff --git a/tests/integration/query/json/with_eq_test.go b/tests/integration/query/json/with_eq_test.go index 4434412a1a..d319148915 100644 --- a/tests/integration/query/json/with_eq_test.go +++ b/tests/integration/query/json/with_eq_test.go @@ -162,3 +162,65 @@ func TestQueryJSON_WithEqualFilterWithNullValue_ShouldFilter(t *testing.T) { testUtils.ExecuteTestCase(t, test) } + +func TestQueryJSON_WithEqualFilterWithAllTypes_ShouldFilter(t *testing.T) { + test := testUtils.TestCase{ + Description: "Simple query with JSON _eq filter all types", + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type Users { + Name: String + Custom: JSON + } + `, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Shahzad", + "Custom": "32" + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Andy", + "Custom": [1, 2] + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Fred", + "Custom": {"one": 1} + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Custom": false + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "David", + "Custom": 32 + }`, + }, + testUtils.Request{ + Request: `query { + Users(filter: {Custom: {_eq: {one: 1}}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Fred", + }, + }, + }, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +}