Skip to main content

Module role

Module role 

Source
Expand description

What one role can see.

Hasura builds a separate GraphQL schema for every role, and the difference between them is not cosmetic. A role with no select permission on a table does not get a table it is refused access to – it gets a schema with no such field to read it by, and naming one is a validation failure rather than a denial. The same goes one level down: a column outside the permission is absent from the type, not merely null.

That shape is what the corpus tests. artist_select_query_Track_fail.yaml expects field "Track" not found in type: 'query_root', which no amount of filtering at execution time produces.

§Why this is a filtered cache rather than a flag threaded through the

builders

A select permission is a view of a table, and a set of them is a view of the database. Reducing the schema cache to what a role may see and then building the schema from that means the builders need to know nothing about permissions: a table that was dropped generates no root field, no relationship pointing at it and no boolean expression naming it, because the code that would have generated them cannot see it either.

The alternative – asking “may this role?” at each of the several dozen places a name is emitted – has to be right every time, and is wrong the moment someone adds a place. This has to be right once.

§The one thing a cache cannot hold: two column sets

Hasura grants reading and writing separately, so a role may be allowed to set a column it is not allowed to see – ten permissions in the corpus do – and may be allowed to write a table it cannot read at all, which eight more do. A schema cache has one column list per table and no place to say which half of it is which.

The union goes in the cache, and the split is made once, where the object type’s fields are built: crate::schema::object::TableObjectType::fields is what may be read and writable_fields is what may be written. That keeps the property above – everything a read is made of (the type, its boolean expression, its ordering, its column enum, its aggregates) is derived from fields and narrows with it, and the write inputs are built from the other list and narrowed again by the permission that names them.

A table with no readable field is the limit of that: it has no GraphQL type at all, because a type with no fields is not a legal one. Its bulk writes remain and answer with affected_rows alone – there is no returning to hang rows on – and everything that would return a row of it (the query roots, insert_one, the _by_pk writes, a relationship pointing at it, a function returning it) is left out with the type.

What is left over goes on SchemaConfig: allow_aggregations, which is a fact about a permission rather than about a table.

Structs§

Caller
Who is asking, for the places that have to narrow rows to them.

Enums§

Fault
Why a read could not be narrowed to the caller.
Verb
Which of the four grants is being asked about.

Constants§

CHECK_FAILED
Hasura’s wording for a written row that a permission refuses.

Functions§

allows_aggregations
Whether a role may ask for aggregates over a table.
cache_for_role
Reduce a schema cache to what one role may see.
exists_target
The table _exists looks in, as (schema, table).
has_backend_only
Whether any of this role’s permissions is reachable only by a backend.
permission_where
Turn a permission’s row filter into the boolean expression a where argument would have been.
presets
The columns the server fills in itself, with their values.
read_limit
How many rows a role’s permission lets one read return.
read_predicate
The predicate a role’s select permission adds to a read of one table.
reads_anything
Whether this role can read anything of this table at all.
row_filter
Which rows a role’s permission lets one operation reach.
write_check
What a written row has to satisfy for the write to stand.