-
Notifications
You must be signed in to change notification settings - Fork 44
Home
There are two problems that you would face when you start to build a saas
(multi-tenancy) system
-
- How to determine current scope of tenant
-
- How to do data isolation in the data storage
- Host: super admin site, where you can manage all tenants
- Tenant: tenant site, where customers can use your software
go-saas
uses the go context
api to store current tenant value, and define a TenantResolver
interface to resolve current tenant id or name
The DefaultTenantResolver
which implements TenantResolver
uses slice of TenantResolveContributor
and call each Resolve
function one by one. It uses the Chain-of-responsibility pattern
For most web applications, you can use the implemented TenantResolveContributor
like
-
CookieTenantResolveContributor
: resolve from a cookie value -
DomainTenantResolveContributor
: resolve from a domain regex -
FormTenantResolveContributor
: resolve from a from value -
HeaderTenantResolveContributor
: resolve from a header value -
QueryTenantResolveContributor
: resolve from a query value
For web application build on top of gin,
you can use the MultiTenancy
middileware to inject resolved tenant value in every request, sample codes
After current tenant is resolved, you can call FromCurrentTenant(ctx context.Context) BasicTenantInfo
to get current tenant
TenantStore
: define a query interface to resolve tenant info including with connection string key-values
go-saas
defines a ConnStrResolver
to resolve connection string of current tenant
The DefaultConnStrResolver
resolve connection string value from config directly. And the MultiTenancyConnStrResolver
use TenantStore
to query current tenant info, once a host environment detected, a fallback resolve behavior to DefaultConnStrResolver
would be performed
you can use NewEnableMultiTenancyDataFilter(ctx context.Context)context.Context
to get a disable tenant filter context, and use this conext to access database
when you create an entity, if current tenant id is not equal with TenantId value of this entity, in tenant site, the value will be always normalize to current tenant id
You can also disable with NewDisableAutoSetTenantId(ctx context.Context)context.Context
to get a disable auto set context
For application use gorm
-
- Add
HasTenant
field to your entity or addMultiTenancy
to your struct
- Add
type TestEntity struct {
ID string
MultiTenancy
}
type TestEntity1 struct {
ID string
TenantId HasTenant `gorm:"index"`
}
-
- Initialize a
DefaultDbProvider
, initialze aGormTenantStore
, and initialize aGormTenantRepo
you can see the sqlite sample in sample code
- Initialize a
-
- Do use the same
DefaultDbProvider
to resolve*gorm.Db
by context, the data isolution is automaticly done bygorm
- Do use the same
-
- Do not forget to close all dbs
- Add support for more web frameworks
- Add support for more orms