Documentation
¶
Overview ¶
Package postgres provides a PostgreSQL driver for GORM, offering tools to facilitate the construction and management of multi-tenant applications.
Example:
package main
import (
"gorm.io/gorm"
"github.com/bartventer/gorm-multitenancy/drivers/postgres/v7"
"github.com/bartventer/gorm-multitenancy/drivers/postgres/v7/scopes"
)
// Tenant is a public model
type Tenant struct {
gorm.Model
postgres.TenantModel // Embed the TenantModel
}
// Implement the gorm.Tabler interface
func (Tenant) TableName() string {return "public.tenants"} // Note the public. prefix
// Book is a tenant specific model
type Book struct {
gorm.Model
Title string
TenantSchema string `gorm:"column:tenant_schema"`
Tenant Tenant `gorm:"foreignKey:TenantSchema;references:SchemaName"`
}
// Implement the gorm.Tabler interface
func (Book) TableName() string {return "books"} // Note the lack of prefix
// Implement the TenantTabler interface
func (Book) IsTenantTable() bool {return true} // This classifies the model as a tenant specific model
func main(){
// Open a connection to the database
db, err := gorm.Open(postgres.New(postgres.Config{
DSN: "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable",
}), &gorm.Config{})
if err != nil {
panic(err)
}
// Register models
if err := postgres.RegisterModels(db, &Tenant{}, &Book{}); err != nil {
panic(err)
}
// Migrate the public schema
if err := postgres.MigratePublicSchema(db); err != nil {
panic(err)
}
// Create a tenant
tenant := &Tenant{
TenantModel: postgres.TenantModel{
DomainURL: "tenant1.example.com",
SchemaName: "tenant1",
},
}
if err := db.Create(tenant).Error; err != nil {
panic(err)
}
// Create the schema for the tenant
if err := postgres.CreateSchemaForTenant(db, tenant.SchemaName); err != nil {
panic(err)
}
// Create a book for the tenant
b := &Book{
Title: "Book 1",
TenantSchema: tenant.SchemaName,
}
if err := db.Scopes(scopes.WithTenantSchema(tenant.SchemaName)).Create(b).Error; err != nil {
panic(err)
}
// Drop the schema for the tenant
if err := postgres.DropSchemaForTenant(db, tenant.SchemaName); err != nil {
panic(err)
}
}
Index ¶
- Constants
- func CreateSchemaForTenant(db *gorm.DB, schemaName string) error
- func DropSchemaForTenant(db *gorm.DB, schemaName string) error
- func MigratePublicSchema(db *gorm.DB) error
- func New(config Config, models ...interface{}) gorm.Dialector
- func Open(dsn string, models ...interface{}) gorm.Dialector
- func RegisterModels(db *gorm.DB, models ...interface{}) error
- type Config
- type Dialector
- type Migrator
- type MultitenancyMigrator
- type TenantModel
- type TenantPKModel
- type TenantTabler
Constants ¶
const (
// PublicSchemaName is the name of the public schema.
PublicSchemaName = "public"
)
Variables ¶
This section is empty.
Functions ¶
func CreateSchemaForTenant ¶
CreateSchemaForTenant creates a new schema for a specific tenant in the PostgreSQL database.
func DropSchemaForTenant ¶
DropSchemaForTenant drops the schema for a specific tenant in the PostgreSQL database (CASCADE).
func MigratePublicSchema ¶
MigratePublicSchema migrates the public schema in the database.
Types ¶
type Migrator ¶
type Migrator struct {
postgres.Migrator // gorm postgres migrator
// contains filtered or unexported fields
}
Migrator is the struct that implements the MultitenancyMigrator interface.
func (Migrator) AutoMigrate ¶
AutoMigrate migrates the specified values to the database based on the migration options.
func (*Migrator) CreateSchemaForTenant ¶
CreateSchemaForTenant creates a schema for a specific tenant and migrates the private tables.
func (*Migrator) DropSchemaForTenant ¶
DropSchemaForTenant drops the schema for a specific tenant.
func (*Migrator) MigratePublicSchema ¶
MigratePublicSchema migrates the public tables in the database.
type MultitenancyMigrator ¶
type MultitenancyMigrator interface {
gorm.Migrator
// CreateSchemaForTenant creates the schema for the tenant, and migrates the private tables
//
// Parameters:
// - tenant: the tenant's schema name
//
// Returns:
// - error: the error if any
CreateSchemaForTenant(tenant string) error
// DropSchemaForTenant drops the schema for the tenant (CASCADING tables)
//
// Parameters:
// - tenant: the tenant's schema name
//
// Returns:
// - error: the error if any
DropSchemaForTenant(tenant string) error
// MigratePublicSchema migrates the public tables
MigratePublicSchema() error
}
MultitenancyMigrator is the interface for the postgres migrator with multitenancy support.
type TenantModel ¶
type TenantModel struct {
// DomainURL is the domain URL of the tenant
DomainURL string `json:"domainURL" gorm:"column:domain_url;uniqueIndex;size:128"`
// SchemaName is the schema name of the tenant and the primary key of the model.
//
// Field-level permissions are restricted to read and create.
//
// The following constraints are applied:
// - unique index
// - size: 63
//
// Additionally, check constraints are applied to ensure that the schema name adheres to the following rules:
// - It must start with an underscore or a letter.
// - The rest of the string can contain underscores, letters, and numbers.
// - It must be at least 3 characters long.
// - It must not start with 'pg_', as this prefix is reserved for system schemas.
//
// Examples of valid schema names:
// - "tenant1"
// - "_tenant"
// - "tenant_1"
//
// Examples of invalid schema names:
// - "1tenant" (does not start with an underscore or a letter)
// - "pg_tenant" (starts with 'pg_')
// - "t" (less than 3 characters long)
//
SchemaName string `` /* 152-byte string literal not displayed */
}
TenantModel a basic GoLang struct which includes the following fields: DomainURL, SchemaName. It's intended to be embedded into any public postgresql model that needs to be scoped to a tenant. It may be embedded into your model or you may build your own model without it.
For example:
type Tenant struct {
postgres.TenantModel
}
type TenantPKModel ¶
type TenantPKModel struct {
// DomainURL is the domain URL of the tenant
DomainURL string `json:"domainURL" gorm:"column:domain_url;uniqueIndex;size:128"`
// SchemaName is the schema name of the tenant and the primary key of the model.
// For details on the constraints and rules for this field, see [TenantModel.SchemaName].
SchemaName string `` /* 163-byte string literal not displayed */
}
TenantPKModel is identical to TenantModel but with SchemaName as a primary key field.
type TenantTabler ¶
type TenantTabler interface {
// IsTenantTable returns true if the table is a tenant table
IsTenantTable() bool
}
TenantTabler is the interface for tenant tables.
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
testutil
Package testutil provides internal testing utilities for the application.
|
Package testutil provides internal testing utilities for the application. |
|
Package schema provides utilities for managing PostgreSQL schemas in a multi-tenant application.
|
Package schema provides utilities for managing PostgreSQL schemas in a multi-tenant application. |
|
Package scopes provides a set of predefined multitenancy scopes for GORM.
|
Package scopes provides a set of predefined multitenancy scopes for GORM. |