Disable GraphQL Query and Subscription Root Fields selectively with RBAC
For each database table in a Hasura app, the GraphQL engine creates three root fields by default. Assuming there is a note
table, the three root fields would be:
- note
- note_by_pk
- note_aggregate
However, there are use cases where you might want to expose only certain root fields or none at all. For example, you might want to hide note_aggregate
, expose only note_by_pk
, or hide all of them. Now it's possible to do that.
Hasura launched this feature in the v2.8.0 version. You can check the v2.8.0 changelog here.
In the next step, you will build and use a Hasura application to test the different use cases.
Try it out via Hasura
The Hasura application you will build is a basic note-taking app. Users can add multiple notes, whereas each note belongs to only one user.
The quickest way to use Hasura is via the Hasura Cloud. Create a new Hasura project and launch the console.
Note: If you prefer local development using Docker, check out the documentation on getting started with Docker.
After that, connect the Hasura application to a database and create two tables - user
and note
.
The user
table has the following columns:
id
of type UUID (PK)name
of type Text
The note
table has the following columns:
id
of type UUID (PK)title
of type Textcontent
of type Textauthor_id
of type Text
The next step involves creating the relationships between the two tables. Navigate to the "Permissions" tab in the user
table and create an array relationship between the user
and note
tables.
The id
column from the user
table maps to the author_id
column from the note
table.
Similarly, create an object relationship between the note
and user
table. The author_id
column from the note
table maps to the id
column from the user
table.
You finished configuring the application! Add some data (users and notes) to the application so you can test the different use cases.
How to use the feature
It's important to mention that you can disable query/subscription root fields only through the metadata file. You need to export and import metadata whenever you want to customize the root fields.
You will export the metadata file, make the corresponding changes and then upload the metadata file to Hasura.
Note: An alternative way of managing the metadata is to use the Hasura command-line interface (CLI). The documentation covers the hasura metadata in detail.
The console support will come soon too!
Use case: Disable GraphQL operations
The feature allows you to disable a specific GraphQL operation (queries or subscriptions) or all of them. You can grant a role to make queries, but not subscriptions, and vice-versa. Or you can disallow both.
Using the example Hasura application, you can disable all the root fields of the user
table for the guest
role as follows:
{
"role": "guest",
"permission": {
"columns": [
"id",
"title",
"content",
"author_id"
],
"filter": {},
"allow_aggregations": true,
"query_root_fields": [],
"subscription_root_fields": []
}
}
The empty arrays from the last two fields indicate that no root fields should be displayed for the user
table.
The image illustrates what you should see after applying the permissions.
⚠️ It's important to note that the guest
role can still indirectly access the user
table through the notes
relationship.
query {
note {
id
title
content
author_id
author {
id
name
}
}
}
If you run the above query, you will see the author details for each note. Keep this in mind when disabling direct access to a table.
You can see the complete metadata code for this use case in this Gist.
Use case: Primary key access only
Another use case would be to access the table only through its primary key. The client can only fetch data from the table if the client knows the primary key of a particular row.
Add the following permissions to the note
table in the metadata file:
{
"role": "guest",
"permission": {
"columns": [
"author_id",
"content",
"title",
"id"
],
"filter": {},
"query_root_fields": ["select_by_pk"],
"subscription_root_fields": ["select_by_pk"]
}
}
After you import the updated metadata file, the guest
role should only have access to the note_by_pk
root field, as shown in the image below.
You can see the complete metadata code for this use case in this Gist.
Use case: Access table through a relationship
The last scenario from this post involves providing indirect access to a table. That means accessing a table through a relationship.
In this application example, you could make the user
table accessible only through the notes
relationship.
Go to the metadata file and apply the following permissions for the user
table:
{
"role": "guest",
"permission": {
"columns": [
"id",
"name"],
"filter": {},
"query_root_fields": [],
"subscription_root_fields": []
}
}
If you go to the Hasura console and perform the query shown in the image, you should be able to access the rows from the user
table.
You can see the complete metadata code for this use case in this Gist.
Summary
The feature allows you to disable root fields and customize your GraphQL API. You can disable queries, subscriptions, or both of them. It also allows you to make tables accessible only through a relationship.
There is also a video that talks about hiding root fields.