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: PgPoolDatabase connection pool.
schema_cache: SchemaCacheRefSchema cache for table/column metadata.
auth: AuthResultAuthentication 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: boolWhether 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: SharedWriteThe transaction every write in this operation shares. See SharedWrite.
Implementations§
Source§impl GraphQLContext
impl GraphQLContext
Sourcepub fn new(pool: PgPool, schema_cache: SchemaCacheRef, auth: AuthResult) -> Self
pub fn new(pool: PgPool, schema_cache: SchemaCacheRef, auth: AuthResult) -> Self
Create a new GraphQL context.
Sourcepub fn with_identity(self, role: Option<String>, elevated: bool) -> Self
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.
Sourcepub fn acting_role(&self) -> &str
pub fn acting_role(&self) -> &str
The role the caller speaks as: the Hasura role where one was named, and the database role otherwise.
Sourcepub fn caller(&self) -> Caller<'_>
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.
Sourcepub fn with_write(self, write: SharedWrite) -> Self
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.
Sourcepub fn with_session(self, session: HashMap<String, String>) -> Self
pub fn with_session(self, session: HashMap<String, String>) -> Self
Carry session variables into every transaction this request opens.
Sourcepub fn session_settings(&self) -> Vec<(String, String)>
pub fn session_settings(&self) -> Vec<(String, String)>
The SET LOCAL statements this request’s session variables need.
The setting name is built from the variable’s own name after it has
been checked, and the value is bound rather than interpolated:
set_config takes both as arguments, where SET LOCAL would need the
value written into the statement.
Sourcepub fn hasura_session(&self) -> Value
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.
Sourcepub fn role(&self) -> &str
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.
Auto Trait Implementations§
impl !RefUnwindSafe for GraphQLContext
impl !UnwindSafe for GraphQLContext
impl Freeze for GraphQLContext
impl Send for GraphQLContext
impl Sync for GraphQLContext
impl Unpin for GraphQLContext
impl UnsafeUnpin for GraphQLContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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