Table of Contents
A REST API service in Golang that handles authorization and authentication for a multi tenant web app using JWT
- Gin - Gin is the Golang Web framework used for building the API. It was chosen because it is the most popular web framework for Go and is easy to use, has high performance and a robust middleware system that allows developers to easily add functionality to their APIs.
- PostgreSQL - I decided to use a relational database for the project because there is potential for joins and relationships involving users in the database. PostgreSQL was chosen as it is a feature-rich database that is open-source and is highly scalable.
- GORM - It is the ORM used to interface with Postgres. GORM was chosen as it is a developer-friendly, feature-rich ORM built on the
database/sql
package, possessing many functionalities like auto migration, logging, contexts, prepared statements, associations, constraints etc. The GORM package takes the code-first approach and uses structs as the model for interacting with databases which makes it very developer friendly. Using GORM doesn’t trade off most of the functionalities you’ll get from writing raw SQL queries.
- Install Go
- A PostgreSQL database has to be setup locally. This can be done using Docker.
- Install Docker
- Run
docker run --name postgres-container -e POSTGRES_PASSWORD=<PASSWORD> -e POSTGRES_USER=<USER> -e POSTGRES_DB=<DATABASE> -p <HOST_PORT>:5432 -d postgres
-
Fill out the
.env
fileVariable Description Default SERVER_PORT Port on which the API server should run CLIENT_DOMAIN Domain on which the refresh cookie has to be sent localhost DB_HOST Host where the database is running localhost DB_PORT Port on which the database is running DB_PASSWORD Password for the database user DB_USER User for the database DB_SSLMODE SSL mode for the database disable DB_NAME Name of the databse ACCESS_TOKEN_SECRET Secret to sign access token REFRESH_TOKEN_SECRET Secret to sign refresh token -
In the root folder run
go run cmd/main.go
Unit tests have been written for all the handlers. Use a different database to run the tests to prevent conflicts with existing data as well as to prevent deleting data after a test during clean up.
- Fill out the
.env.testing
file - In the root folder run
go test ./...
Users of different organizations are isolated using PostgreSQL schemas. PostgreSQL schemas let us hold multiple instances of the same set of tables inside a single database. They’re essentially namespaces for tables. The following is diagram of the database structure -
Multi-tenant solutions range from one database per tenant (shared nothing) to one row per tenant (shared everything).
"Shared nothing" = separate database per tenant, most expensive per client, highest data isolation, simple disaster recovery, theoretically harder maintenance, easily customizable, lowest number of rows per table.
"Shared everything" = shared table, least expensive per tenant, lowest data isolation, complicated disaster recovery, simpler structural maintenance, highest number of rows per table.
"Shared schema" = tenants share a database, each tenant has its own named schema, cost falls between "shared nothing" and "shared everything", better isolation than "shared everything", easier maintenance than "shared nothing", more active tenants per server, disaster recovery for a single tenant is easy or hard depending on DBMS.
In the assignment, each of the organizations have their own schemas with isolated User tables. This approach was chosen as it provided a balance between isolation and cost/maintenance.
Postman spec for the API can be found here