2019-12-04

Building a multi-tenant application with Hasura

elitasson's avatar on Twitter
Johan Eliasson

Multi-tenant application. What is it and why does it matter?

A multi-tenant application is an application that support multiple tenants, usually customers, where each customer has an isolated environment in your system.

If you are building a SaaS app you must likely are building a multi-tenant application where each of your customer has its own login and can access its own data. But you share resources such as frontend, backend and database to keep costs low, maintenance easy and development fast.

So let's see how we could do this with Nhost and Hasura

We will build a Customer Relationship Management (CRM).

Project Setup

In the Nhost console, create a new project.

New Nhost project created
New Nhost project created

The Hasura instance and database comes ready with users table. We track all tables and relationships. Next we manually create two more tables for our CRM.

companies table

The companies are each tenant in the CRM and each company are a customer to us.

Creating table for companies
Creating table for companies

customers table

Creating table for customers
Creating table for customers
Adding a Foreign Keys to the companies table
Adding a Foreign Keys to the companies table

Next we'll add a foreign key to the users table. The customers.user_id is going to reference the user who is responsible for the customer. Note the we set the On Delete Violation to set null. So if the user thats responsible for the customer gets deleted, the value of customers.user_id will automatically be set to null.

Adding a foreign key to the users table
Adding a foreign key to the users table

Last thing before adding this customers table is to set a unique constraint on the email column. This will make sure we won't have any duplicated customers with the same email.

Adding a unique constraint on the email
Adding a unique constraint on the email

Table customer_comments

To at least add a little bit of functionality in our simplistic CRM we add the functionality to add and manage comments for every customer. So each company can make internal notes for each customer.

Updating the users table

Now we have our tables set up. Next we will add the column company_id to our users table so that every user is part of a company. We'll also create a foreign key between the users and the companies tables.

Adding company_id as a column on the users table
Adding company_id as a column on the users table
Adding the foreign key to the companies table
Adding the foreign key to the companies table

Insert test data

Our tables are setup correctly and it's time to set up some example data. First, we will add

Adding two test users

Let's add two test users for two different companies. We'll add the users in the Nhost console.

Adding Alice from Nike
Adding Alice from Nike
Adding user Bob for company Coca-Cola
Adding user Bob for company Coca-Cola

Next, let's add the two companies in the companies table in the database.

Add company Nike
Add company Nike
Add company Coca-Cola
Add company Coca-Cola
Our two companies in the database
Our two companies in the database

Next, let's take the id of the respective companies and update the users company_id field.

Update company_id for Alice
Update company_id for Alice

Then we will activate the column company_id as a permission variable (session variable) for Hasura to be able to use the company_id in Hasuras permission system. We check the company_id` in the Hasura console under Settings -> Authentication -> Edit.

Adding permission variable company_id
Adding permission variable company_id

Next, let's track all relationships in Hasura. This enables Hasura to follow all foreign keys and create the relationships for the GraphQL API. Klick Track All next to Untracked foreign-key relations.

Track all relationships in Hasura
Track all relationships in Hasura

Hasura permissions

Time to create the permissions to make sure users are only allowed to insert/select/update/delete correctly. We'll start with the insert in the customers table.

Insert

When a user inserts a new customer we want that new customer to have the correct fields for user_id and company_id so a user from ex company Nike only can insert customer that's associated to company Nike. Also we want the customer to be connected to the user.

We do this by Column presets. Column presets will automatically populate a column in the database with a value from a session variable. This makes sure the value is correct and can not be tampered with by any users.

So we set user_id to get the value in the session variable x-hasura-user-id and company_id to get the value in the session variable x-hasura-company-id.

We also only enable a user to insert values for email and name becuase all other values gets set automatically.

Insert permission for a customer
Insert permission for a customer

Select

For select we only want users to be able to select customers that has the same company_id as the x-hasura-company-id session variable as the user. So we make the following check for selecting customers:

{
  "company_id": {
    "_eq": "X-Hasura-company-id"
  }
}

Test the permissions

Ok, so we have made our tables and we have created some permissions. Time to test our backend. Let's go back to the Hasura console and to the GraphQL API tab. Here we can select a specific user to make the request from. We select the user in the select input in the top left corner. We insert one customer with Alice at Nike and another user with Bob at Coca-Cola.

Insert a user as alice@nike.io
Insert a user as alice@nike.io
Insert a customer as bob@cocacola.com
Insert a customer as bob@cocacola.com

We now have two customers in the database. One customer for each company.

Two customers in the customer's database
Two customers in the customer's database

Back in our GraphQL API, we make a request to get all customers as alice@nike.io. As you see, we only get the one customer associated with the company which Alice is part of.

Same thing if we switch user to bob@cocacola.com and make the exact same query.

Summary

In this blog post we have showed you how you can model your multi tenant application with Nhost and Hasura. This is done by using the session variables for a user and make the appropriate permission rules with custom permission checks and column presets.

Try Nhost for Free Today

Get a perfect backend with Hasura
Get started