From 8181a15500e95e1f7da073b336c6967b630b7e5c Mon Sep 17 00:00:00 2001 From: Keenan Nemetz Date: Thu, 17 Oct 2024 17:43:46 -0700 Subject: [PATCH] fix: Validate GraphQL schemas (#3152) ## Relevant issue(s) Resolves #3151 ## Description This PR fixes an issue where GraphQL schemas were never validated. ## 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? Updated integration tests. Specify the platform(s) on which this was tested: - MacOS --- examples/schema/user.graphql | 2 +- internal/core/parser.go | 2 +- internal/db/schema.go | 2 +- internal/db/view.go | 2 +- internal/request/graphql/parser.go | 14 +- internal/request/graphql/schema/collection.go | 24 -- .../graphql/schema/index_parse_test.go | 27 +-- internal/request/graphql/schema/manager.go | 214 +++--------------- internal/request/graphql/schema/schema.go | 206 +++++++++++++++++ .../request/graphql/schema/types/types.go | 4 +- tests/bench/query/planner/utils.go | 3 +- .../reject_invalid_arg_type_on_schema_test.go | 4 +- .../with_default_fields_test.go | 2 +- tests/integration/encryption/commit_test.go | 4 +- .../integration/encryption/peer_share_test.go | 4 +- tests/integration/encryption/query_test.go | 2 +- tests/integration/encryption/utils.go | 2 +- tests/integration/issues/2566_test.go | 4 +- tests/integration/issues/2569_test.go | 6 +- .../mutation/create/crdt/pcounter_test.go | 2 +- .../mutation/create/crdt/pncounter_test.go | 2 +- .../mutation/update/crdt/pcounter_test.go | 10 +- .../mutation/update/crdt/pncounter_test.go | 12 +- .../net/simple/peer/crdt/pcounter_test.go | 4 +- .../net/simple/peer/crdt/pncounter_test.go | 4 +- .../peer_replicator/crdt/pcounter_test.go | 4 +- .../peer_replicator/crdt/pncounter_test.go | 4 +- .../simple/replicator/crdt/pcounter_test.go | 2 +- .../simple/replicator/crdt/pncounter_test.go | 2 +- .../query/simple/with_cid_doc_id_test.go | 8 +- tests/integration/schema/crdt_type_test.go | 14 +- tests/integration/utils.go | 2 +- 32 files changed, 306 insertions(+), 292 deletions(-) create mode 100644 internal/request/graphql/schema/schema.go diff --git a/examples/schema/user.graphql b/examples/schema/user.graphql index 9390a28f64..fbdea6a418 100644 --- a/examples/schema/user.graphql +++ b/examples/schema/user.graphql @@ -2,5 +2,5 @@ type User { name: String age: Int verified: Boolean - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } diff --git a/internal/core/parser.go b/internal/core/parser.go index 8955314e26..accb192373 100644 --- a/internal/core/parser.go +++ b/internal/core/parser.go @@ -55,7 +55,7 @@ type Parser interface { // The parsing should validate the syntax, but not validate what that syntax expresses // is valid or not, i.e. we don't want the parser to make remote calls to verify the // policy description is valid or not (that is the callers responsiblity). - ParseSDL(ctx context.Context, schemaString string) ([]client.CollectionDefinition, error) + ParseSDL(sdl string) ([]client.CollectionDefinition, error) // Adds the given schema to this parser's model. // diff --git a/internal/db/schema.go b/internal/db/schema.go index f1906feb54..b5e2ff4e61 100644 --- a/internal/db/schema.go +++ b/internal/db/schema.go @@ -38,7 +38,7 @@ func (db *db) addSchema( ctx context.Context, schemaString string, ) ([]client.CollectionDescription, error) { - newDefinitions, err := db.parser.ParseSDL(ctx, schemaString) + newDefinitions, err := db.parser.ParseSDL(schemaString) if err != nil { return nil, err } diff --git a/internal/db/view.go b/internal/db/view.go index 23bb3cad42..8fb54ccb24 100644 --- a/internal/db/view.go +++ b/internal/db/view.go @@ -38,7 +38,7 @@ func (db *db) addView( // with the all calls to the parser appart from `ParseSDL` when we implement the DQL stuff. query := fmt.Sprintf(`query { %s }`, inputQuery) - newDefinitions, err := db.parser.ParseSDL(ctx, sdl) + newDefinitions, err := db.parser.ParseSDL(sdl) if err != nil { return nil, err } diff --git a/internal/request/graphql/parser.go b/internal/request/graphql/parser.go index 26e09230ad..7ff23394fa 100644 --- a/internal/request/graphql/parser.go +++ b/internal/request/graphql/parser.go @@ -94,19 +94,11 @@ func (p *parser) Parse(ast *ast.Document, options *client.GQLOptions) (*request. return nil, errors } - query, parsingErrors := defrap.ParseRequest(*schema, ast, options) - if len(parsingErrors) > 0 { - return nil, parsingErrors - } - - return query, nil + return defrap.ParseRequest(*schema, ast, options) } -func (p *parser) ParseSDL(ctx context.Context, schemaString string) ( - []client.CollectionDefinition, - error, -) { - return schema.FromString(ctx, schemaString) +func (p *parser) ParseSDL(sdl string) ([]client.CollectionDefinition, error) { + return p.schemaManager.ParseSDL(sdl) } func (p *parser) SetSchema(ctx context.Context, txn datastore.Txn, collections []client.CollectionDefinition) error { diff --git a/internal/request/graphql/schema/collection.go b/internal/request/graphql/schema/collection.go index e2bf4a2455..7085ba5c97 100644 --- a/internal/request/graphql/schema/collection.go +++ b/internal/request/graphql/schema/collection.go @@ -11,15 +11,12 @@ package schema import ( - "context" "fmt" "sort" "strings" gql "github.com/sourcenetwork/graphql-go" "github.com/sourcenetwork/graphql-go/language/ast" - gqlp "github.com/sourcenetwork/graphql-go/language/parser" - "github.com/sourcenetwork/graphql-go/language/source" "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client" @@ -50,27 +47,6 @@ var TypeToDefaultPropName = map[string]string{ typeBlob: types.DefaultDirectivePropBlob, } -// FromString parses a GQL SDL string into a set of collection descriptions. -func FromString(ctx context.Context, schemaString string) ( - []client.CollectionDefinition, - error, -) { - source := source.NewSource(&source.Source{ - Body: []byte(schemaString), - }) - - doc, err := gqlp.Parse( - gqlp.ParseParams{ - Source: source, - }, - ) - if err != nil { - return nil, err - } - - return fromAst(doc) -} - // fromAst parses a GQL AST into a set of collection descriptions. func fromAst(doc *ast.Document) ( []client.CollectionDefinition, diff --git a/internal/request/graphql/schema/index_parse_test.go b/internal/request/graphql/schema/index_parse_test.go index e10394f38d..df813f14e2 100644 --- a/internal/request/graphql/schema/index_parse_test.go +++ b/internal/request/graphql/schema/index_parse_test.go @@ -11,7 +11,6 @@ package schema import ( - "context" "testing" "github.com/stretchr/testify/assert" @@ -132,12 +131,12 @@ func TestParseInvalidIndexOnStruct(t *testing.T) { { description: "unknown argument", sdl: `type user @index(unknown: "something", includes: [{field: "name"}]) {}`, - expectedErr: errIndexUnknownArgument, + expectedErr: `Unknown argument "unknown" on directive "@index".`, }, { description: "invalid index name type", sdl: `type user @index(name: 1, includes: [{field: "name"}]) {}`, - expectedErr: errIndexInvalidArgument, + expectedErr: `Argument "name" has invalid value 1`, }, { description: "index name starts with a number", @@ -162,17 +161,17 @@ func TestParseInvalidIndexOnStruct(t *testing.T) { { description: "invalid 'unique' value type", sdl: `type user @index(includes: [{field: "name"}], unique: "true") {}`, - expectedErr: errIndexInvalidArgument, + expectedErr: `Argument "unique" has invalid value "true"`, }, { description: "invalid 'includes' value type (not a list)", sdl: `type user @index(includes: "name") {}`, - expectedErr: errIndexInvalidArgument, + expectedErr: `Argument "includes" has invalid value "name"`, }, { description: "invalid 'includes' value type (not an object list)", sdl: `type user @index(includes: [1]) {}`, - expectedErr: errIndexInvalidArgument, + expectedErr: `Argument "includes" has invalid value [1]`, }, } @@ -334,14 +333,14 @@ func TestParseInvalidIndexOnField(t *testing.T) { sdl: `type user { name: String @index(field: "name") }`, - expectedErr: errIndexUnknownArgument, + expectedErr: `Unknown argument "field" on directive "@index`, }, { description: "invalid field index name type", sdl: `type user { name: String @index(name: 1) }`, - expectedErr: errIndexInvalidArgument, + expectedErr: `Argument "name" has invalid value 1`, }, { description: "field index name starts with a number", @@ -376,7 +375,7 @@ func TestParseInvalidIndexOnField(t *testing.T) { sdl: `type user { name: String @index(unique: "true") }`, - expectedErr: errIndexInvalidArgument, + expectedErr: `Argument "unique" has invalid value "true"`, }, } @@ -386,9 +385,10 @@ func TestParseInvalidIndexOnField(t *testing.T) { } func parseIndexAndTest(t *testing.T, testCase indexTestCase) { - ctx := context.Background() + schemaManager, err := NewSchemaManager() + require.NoError(t, err) - cols, err := FromString(ctx, testCase.sdl) + cols, err := schemaManager.ParseSDL(testCase.sdl) require.NoError(t, err, testCase.description) require.Equal(t, len(cols), 1, testCase.description) @@ -400,9 +400,10 @@ func parseIndexAndTest(t *testing.T, testCase indexTestCase) { } func parseInvalidIndexAndTest(t *testing.T, testCase invalidIndexTestCase) { - ctx := context.Background() + schemaManager, err := NewSchemaManager() + require.NoError(t, err) - _, err := FromString(ctx, testCase.sdl) + _, err = schemaManager.ParseSDL(testCase.sdl) assert.ErrorContains(t, err, testCase.expectedErr, testCase.description) } diff --git a/internal/request/graphql/schema/manager.go b/internal/request/graphql/schema/manager.go index 881c94c144..1a3f923ddc 100644 --- a/internal/request/graphql/schema/manager.go +++ b/internal/request/graphql/schema/manager.go @@ -11,9 +11,13 @@ package schema import ( - gql "github.com/sourcenetwork/graphql-go" + "errors" + + "github.com/sourcenetwork/defradb/client" - schemaTypes "github.com/sourcenetwork/defradb/internal/request/graphql/schema/types" + gql "github.com/sourcenetwork/graphql-go" + gqlp "github.com/sourcenetwork/graphql-go/language/parser" + "github.com/sourcenetwork/graphql-go/language/source" ) // SchemaManager creates an instanced management point @@ -26,40 +30,14 @@ type SchemaManager struct { // NewSchemaManager returns a new instance of a SchemaManager // with a new default type map func NewSchemaManager() (*SchemaManager, error) { - sm := &SchemaManager{} - - orderEnum := schemaTypes.OrderingEnum() - crdtEnum := schemaTypes.CRDTEnum() - explainEnum := schemaTypes.ExplainEnum() - - commitLinkObject := schemaTypes.CommitLinkObject() - commitObject := schemaTypes.CommitObject(commitLinkObject) - commitsOrderArg := schemaTypes.CommitsOrderArg(orderEnum) - - indexFieldInput := schemaTypes.IndexFieldInputObject(orderEnum) - - schema, err := gql.NewSchema(gql.SchemaConfig{ - Types: defaultTypes( - commitObject, - commitLinkObject, - commitsOrderArg, - orderEnum, - crdtEnum, - explainEnum, - indexFieldInput, - ), - Query: defaultQueryType(commitObject, commitsOrderArg), - Mutation: defaultMutationType(), - Directives: defaultDirectivesType(crdtEnum, explainEnum, orderEnum, indexFieldInput), - Subscription: defaultSubscriptionType(), - }) + schema, err := defaultSchema() if err != nil { - return sm, err + return nil, err + } + sm := &SchemaManager{ + schema: schema, } - sm.schema = schema - sm.NewGenerator() - return sm, nil } @@ -99,162 +77,24 @@ func (s *SchemaManager) ResolveTypes() error { return s.schema.AppendType(query) } -// @todo: Use a better default Query type -func defaultQueryType(commitObject *gql.Object, commitsOrderArg *gql.InputObject) *gql.Object { - queryCommits := schemaTypes.QueryCommits(commitObject, commitsOrderArg) - queryLatestCommits := schemaTypes.QueryLatestCommits(commitObject) - - return gql.NewObject(gql.ObjectConfig{ - Name: "Query", - Fields: gql.Fields{ - "_": &gql.Field{ - Name: "_", - Type: gql.Boolean, - }, - - // database API queries - queryCommits.Name: queryCommits, - queryLatestCommits.Name: queryLatestCommits, - }, - }) -} - -func defaultMutationType() *gql.Object { - return gql.NewObject(gql.ObjectConfig{ - Name: "Mutation", - Fields: gql.Fields{ - "_": &gql.Field{ - Name: "_", - Type: gql.Boolean, - }, - }, +func (s *SchemaManager) ParseSDL(sdl string) ([]client.CollectionDefinition, error) { + src := source.NewSource(&source.Source{ + Body: []byte(sdl), }) -} - -func defaultSubscriptionType() *gql.Object { - return gql.NewObject(gql.ObjectConfig{ - Name: "Subscription", - Fields: gql.Fields{ - "_": &gql.Field{ - Name: "_", - Type: gql.Boolean, - }, - }, + doc, err := gqlp.Parse(gqlp.ParseParams{ + Source: src, }) -} - -// default directives type. -func defaultDirectivesType( - crdtEnum *gql.Enum, - explainEnum *gql.Enum, - orderEnum *gql.Enum, - indexFieldInput *gql.InputObject, -) []*gql.Directive { - return []*gql.Directive{ - schemaTypes.CRDTFieldDirective(crdtEnum), - schemaTypes.DefaultDirective(), - schemaTypes.ExplainDirective(explainEnum), - schemaTypes.PolicyDirective(), - schemaTypes.IndexDirective(orderEnum, indexFieldInput), - schemaTypes.PrimaryDirective(), - schemaTypes.RelationDirective(), - schemaTypes.MaterializedDirective(), - } -} - -func inlineArrayTypes() []gql.Type { - return []gql.Type{ - gql.Boolean, - gql.Float, - gql.Int, - gql.String, - gql.NewNonNull(gql.Boolean), - gql.NewNonNull(gql.Float), - gql.NewNonNull(gql.Int), - gql.NewNonNull(gql.String), + if err != nil { + return nil, err } -} - -// default type map includes all the native scalar types -func defaultTypes( - commitObject *gql.Object, - commitLinkObject *gql.Object, - commitsOrderArg *gql.InputObject, - orderEnum *gql.Enum, - crdtEnum *gql.Enum, - explainEnum *gql.Enum, - indexFieldInput *gql.InputObject, -) []gql.Type { - blobScalarType := schemaTypes.BlobScalarType() - jsonScalarType := schemaTypes.JSONScalarType() - - idOpBlock := schemaTypes.IDOperatorBlock() - intOpBlock := schemaTypes.IntOperatorBlock() - floatOpBlock := schemaTypes.FloatOperatorBlock() - booleanOpBlock := schemaTypes.BooleanOperatorBlock() - stringOpBlock := schemaTypes.StringOperatorBlock() - blobOpBlock := schemaTypes.BlobOperatorBlock(blobScalarType) - dateTimeOpBlock := schemaTypes.DateTimeOperatorBlock() - - notNullIntOpBlock := schemaTypes.NotNullIntOperatorBlock() - notNullFloatOpBlock := schemaTypes.NotNullFloatOperatorBlock() - notNullBooleanOpBlock := schemaTypes.NotNullBooleanOperatorBlock() - notNullStringOpBlock := schemaTypes.NotNullStringOperatorBlock() - notNullBlobOpBlock := schemaTypes.NotNullBlobOperatorBlock(blobScalarType) - - return []gql.Type{ - // Base Scalar types - gql.Boolean, - gql.DateTime, - gql.Float, - gql.ID, - gql.Int, - gql.String, - - // Custom Scalar types - blobScalarType, - jsonScalarType, - - // Base Query types - - // Sort/Order enum - orderEnum, - - // Filter scalar blocks - idOpBlock, - intOpBlock, - floatOpBlock, - booleanOpBlock, - stringOpBlock, - blobOpBlock, - dateTimeOpBlock, - - // Filter non null scalar blocks - notNullIntOpBlock, - notNullFloatOpBlock, - notNullBooleanOpBlock, - notNullStringOpBlock, - notNullBlobOpBlock, - - // Filter scalar list blocks - schemaTypes.IntListOperatorBlock(intOpBlock), - schemaTypes.FloatListOperatorBlock(floatOpBlock), - schemaTypes.BooleanListOperatorBlock(booleanOpBlock), - schemaTypes.StringListOperatorBlock(stringOpBlock), - - // Filter non null scalar list blocks - schemaTypes.NotNullIntListOperatorBlock(notNullIntOpBlock), - schemaTypes.NotNullFloatListOperatorBlock(notNullFloatOpBlock), - schemaTypes.NotNullBooleanListOperatorBlock(notNullBooleanOpBlock), - schemaTypes.NotNullStringListOperatorBlock(notNullStringOpBlock), - - commitsOrderArg, - commitLinkObject, - commitObject, - - crdtEnum, - explainEnum, - - indexFieldInput, + // The user provided SDL must be validated using the latest generated schema + // so that relations to other user defined types do not return an error. + validation := gql.ValidateDocument(&s.schema, doc, gql.SpecifiedRules) + if !validation.IsValid { + for _, e := range validation.Errors { + err = errors.Join(err, e) + } + return nil, err } + return fromAst(doc) } diff --git a/internal/request/graphql/schema/schema.go b/internal/request/graphql/schema/schema.go new file mode 100644 index 0000000000..d18911c929 --- /dev/null +++ b/internal/request/graphql/schema/schema.go @@ -0,0 +1,206 @@ +// Copyright 2024 Democratized Data Foundation +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package schema + +import ( + "github.com/sourcenetwork/defradb/internal/request/graphql/schema/types" + + gql "github.com/sourcenetwork/graphql-go" +) + +// defaultSchema returns a new gql.Schema containing the default type definitions. +func defaultSchema() (gql.Schema, error) { + orderEnum := types.OrderingEnum() + crdtEnum := types.CRDTEnum() + explainEnum := types.ExplainEnum() + + commitLinkObject := types.CommitLinkObject() + commitObject := types.CommitObject(commitLinkObject) + commitsOrderArg := types.CommitsOrderArg(orderEnum) + + indexFieldInput := types.IndexFieldInputObject(orderEnum) + + return gql.NewSchema(gql.SchemaConfig{ + Types: defaultTypes( + commitObject, + commitLinkObject, + commitsOrderArg, + orderEnum, + crdtEnum, + explainEnum, + indexFieldInput, + ), + Query: defaultQueryType(commitObject, commitsOrderArg), + Mutation: defaultMutationType(), + Directives: defaultDirectivesType(crdtEnum, explainEnum, orderEnum, indexFieldInput), + Subscription: defaultSubscriptionType(), + }) +} + +// @todo: Use a better default Query type +func defaultQueryType(commitObject *gql.Object, commitsOrderArg *gql.InputObject) *gql.Object { + queryCommits := types.QueryCommits(commitObject, commitsOrderArg) + queryLatestCommits := types.QueryLatestCommits(commitObject) + + return gql.NewObject(gql.ObjectConfig{ + Name: "Query", + Fields: gql.Fields{ + "_": &gql.Field{ + Name: "_", + Type: gql.Boolean, + }, + + // database API queries + queryCommits.Name: queryCommits, + queryLatestCommits.Name: queryLatestCommits, + }, + }) +} + +func defaultMutationType() *gql.Object { + return gql.NewObject(gql.ObjectConfig{ + Name: "Mutation", + Fields: gql.Fields{ + "_": &gql.Field{ + Name: "_", + Type: gql.Boolean, + }, + }, + }) +} + +func defaultSubscriptionType() *gql.Object { + return gql.NewObject(gql.ObjectConfig{ + Name: "Subscription", + Fields: gql.Fields{ + "_": &gql.Field{ + Name: "_", + Type: gql.Boolean, + }, + }, + }) +} + +// default directives type. +func defaultDirectivesType( + crdtEnum *gql.Enum, + explainEnum *gql.Enum, + orderEnum *gql.Enum, + indexFieldInput *gql.InputObject, +) []*gql.Directive { + return []*gql.Directive{ + types.CRDTFieldDirective(crdtEnum), + types.DefaultDirective(), + types.ExplainDirective(explainEnum), + types.PolicyDirective(), + types.IndexDirective(orderEnum, indexFieldInput), + types.PrimaryDirective(), + types.RelationDirective(), + types.MaterializedDirective(), + } +} + +func inlineArrayTypes() []gql.Type { + return []gql.Type{ + gql.Boolean, + gql.Float, + gql.Int, + gql.String, + gql.NewNonNull(gql.Boolean), + gql.NewNonNull(gql.Float), + gql.NewNonNull(gql.Int), + gql.NewNonNull(gql.String), + } +} + +// default type map includes all the native scalar types +func defaultTypes( + commitObject *gql.Object, + commitLinkObject *gql.Object, + commitsOrderArg *gql.InputObject, + orderEnum *gql.Enum, + crdtEnum *gql.Enum, + explainEnum *gql.Enum, + indexFieldInput *gql.InputObject, +) []gql.Type { + blobScalarType := types.BlobScalarType() + jsonScalarType := types.JSONScalarType() + + idOpBlock := types.IDOperatorBlock() + intOpBlock := types.IntOperatorBlock() + floatOpBlock := types.FloatOperatorBlock() + booleanOpBlock := types.BooleanOperatorBlock() + stringOpBlock := types.StringOperatorBlock() + blobOpBlock := types.BlobOperatorBlock(blobScalarType) + dateTimeOpBlock := types.DateTimeOperatorBlock() + + notNullIntOpBlock := types.NotNullIntOperatorBlock() + notNullFloatOpBlock := types.NotNullFloatOperatorBlock() + notNullBooleanOpBlock := types.NotNullBooleanOperatorBlock() + notNullStringOpBlock := types.NotNullStringOperatorBlock() + notNullBlobOpBlock := types.NotNullBlobOperatorBlock(blobScalarType) + + return []gql.Type{ + // Base Scalar types + gql.Boolean, + gql.DateTime, + gql.Float, + gql.ID, + gql.Int, + gql.String, + + // Custom Scalar types + blobScalarType, + jsonScalarType, + + // Base Query types + + // Sort/Order enum + orderEnum, + + // Filter scalar blocks + idOpBlock, + intOpBlock, + floatOpBlock, + booleanOpBlock, + stringOpBlock, + blobOpBlock, + dateTimeOpBlock, + + // Filter non null scalar blocks + notNullIntOpBlock, + notNullFloatOpBlock, + notNullBooleanOpBlock, + notNullStringOpBlock, + notNullBlobOpBlock, + + // Filter scalar list blocks + types.IntListOperatorBlock(intOpBlock), + types.FloatListOperatorBlock(floatOpBlock), + types.BooleanListOperatorBlock(booleanOpBlock), + types.StringListOperatorBlock(stringOpBlock), + + // Filter non null scalar list blocks + types.NotNullIntListOperatorBlock(notNullIntOpBlock), + types.NotNullFloatListOperatorBlock(notNullFloatOpBlock), + types.NotNullBooleanListOperatorBlock(notNullBooleanOpBlock), + types.NotNullStringListOperatorBlock(notNullStringOpBlock), + + commitsOrderArg, + commitLinkObject, + commitObject, + + crdtEnum, + explainEnum, + + indexFieldInput, + } +} diff --git a/internal/request/graphql/schema/types/types.go b/internal/request/graphql/schema/types/types.go index 8b02c59056..5770b4b579 100644 --- a/internal/request/graphql/schema/types/types.go +++ b/internal/request/graphql/schema/types/types.go @@ -232,7 +232,7 @@ func MaterializedDirective() *gql.Directive { }, }, Locations: []string{ - gql.DirectiveLocationSchema, + gql.DirectiveLocationObject, }, }) } @@ -277,7 +277,7 @@ func CRDTFieldDirective(crdtEnum *gql.Enum) *gql.Directive { }, }, Locations: []string{ - gql.DirectiveLocationField, + gql.DirectiveLocationFieldDefinition, }, }) } diff --git a/tests/bench/query/planner/utils.go b/tests/bench/query/planner/utils.go index 0ab739ac20..a4fc69e091 100644 --- a/tests/bench/query/planner/utils.go +++ b/tests/bench/query/planner/utils.go @@ -23,7 +23,6 @@ import ( "github.com/sourcenetwork/defradb/internal/core" "github.com/sourcenetwork/defradb/internal/planner" "github.com/sourcenetwork/defradb/internal/request/graphql" - gqlSchema "github.com/sourcenetwork/defradb/internal/request/graphql/schema" benchutils "github.com/sourcenetwork/defradb/tests/bench" "github.com/sourcenetwork/defradb/tests/bench/fixtures" ) @@ -116,7 +115,7 @@ func buildParser( return nil, err } - collectionDescriptions, err := gqlSchema.FromString(ctx, schema) + collectionDescriptions, err := parser.ParseSDL(schema) if err != nil { return nil, err } diff --git a/tests/integration/acp/schema/add_dpi/reject_invalid_arg_type_on_schema_test.go b/tests/integration/acp/schema/add_dpi/reject_invalid_arg_type_on_schema_test.go index 5aaa44bc56..efb05fca7b 100644 --- a/tests/integration/acp/schema/add_dpi/reject_invalid_arg_type_on_schema_test.go +++ b/tests/integration/acp/schema/add_dpi/reject_invalid_arg_type_on_schema_test.go @@ -66,7 +66,7 @@ func TestACP_AddDPISchema_InvalidPolicyIDArgTypeWasSpecifiedOnSchema_SchemaRejec age: Int } `, - ExpectedError: "policy directive with invalid id property", + ExpectedError: `Argument "id" has invalid value 123`, }, testUtils.IntrospectionRequest{ @@ -144,7 +144,7 @@ func TestACP_AddDPISchema_InvalidResourceArgTypeWasSpecifiedOnSchema_SchemaRejec policyIDOfValidDPI, ), - ExpectedError: "policy directive with invalid resource property", + ExpectedError: `Argument "resource" has invalid value 123`, }, testUtils.IntrospectionRequest{ diff --git a/tests/integration/collection_description/with_default_fields_test.go b/tests/integration/collection_description/with_default_fields_test.go index dca776532d..0d35254ca9 100644 --- a/tests/integration/collection_description/with_default_fields_test.go +++ b/tests/integration/collection_description/with_default_fields_test.go @@ -99,7 +99,7 @@ func TestCollectionDescription_WithInvalidDefaultFieldValueType_ReturnsError(t * active: Boolean @default(bool: invalid) } `, - ExpectedError: "default value is invalid. Field: active, Arg: bool", + ExpectedError: "Argument \"bool\" has invalid value invalid", }, }, } diff --git a/tests/integration/encryption/commit_test.go b/tests/integration/encryption/commit_test.go index 592f1e0501..fbe94ea53b 100644 --- a/tests/integration/encryption/commit_test.go +++ b/tests/integration/encryption/commit_test.go @@ -200,7 +200,7 @@ func TestDocEncryption_WithEncryptionOnCounterCRDT_ShouldStoreCommitsDeltaEncryp testUtils.SchemaUpdate{ Schema: ` type Users { - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `}, testUtils.CreateDoc{ @@ -243,7 +243,7 @@ func TestDocEncryption_UponUpdateOnCounterCRDT_ShouldEncryptedCommitDelta(t *tes testUtils.SchemaUpdate{ Schema: ` type Users { - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `}, testUtils.CreateDoc{ diff --git a/tests/integration/encryption/peer_share_test.go b/tests/integration/encryption/peer_share_test.go index c04d204a84..25e1cbd7cf 100644 --- a/tests/integration/encryption/peer_share_test.go +++ b/tests/integration/encryption/peer_share_test.go @@ -283,7 +283,7 @@ func TestDocEncryptionPeer_WithUpdatesOnEncryptedDeltaBasedCRDTField_ShouldDecry Schema: ` type User { name: String - age: Int @crdt(type: "pcounter") + age: Int @crdt(type: pcounter) } `, }, @@ -342,7 +342,7 @@ func TestDocEncryptionPeer_WithUpdatesOnDeltaBasedCRDTFieldOfEncryptedDoc_Should Schema: ` type User { name: String - age: Int @crdt(type: "pcounter") + age: Int @crdt(type: pcounter) } `, }, diff --git a/tests/integration/encryption/query_test.go b/tests/integration/encryption/query_test.go index a949081120..286192f66d 100644 --- a/tests/integration/encryption/query_test.go +++ b/tests/integration/encryption/query_test.go @@ -70,7 +70,7 @@ func TestDocEncryption_WithEncryptionOnCounterCRDT_ShouldFetchDecrypted(t *testi Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `}, testUtils.CreateDoc{ diff --git a/tests/integration/encryption/utils.go b/tests/integration/encryption/utils.go index 685a2567fb..3686fae5ac 100644 --- a/tests/integration/encryption/utils.go +++ b/tests/integration/encryption/utils.go @@ -20,7 +20,7 @@ import ( const userCollectionGQLSchema = (` type Users { name: String - age: Int @crdt(type: "lww") + age: Int @crdt(type: lww) verified: Boolean } `) diff --git a/tests/integration/issues/2566_test.go b/tests/integration/issues/2566_test.go index eecf0d20b4..189ee17fd4 100644 --- a/tests/integration/issues/2566_test.go +++ b/tests/integration/issues/2566_test.go @@ -37,7 +37,7 @@ func TestP2PUpdate_WithPNCounterSimultaneousOverflowIncrement_DoesNotReachConsit Schema: ` type Users { Name: String - Age: Float @crdt(type: "pncounter") + Age: Float @crdt(type: pncounter) } `, }, @@ -133,7 +133,7 @@ func TestP2PUpdate_WithPNCounterSimultaneousOverflowDecrement_DoesNotReachConsit Schema: ` type Users { Name: String - Age: Float @crdt(type: "pncounter") + Age: Float @crdt(type: pncounter) } `, }, diff --git a/tests/integration/issues/2569_test.go b/tests/integration/issues/2569_test.go index 2d942177d6..1d7727fd26 100644 --- a/tests/integration/issues/2569_test.go +++ b/tests/integration/issues/2569_test.go @@ -36,7 +36,7 @@ func TestP2PUpdate_WithPNCounterFloatOverflowIncrement_PreventsQuerying(t *testi Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, @@ -81,7 +81,7 @@ func TestP2PUpdate_WithPNCounterFloatOverflowDecrement_PreventsQuerying(t *testi Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, @@ -135,7 +135,7 @@ func TestP2PUpdate_WithPNCounterFloatOverflow_PreventsCollectionGet(t *testing.T Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, diff --git a/tests/integration/mutation/create/crdt/pcounter_test.go b/tests/integration/mutation/create/crdt/pcounter_test.go index 724b157006..ef8f1c5688 100644 --- a/tests/integration/mutation/create/crdt/pcounter_test.go +++ b/tests/integration/mutation/create/crdt/pcounter_test.go @@ -24,7 +24,7 @@ func TestPCounterCreate_IntKindWithPositiveValue_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, diff --git a/tests/integration/mutation/create/crdt/pncounter_test.go b/tests/integration/mutation/create/crdt/pncounter_test.go index c16a0c5bb6..a224946471 100644 --- a/tests/integration/mutation/create/crdt/pncounter_test.go +++ b/tests/integration/mutation/create/crdt/pncounter_test.go @@ -24,7 +24,7 @@ func TestPNCounterCreate_IntKindWithPositiveValue_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, diff --git a/tests/integration/mutation/update/crdt/pcounter_test.go b/tests/integration/mutation/update/crdt/pcounter_test.go index 784bf9f2c4..a174b009eb 100644 --- a/tests/integration/mutation/update/crdt/pcounter_test.go +++ b/tests/integration/mutation/update/crdt/pcounter_test.go @@ -28,7 +28,7 @@ func TestPCounterUpdate_IntKindWithNegativeIncrement_ShouldError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, @@ -75,7 +75,7 @@ func TestPCounterUpdate_IntKindWithPositiveIncrement_ShouldIncrement(t *testing. Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, @@ -135,7 +135,7 @@ func TestPCounterUpdate_IntKindWithPositiveIncrementOverflow_RollsOverToMinInt64 Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, @@ -181,7 +181,7 @@ func TestPCounterUpdate_FloatKindWithPositiveIncrement_ShouldIncrement(t *testin Schema: ` type Users { name: String - points: Float @crdt(type: "pcounter") + points: Float @crdt(type: pcounter) } `, }, @@ -236,7 +236,7 @@ func TestPCounterUpdate_FloatKindWithPositiveIncrementOverflow_NoOp(t *testing.T Schema: ` type Users { name: String - points: Float @crdt(type: "pcounter") + points: Float @crdt(type: pcounter) } `, }, diff --git a/tests/integration/mutation/update/crdt/pncounter_test.go b/tests/integration/mutation/update/crdt/pncounter_test.go index 11efc0452b..ad9f0541a9 100644 --- a/tests/integration/mutation/update/crdt/pncounter_test.go +++ b/tests/integration/mutation/update/crdt/pncounter_test.go @@ -28,7 +28,7 @@ func TestPNCounterUpdate_IntKindWithPositiveIncrement_ShouldIncrement(t *testing Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, @@ -88,7 +88,7 @@ func TestPNCounterUpdate_IntKindWithPositiveIncrementOverflow_RollsOverToMinInt6 Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, @@ -134,7 +134,7 @@ func TestPNCounterUpdate_FloatKindWithPositiveIncrement_ShouldIncrement(t *testi Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, @@ -195,7 +195,7 @@ func TestPNCounterUpdate_FloatKindWithPositiveIncrementOverflow_PositiveInf(t *t Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, @@ -249,7 +249,7 @@ func TestPNCounterUpdate_FloatKindWithDecrementOverflow_NegativeInf(t *testing.T Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, @@ -295,7 +295,7 @@ func TestPNCounterUpdate_FloatKindWithPositiveIncrementInsignificantValue_DoesNo Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, diff --git a/tests/integration/net/simple/peer/crdt/pcounter_test.go b/tests/integration/net/simple/peer/crdt/pcounter_test.go index 569e4bb153..f379ab8d46 100644 --- a/tests/integration/net/simple/peer/crdt/pcounter_test.go +++ b/tests/integration/net/simple/peer/crdt/pcounter_test.go @@ -27,7 +27,7 @@ func TestP2PUpdate_WithPCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, @@ -79,7 +79,7 @@ func TestP2PUpdate_WithPCounterSimultaneousUpdate_NoError(t *testing.T) { Schema: ` type Users { Name: String - Age: Int @crdt(type: "pcounter") + Age: Int @crdt(type: pcounter) } `, }, diff --git a/tests/integration/net/simple/peer/crdt/pncounter_test.go b/tests/integration/net/simple/peer/crdt/pncounter_test.go index de0c67fc2c..4b4d21eec4 100644 --- a/tests/integration/net/simple/peer/crdt/pncounter_test.go +++ b/tests/integration/net/simple/peer/crdt/pncounter_test.go @@ -27,7 +27,7 @@ func TestP2PUpdate_WithPNCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, @@ -79,7 +79,7 @@ func TestP2PUpdate_WithPNCounterSimultaneousUpdate_NoError(t *testing.T) { Schema: ` type Users { Name: String - Age: Int @crdt(type: "pncounter") + Age: Int @crdt(type: pncounter) } `, }, diff --git a/tests/integration/net/simple/peer_replicator/crdt/pcounter_test.go b/tests/integration/net/simple/peer_replicator/crdt/pcounter_test.go index 914f8daba3..612095be45 100644 --- a/tests/integration/net/simple/peer_replicator/crdt/pcounter_test.go +++ b/tests/integration/net/simple/peer_replicator/crdt/pcounter_test.go @@ -28,7 +28,7 @@ func TestP2PPeerReplicatorWithCreate_PCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, @@ -121,7 +121,7 @@ func TestP2PPeerReplicatorWithUpdate_PCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, diff --git a/tests/integration/net/simple/peer_replicator/crdt/pncounter_test.go b/tests/integration/net/simple/peer_replicator/crdt/pncounter_test.go index b990631880..fdbfef9360 100644 --- a/tests/integration/net/simple/peer_replicator/crdt/pncounter_test.go +++ b/tests/integration/net/simple/peer_replicator/crdt/pncounter_test.go @@ -28,7 +28,7 @@ func TestP2PPeerReplicatorWithCreate_PNCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, @@ -121,7 +121,7 @@ func TestP2PPeerReplicatorWithUpdate_PNCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, diff --git a/tests/integration/net/simple/replicator/crdt/pcounter_test.go b/tests/integration/net/simple/replicator/crdt/pcounter_test.go index 2062b912df..f546025a4f 100644 --- a/tests/integration/net/simple/replicator/crdt/pcounter_test.go +++ b/tests/integration/net/simple/replicator/crdt/pcounter_test.go @@ -27,7 +27,7 @@ func TestP2POneToOneReplicatorUpdate_PCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, diff --git a/tests/integration/net/simple/replicator/crdt/pncounter_test.go b/tests/integration/net/simple/replicator/crdt/pncounter_test.go index 48d1783504..db57744ee3 100644 --- a/tests/integration/net/simple/replicator/crdt/pncounter_test.go +++ b/tests/integration/net/simple/replicator/crdt/pncounter_test.go @@ -27,7 +27,7 @@ func TestP2POneToOneReplicatorUpdate_PNCounter_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, diff --git a/tests/integration/query/simple/with_cid_doc_id_test.go b/tests/integration/query/simple/with_cid_doc_id_test.go index 0536099128..8c6476b1e5 100644 --- a/tests/integration/query/simple/with_cid_doc_id_test.go +++ b/tests/integration/query/simple/with_cid_doc_id_test.go @@ -311,7 +311,7 @@ func TestCidAndDocIDQuery_ContainsPNCounterWithIntKind_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, @@ -365,7 +365,7 @@ func TestCidAndDocIDQuery_ContainsPNCounterWithFloatKind_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, @@ -419,7 +419,7 @@ func TestCidAndDocIDQuery_ContainsPCounterWithIntKind_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, @@ -468,7 +468,7 @@ func TestCidAndDocIDQuery_ContainsPCounterWithFloatKind_NoError(t *testing.T) { Schema: ` type Users { name: String - points: Float @crdt(type: "pcounter") + points: Float @crdt(type: pcounter) } `, }, diff --git a/tests/integration/schema/crdt_type_test.go b/tests/integration/schema/crdt_type_test.go index 2a321ef751..afc7a6f539 100644 --- a/tests/integration/schema/crdt_type_test.go +++ b/tests/integration/schema/crdt_type_test.go @@ -27,7 +27,7 @@ func TestSchemaCreate_ContainsPNCounterTypeWithIntKind_NoError(t *testing.T) { testUtils.SchemaUpdate{ Schema: ` type Users { - points: Int @crdt(type: "pncounter") + points: Int @crdt(type: pncounter) } `, }, @@ -66,7 +66,7 @@ func TestSchemaCreate_ContainsPNCounterTypeWithFloatKind_NoError(t *testing.T) { testUtils.SchemaUpdate{ Schema: ` type Users { - points: Float @crdt(type: "pncounter") + points: Float @crdt(type: pncounter) } `, }, @@ -103,7 +103,7 @@ func TestSchemaCreate_ContainsPNCounterTypeWithWrongKind_Error(t *testing.T) { testUtils.SchemaUpdate{ Schema: ` type Users { - points: String @crdt(type: "pncounter") + points: String @crdt(type: pncounter) } `, ExpectedError: "CRDT type pncounter can't be assigned to field kind String", @@ -123,7 +123,7 @@ func TestSchemaCreate_ContainsPNCounterWithInvalidType_Error(t *testing.T) { points: Int @crdt(type: "invalid") } `, - ExpectedError: "CRDT type not supported. Name: points, CRDTType: invalid", + ExpectedError: `Argument "type" has invalid value "invalid"`, }, }, } @@ -139,7 +139,7 @@ func TestSchemaCreate_ContainsPCounterTypeWithIntKind_NoError(t *testing.T) { testUtils.SchemaUpdate{ Schema: ` type Users { - points: Int @crdt(type: "pcounter") + points: Int @crdt(type: pcounter) } `, }, @@ -178,7 +178,7 @@ func TestSchemaCreate_ContainsPCounterTypeWithFloatKind_NoError(t *testing.T) { testUtils.SchemaUpdate{ Schema: ` type Users { - points: Float @crdt(type: "pcounter") + points: Float @crdt(type: pcounter) } `, }, @@ -215,7 +215,7 @@ func TestSchemaCreate_ContainsPCounterTypeWithWrongKind_Error(t *testing.T) { testUtils.SchemaUpdate{ Schema: ` type Users { - points: String @crdt(type: "pcounter") + points: String @crdt(type: pcounter) } `, ExpectedError: "CRDT type pcounter can't be assigned to field kind String", diff --git a/tests/integration/utils.go b/tests/integration/utils.go index 744f874423..8d12d03b29 100644 --- a/tests/integration/utils.go +++ b/tests/integration/utils.go @@ -2517,7 +2517,7 @@ func ParseSDL(gqlSDL string) (map[string]client.CollectionDefinition, error) { if err != nil { return nil, err } - cols, err := parser.ParseSDL(context.Background(), gqlSDL) + cols, err := parser.ParseSDL(gqlSDL) if err != nil { return nil, err }