When introspection is disabled, introspection related types are no longer registered.

This commit is contained in:
Sunli 2021-02-23 12:49:41 +08:00
parent 8ba56f3bf6
commit cd8da606f2
3 changed files with 112 additions and 109 deletions

View File

@ -300,6 +300,8 @@ pub struct Registry {
pub query_type: String,
pub mutation_type: Option<String>,
pub subscription_type: Option<String>,
pub disable_introspection: bool,
pub enable_federation: bool,
}
impl Registry {

View File

@ -33,7 +33,6 @@ pub struct SchemaBuilder<Query, Mutation, Subscription> {
complexity: Option<usize>,
depth: Option<usize>,
extensions: Vec<Box<dyn ExtensionFactory>>,
enable_federation: bool,
}
impl<Query, Mutation, Subscription> SchemaBuilder<Query, Mutation, Subscription> {
@ -47,7 +46,7 @@ impl<Query, Mutation, Subscription> SchemaBuilder<Query, Mutation, Subscription>
/// Disable introspection queries.
pub fn disable_introspection(mut self) -> Self {
self.query.disable_introspection = true;
self.registry.disable_introspection = true;
self
}
@ -102,7 +101,7 @@ impl<Query, Mutation, Subscription> SchemaBuilder<Query, Mutation, Subscription>
/// Enable federation, which is automatically enabled if the Query has least one entity definition.
pub fn enable_federation(mut self) -> Self {
self.enable_federation = true;
self.registry.enable_federation = true;
self
}
@ -115,7 +114,7 @@ impl<Query, Mutation, Subscription> SchemaBuilder<Query, Mutation, Subscription>
/// Build schema.
pub fn finish(mut self) -> Schema<Query, Mutation, Subscription> {
// federation
if self.enable_federation || self.registry.has_entities() {
if self.registry.enable_federation || self.registry.has_entities() {
self.registry.create_federation_types();
}
@ -217,10 +216,7 @@ where
) -> SchemaBuilder<Query, Mutation, Subscription> {
SchemaBuilder {
validation_mode: ValidationMode::Strict,
query: QueryRoot {
inner: query,
disable_introspection: false,
},
query: QueryRoot { inner: query },
mutation,
subscription,
registry: Self::create_registry(),
@ -228,7 +224,6 @@ where
complexity: None,
depth: None,
extensions: Default::default(),
enable_federation: false,
}
}
@ -248,6 +243,8 @@ where
} else {
Some(Subscription::type_name().to_string())
},
disable_introspection: false,
enable_federation: false,
};
registry.add_directive(MetaDirective {

View File

@ -19,7 +19,6 @@ struct Service {
pub(crate) struct QueryRoot<T> {
pub(crate) inner: T,
pub(crate) disable_introspection: bool,
}
impl<T: Type> Type for QueryRoot<T> {
@ -28,8 +27,10 @@ impl<T: Type> Type for QueryRoot<T> {
}
fn create_type_info(registry: &mut registry::Registry) -> String {
let schema_type = __Schema::create_type_info(registry);
let root = T::create_type_info(registry);
if !registry.disable_introspection {
let schema_type = __Schema::create_type_info(registry);
if let Some(registry::MetaType::Object { fields, .. }) =
registry.types.get_mut(T::type_name().as_ref())
{
@ -81,6 +82,8 @@ impl<T: Type> Type for QueryRoot<T> {
},
);
}
}
root
}
}
@ -88,11 +91,8 @@ impl<T: Type> Type for QueryRoot<T> {
#[async_trait::async_trait]
impl<T: ObjectType> ContainerType for QueryRoot<T> {
async fn resolve_field(&self, ctx: &Context<'_>) -> ServerResult<Option<Value>> {
if !ctx.schema_env.registry.disable_introspection {
if ctx.item.node.name.node == "__schema" {
if self.disable_introspection {
return Err(ServerError::new("Query introspection is disabled.").at(ctx.item.pos));
}
let ctx_obj = ctx.with_selection_set(&ctx.item.node.selection_set);
return OutputType::resolve(
&__Schema {
@ -118,15 +118,18 @@ impl<T: ObjectType> ContainerType for QueryRoot<T> {
)
.await
.map(Some);
} else if ctx.item.node.name.node == "_entities" {
}
}
if ctx.schema_env.registry.enable_federation || ctx.schema_env.registry.has_entities() {
if ctx.item.node.name.node == "_entities" {
let representations: Vec<Any> = ctx.param_value("representations", None)?;
let mut res = Vec::new();
for item in representations {
res.push(
self.inner
.find_entity(ctx, &item.0)
.await?
.ok_or_else(|| ServerError::new("Entity not found.").at(ctx.item.pos))?,
self.inner.find_entity(ctx, &item.0).await?.ok_or_else(|| {
ServerError::new("Entity not found.").at(ctx.item.pos)
})?,
);
}
return Ok(Some(Value::List(res)));
@ -142,6 +145,7 @@ impl<T: ObjectType> ContainerType for QueryRoot<T> {
.await
.map(Some);
}
}
self.inner.resolve_field(ctx).await
}