Skip to content

Commit de1a152

Browse files
committed
handle case where all fields are removed via Field visibility transformer (for input object types)
1 parent 8407043 commit de1a152

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

src/main/java/graphql/schema/transform/FieldVisibilitySchemaTransformation.java

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import graphql.schema.GraphQLInputObjectField;
1010
import graphql.schema.GraphQLInputObjectType;
1111
import graphql.schema.GraphQLInterfaceType;
12-
import graphql.schema.GraphQLNamedSchemaElement;
1312
import graphql.schema.GraphQLNamedType;
1413
import graphql.schema.GraphQLObjectType;
1514
import graphql.schema.GraphQLSchema;
@@ -160,6 +159,7 @@ private static class FieldRemovalVisitor extends GraphQLTypeVisitorStub {
160159
private final Set<GraphQLType> removedTypes;
161160

162161
private final Set<GraphQLFieldDefinition> fieldDefinitionsToActuallyRemove = new LinkedHashSet<>();
162+
private final Set<GraphQLInputObjectField> inputObjectFieldsToDelete = new LinkedHashSet<>();
163163

164164
private FieldRemovalVisitor(VisibleFieldPredicate visibilityPredicate,
165165
Set<GraphQLType> removedTypes) {
@@ -197,6 +197,27 @@ private TraversalControl visitFieldsContainer(GraphQLFieldsContainer fieldsConta
197197
}
198198
}
199199

200+
@Override
201+
public TraversalControl visitGraphQLInputObjectType(GraphQLInputObjectType inputObjectType, TraverserContext<GraphQLSchemaElement> context) {
202+
boolean allFieldsDeleted = true;
203+
for (GraphQLInputObjectField inputField : inputObjectType.getFieldDefinitions()) {
204+
VisibleFieldPredicateEnvironment environment = new VisibleFieldPredicateEnvironmentImpl(
205+
inputField, inputObjectType);
206+
if (!visibilityPredicate.isVisible(environment)) {
207+
inputObjectFieldsToDelete.add(inputField);
208+
removedTypes.add(inputField.getType());
209+
} else {
210+
allFieldsDeleted = false;
211+
}
212+
}
213+
if (allFieldsDeleted) {
214+
// we are deleting the whole input object type because all fields are supposed to be deleted
215+
return deleteNode(context);
216+
} else {
217+
return TraversalControl.CONTINUE;
218+
}
219+
220+
}
200221

201222
@Override
202223
public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition definition,
@@ -211,25 +232,11 @@ public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition defin
211232
@Override
212233
public TraversalControl visitGraphQLInputObjectField(GraphQLInputObjectField definition,
213234
TraverserContext<GraphQLSchemaElement> context) {
214-
return visitField(definition, context);
215-
}
216-
217-
private TraversalControl visitField(GraphQLNamedSchemaElement element,
218-
TraverserContext<GraphQLSchemaElement> context) {
219-
220-
VisibleFieldPredicateEnvironment environment = new VisibleFieldPredicateEnvironmentImpl(
221-
element, context.getParentNode());
222-
if (!visibilityPredicate.isVisible(environment)) {
223-
deleteNode(context);
224-
225-
if (element instanceof GraphQLFieldDefinition) {
226-
removedTypes.add(((GraphQLFieldDefinition) element).getType());
227-
} else if (element instanceof GraphQLInputObjectField) {
228-
removedTypes.add(((GraphQLInputObjectField) element).getType());
229-
}
235+
if (inputObjectFieldsToDelete.contains(definition)) {
236+
return deleteNode(context);
237+
} else {
238+
return TraversalControl.CONTINUE;
230239
}
231-
232-
return TraversalControl.CONTINUE;
233240
}
234241
}
235242

src/test/groovy/graphql/schema/transform/FieldVisibilitySchemaTransformationTest.groovy

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,4 +1279,36 @@ class FieldVisibilitySchemaTransformationTest extends Specification {
12791279
(restrictedSchema.getType("Foo") as GraphQLObjectType).getFieldDefinition("toDelete") == null
12801280
}
12811281

1282+
def "remove all fields from an input type which is referenced via additional types"() {
1283+
given:
1284+
GraphQLSchema schema = TestUtil.schema("""
1285+
directive @private on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
1286+
type Query {
1287+
foo(input: Input): String
1288+
}
1289+
input Input {
1290+
foo: String
1291+
toDelete:ToDelete @private
1292+
}
1293+
input ToDelete {
1294+
toDelete:String @private
1295+
}
1296+
""")
1297+
1298+
when:
1299+
schema.typeMap
1300+
def patchedSchema = schema.transform { builder ->
1301+
schema.typeMap.each { entry ->
1302+
def type = entry.value
1303+
if (type != schema.queryType && type != schema.mutationType && type != schema.subscriptionType) {
1304+
builder.additionalType(type)
1305+
}
1306+
}
1307+
}
1308+
GraphQLSchema restrictedSchema = visibilitySchemaTransformation.apply(patchedSchema)
1309+
then:
1310+
(restrictedSchema.getType("Input") as GraphQLInputObjectType).getFieldDefinition("toDelete") == null
1311+
}
1312+
1313+
12821314
}

0 commit comments

Comments
 (0)