Skip to main content

GraphQLState

Struct GraphQLState 

Source
pub struct GraphQLState {
    pub pool: PgPool,
    pub schema_cache: Arc<SchemaCache>,
    pub generated_schema: GeneratedSchema,
    pub schema: Schema,
    pub role_schemas: HashMap<(String, bool), Schema>,
    pub ungranted_schema: Option<Schema>,
    pub config: SchemaConfig,
    pub subscription_fields: Vec<SubscriptionField>,
    pub broker: Arc<RwLock<Option<NotifyBroker>>>,
}
Expand description

GraphQL execution state shared across requests.

Fields§

§pool: PgPool

Database connection pool

§schema_cache: Arc<SchemaCache>

Schema cache

§generated_schema: GeneratedSchema

Generated GraphQL schema

§schema: Schema

async-graphql Schema (built dynamically)

The unrestricted one: what an administrator is answered from, and what every caller is answered from on a server with no permission document.

§role_schemas: HashMap<(String, bool), Schema>

One schema per role the permission document names.

Hasura builds a schema per role because a permission is a statement about what exists, not about what is allowed: a role with no select on a table has no field to name, and naming one is a validation failure rather than a denial. Each is built from a schema cache already reduced to what that role may see.

Built at startup rather than on first use, so a permission document that cannot be built fails while someone is watching rather than on the first request from whichever role it broke.

Keyed by the role and by whether the caller asked for what only a backend may name – which is a second schema rather than a check, because backend_only decides whether a field exists.

§ungranted_schema: Option<Schema>

What a role the document never names is answered from.

Not a refusal. To Hasura an unrecognised role is a role with nothing granted, so it gets a schema with nothing in it – and a request is answered field 'user' not found in type: 'query_root', or no mutations exist where there is no mutation root at all, rather than with a complaint about the role. address_permission_error sends X-Hasura-Role: merchant, which no permission mentions, and expects exactly that.

One schema for every such role rather than one each: they are all the same schema, since what they were granted is the same nothing.

§config: SchemaConfig

Schema configuration

§subscription_fields: Vec<SubscriptionField>

Subscription fields

§broker: Arc<RwLock<Option<NotifyBroker>>>

Notification broker for subscriptions

Implementations§

Source§

impl GraphQLState

Source

pub fn new( pool: PgPool, schema_cache: Arc<SchemaCache>, config: SchemaConfig, ) -> Result<Self, GraphQLError>

Create new GraphQL state from schema cache.

Source

pub fn schema_for(&self, role: Option<&str>, backend: bool) -> Option<&Schema>

Which schema answers for a caller speaking as this role.

A role the document does not name is answered from the schema with nothing in it, which is Hasura’s reading: an unrecognised role is a role that was granted nothing, not an error. Three things are deliberately not that: a server with no permission document answers everyone from the unrestricted schema, an administrator is answered from it too – permissions are rules for everyone else – and so is a request on a server where the layer is off.

None only where the empty schema itself could not be built, which the caller still turns into a refusal.

Source

pub fn rebuild(&mut self) -> Result<(), GraphQLError>

Rebuild the schema (e.g., after schema cache refresh).

Source

pub async fn init_subscriptions(&self) -> Result<(), BrokerError>

Initialize the subscription broker.

This should be called after creating the state to enable subscriptions.

Source

pub async fn stop_subscriptions(&self)

Stop the subscription broker.

Source

pub async fn get_broker(&self) -> Option<Arc<RwLock<Option<NotifyBroker>>>>

Get the notification broker.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more