diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.java index 6b2327d2d0..5cb3f77b0b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfiguration.java @@ -24,6 +24,7 @@ import java.util.stream.Collectors; import graphql.GraphQL; import graphql.execution.instrumentation.Instrumentation; +import graphql.schema.visibility.NoIntrospectionGraphqlFieldVisibility; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -77,6 +78,10 @@ public class GraphQlAutoConfiguration { .schemaResources(schemaResources.toArray(new Resource[0])) .exceptionResolvers(exceptionResolversProvider.orderedStream().collect(Collectors.toList())) .instrumentation(instrumentationsProvider.orderedStream().collect(Collectors.toList())); + if (!properties.getSchema().getIntrospection().isEnabled()) { + builder.configureRuntimeWiring((wiring) -> wiring + .fieldVisibility(NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY)); + } wiringConfigurers.orderedStream().forEach(builder::configureRuntimeWiring); sourceCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); try { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlProperties.java index 3df070e745..02df4a3095 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/GraphQlProperties.java @@ -73,6 +73,8 @@ public class GraphQlProperties { */ private String[] fileExtensions = new String[] { ".graphqls", ".gqls" }; + private final Introspection introspection = new Introspection(); + private final Printer printer = new Printer(); public String[] getLocations() { @@ -96,10 +98,31 @@ public class GraphQlProperties { .toArray(String[]::new); } + public Introspection getIntrospection() { + return this.introspection; + } + public Printer getPrinter() { return this.printer; } + public static class Introspection { + + /** + * Whether field introspection should be enabled at the schema level. + */ + private boolean enabled = true; + + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + } + public static class Printer { /** diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfigurationTests.java index 5f1f388f9a..e769425c76 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/GraphQlAutoConfigurationTests.java @@ -21,6 +21,8 @@ import graphql.execution.instrumentation.ChainedInstrumentation; import graphql.execution.instrumentation.Instrumentation; import graphql.schema.GraphQLSchema; import graphql.schema.idl.RuntimeWiring; +import graphql.schema.visibility.DefaultGraphqlFieldVisibility; +import graphql.schema.visibility.NoIntrospectionGraphqlFieldVisibility; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.Test; @@ -145,6 +147,25 @@ class GraphQlAutoConfigurationTests { }); } + @Test + void fieldIntrospectionShouldBeEnabledByDefault() { + this.contextRunner.run((context) -> { + GraphQlSource graphQlSource = context.getBean(GraphQlSource.class); + GraphQLSchema schema = graphQlSource.schema(); + assertThat(schema.getCodeRegistry().getFieldVisibility()).isInstanceOf(DefaultGraphqlFieldVisibility.class); + }); + } + + @Test + void shouldDisableFieldIntrospection() { + this.contextRunner.withPropertyValues("spring.graphql.schema.introspection.enabled:false").run((context) -> { + GraphQlSource graphQlSource = context.getBean(GraphQlSource.class); + GraphQLSchema schema = graphQlSource.schema(); + assertThat(schema.getCodeRegistry().getFieldVisibility()) + .isInstanceOf(NoIntrospectionGraphqlFieldVisibility.class); + }); + } + @Configuration(proxyBeanMethods = false) static class CustomGraphQlBuilderConfiguration { diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/web/spring-graphql.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/web/spring-graphql.adoc index 66ea980ac8..e197774c32 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/web/spring-graphql.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/web/spring-graphql.adoc @@ -40,6 +40,8 @@ In the following sections, we'll consider this sample GraphQL schema, defining t include::{docs-resources}/graphql/schema.graphqls[] ---- +NOTE: By default, https://spec.graphql.org/draft/#sec-Introspection[field introspection] will be allowed on the schema as it is required for tools such as GraphiQL. +If you wish to not expose information about the schema, you can disable introspection by setting configprop:spring.graphql.schema.introspection.enabled[] to `false`. [[web.graphql.runtimewiring]] === GraphQL RuntimeWiring