Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ public FieldVisibilitySchemaTransformation(VisibleFieldPredicate visibleFieldPre
}

public final GraphQLSchema apply(GraphQLSchema schema) {
Set<GraphQLType> observedBeforeTransform = new HashSet<>();
Set<GraphQLType> observedAfterTransform = new HashSet<>();
Set<String> observedBeforeTransform = new LinkedHashSet<>();
Set<String> observedAfterTransform = new LinkedHashSet<>();
Set<GraphQLType> markedForRemovalTypes = new HashSet<>();

// query, mutation, and subscription types should not be removed
Expand Down Expand Up @@ -135,18 +135,22 @@ protected TraversalControl visitGraphQLType(GraphQLSchemaElement node, Traverser

private static class TypeObservingVisitor extends GraphQLTypeVisitorStub {

private final Set<GraphQLType> observedTypes;
private final Set<String> observedTypes;


private TypeObservingVisitor(Set<GraphQLType> observedTypes) {
private TypeObservingVisitor(Set<String> observedTypes) {
this.observedTypes = observedTypes;
}

@Override
protected TraversalControl visitGraphQLType(GraphQLSchemaElement node,
TraverserContext<GraphQLSchemaElement> context) {
if (node instanceof GraphQLType) {
observedTypes.add((GraphQLType) node);
if (node instanceof GraphQLObjectType ||
node instanceof GraphQLEnumType ||
node instanceof GraphQLInputObjectType ||
node instanceof GraphQLInterfaceType ||
node instanceof GraphQLUnionType) {
observedTypes.add(((GraphQLNamedType) node).getName());
}

return TraversalControl.CONTINUE;
Expand Down Expand Up @@ -243,12 +247,12 @@ public TraversalControl visitGraphQLInputObjectField(GraphQLInputObjectField def
private static class TypeVisibilityVisitor extends GraphQLTypeVisitorStub {

private final Set<String> protectedTypeNames;
private final Set<GraphQLType> observedBeforeTransform;
private final Set<GraphQLType> observedAfterTransform;
private final Set<String> observedBeforeTransform;
private final Set<String> observedAfterTransform;

private TypeVisibilityVisitor(Set<String> protectedTypeNames,
Set<GraphQLType> observedTypes,
Set<GraphQLType> observedAfterTransform) {
Set<String> observedTypes,
Set<String> observedAfterTransform) {
this.protectedTypeNames = protectedTypeNames;
this.observedBeforeTransform = observedTypes;
this.observedAfterTransform = observedAfterTransform;
Expand All @@ -263,17 +267,19 @@ public TraversalControl visitGraphQLInterfaceType(GraphQLInterfaceType node,
@Override
public TraversalControl visitGraphQLType(GraphQLSchemaElement node,
TraverserContext<GraphQLSchemaElement> context) {
if (observedBeforeTransform.contains(node) &&
!observedAfterTransform.contains(node) &&
(node instanceof GraphQLObjectType ||
node instanceof GraphQLEnumType ||
node instanceof GraphQLInputObjectType ||
node instanceof GraphQLInterfaceType ||
node instanceof GraphQLUnionType)) {

return deleteNode(context);
if (node instanceof GraphQLObjectType ||
node instanceof GraphQLEnumType ||
node instanceof GraphQLInputObjectType ||
node instanceof GraphQLInterfaceType ||
node instanceof GraphQLUnionType) {
String name = ((GraphQLNamedType) node).getName();
if (observedBeforeTransform.contains(name) &&
!observedAfterTransform.contains(name)
&& !protectedTypeNames.contains(name)
) {
return deleteNode(context);
}
}

return TraversalControl.CONTINUE;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import graphql.schema.GraphQLInputObjectType
import graphql.schema.GraphQLObjectType
import graphql.schema.GraphQLSchema
import graphql.schema.TypeResolver
import graphql.schema.idl.SchemaPrinter
import spock.lang.Specification

import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition
Expand Down Expand Up @@ -973,7 +972,6 @@ class FieldVisibilitySchemaTransformationTest extends Specification {
.build()
when:

System.out.println((new SchemaPrinter()).print(schema))
GraphQLSchema restrictedSchema = visibilitySchemaTransformation.apply(schema)

then:
Expand Down Expand Up @@ -1022,7 +1020,6 @@ class FieldVisibilitySchemaTransformationTest extends Specification {
.build()
when:

System.out.println((new SchemaPrinter()).print(schema))
GraphQLSchema restrictedSchema = visibilitySchemaTransformation.apply(schema)

then:
Expand Down Expand Up @@ -1057,7 +1054,6 @@ class FieldVisibilitySchemaTransformationTest extends Specification {
.build()
when:

System.out.println((new SchemaPrinter()).print(schema))
GraphQLSchema restrictedSchema = visibilitySchemaTransformation.apply(schema)

then:
Expand Down Expand Up @@ -1279,6 +1275,46 @@ class FieldVisibilitySchemaTransformationTest extends Specification {
(restrictedSchema.getType("Foo") as GraphQLObjectType).getFieldDefinition("toDelete") == null
}

def "remove field from a type which is referenced via additional types and an additional not reachable child is deleted"() {
given:
/*
the test case here is that ToDelete is changed, because ToDelete.toDelete is deleted
and additionally Indirect needs to be deleted because it is not reachable via the
Query type anymore.
We had a bug where ToDeleted was not deleted correctly, but because Indirect was, it resulted
in an invalid schema and exception.
*/
GraphQLSchema schema = TestUtil.schema("""
directive @private on FIELD_DEFINITION
type Query {
foo: String
toDelete: ToDelete @private
}
type ToDelete {
bare: String @private
toDelete:[Indirect!]
}
type Indirect {
foo: String
}
""")

when:
schema.typeMap
def patchedSchema = schema.transform { builder ->
schema.typeMap.each { entry ->
def type = entry.value
if (type != schema.queryType && type != schema.mutationType && type != schema.subscriptionType) {
builder.additionalType(type)
}
}
}
GraphQLSchema restrictedSchema = visibilitySchemaTransformation.apply(patchedSchema)
then:
(restrictedSchema.getType("Query") as GraphQLObjectType).getFieldDefinition("toDelete") == null
}


def "remove all fields from an input type which is referenced via additional types"() {
given:
GraphQLSchema schema = TestUtil.schema("""
Expand Down
Loading