Skip to main content

GraphQLContext

Struct GraphQLContext 

Source
pub struct GraphQLContext {
    pub pool: PgPool,
    pub schema_cache: SchemaCacheRef,
    pub auth: AuthResult,
    pub session: HashMap<String, String>,
    pub hasura_role: Option<String>,
    pub elevated: bool,
    pub write: SharedWrite,
}
Expand description

Context available to all GraphQL resolvers.

Fields§

§pool: PgPool

Database connection pool.

§schema_cache: SchemaCacheRef

Schema cache for table/column metadata.

§auth: AuthResult

Authentication result with role and claims.

§session: HashMap<String, String>

Session variables carried into the transaction, without their x-hasura- prefix and lowercased: user_id, org_id.

This is the half of Hasura’s permission model that transfers. Its rules live in metadata and are compiled into every query; here permissions live in the database as roles and row level security, and what a policy needs is the caller’s identity. A policy written against current_setting('hasura.user_id') sees what the Hasura permission would have seen.

§hasura_role: Option<String>

The role the caller speaks as, in Hasura’s sense, where that is not the database role the transaction runs as.

The two are different things and conflating them was the reason hasura_session->>'x-hasura-role' used to answer with the name of the connecting database user. Hasura’s roles are labels – Artist, anonymous – that exist in no catalogue and could not be SET ROLE to; what they decide is which permissions apply and what a function reading the session document sees. Which database user the transaction runs as is AuthResult::role, and it is settled separately.

None when nothing named a Hasura role, in which case the database role stands in for it, as it did before the two were told apart.

§elevated: bool

Whether the admin secret authenticated this request.

Not the same question as whether the role is admin, which an administrator gives up as soon as it asks to be treated as someone else. What this gates is the fields a backend_only permission hides: reachable by a caller that proved it holds the secret, whatever role it then claims, and by no one else.

§write: SharedWrite

The transaction every write in this operation shares. See SharedWrite.

Implementations§

Source§

impl GraphQLContext

Source

pub fn new(pool: PgPool, schema_cache: SchemaCacheRef, auth: AuthResult) -> Self

Create a new GraphQL context.

Source

pub fn with_identity(self, role: Option<String>, elevated: bool) -> Self

Record who the caller is in Hasura’s sense, and whether it proved it.

Source

pub fn acting_role(&self) -> &str

The role the caller speaks as: the Hasura role where one was named, and the database role otherwise.

Source

pub fn caller(&self) -> Caller<'_>

Who is asking, for the SQL builders that have to narrow rows to them.

The Hasura role rather than Self::acting_role: a permission is keyed by a role someone wrote into a document, and the database role standing in for a missing one would name no permission and read as unrestricted – which is right, and is worth being explicit about.

Source

pub fn with_write(self, write: SharedWrite) -> Self

Share one transaction with whoever is going to settle it.

The caller keeps the other handle: it is the only thing that knows whether the operation ended in errors, and so the only thing that can decide between commit and rollback.

Source

pub fn with_session(self, session: HashMap<String, String>) -> Self

Carry session variables into every transaction this request opens.

Source

pub fn session_settings(&self) -> Vec<(String, String)>

The transaction-local settings this request’s identity needs.

Hasura session variables retain their existing representation, while the verified JWT is exposed as both request.jwt.claims JSON and individual request.jwt.claims.<name> settings.

Source

pub fn hasura_session(&self) -> Value

The session as a function reading hasura_session expects it.

Hasura hands a function a JSON object of the caller’s session variables, under the names they arrive as – x-hasura-role, x-hasura-user-id – which is what a function body indexes into. Self::session holds them stripped and lowercased for the settings a row-level policy reads, so the prefix goes back on here.

The role is included and is not the caller’s to choose: it is what authenticated the request, or the role an authenticated administrator asked to be treated as – never a bare header.

Source

pub fn role(&self) -> &str

The database role this request’s transaction runs as.

Not Self::acting_role, which is who the caller says it is. SET LOCAL ROLE takes this one, because it is the only one of the two that has to exist in the catalogue.

Source

pub fn claim(&self, key: &str) -> Option<&Value>

Get a claim value.

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> MaybeSend for T
where T: Send + ?Sized,

Source§

impl<T> MaybeSync for T
where T: Sync + ?Sized,

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