11# multi-tenant-persistence-for-saas
2+
23[ ![ Go Report Card] ( https://goreportcard.com/badge/github.com/vmware-labs/multi-tenant-persistence-for-saas )] ( https://goreportcard.com/report/github.com/vmware-labs/multi-tenant-persistence-for-saas )
34[ ![ GitHub Actions] ( https://github.com/vmware-labs/multi-tenant-persistence-for-saas/actions/workflows/go.yml/badge.svg )] ( https://github.com/vmware-labs/multi-tenant-persistence-for-saas/actions?query=branch%3Amaster )
45[ ![ Go Reference] ( https://pkg.go.dev/badge/github.com/vmware-labs/multi-tenant-persistence-for-saas/ )] ( https://pkg.go.dev/github.com/vmware-labs/multi-tenant-persistence-for-saas )
@@ -23,30 +24,47 @@ information stored in a Postgres database:
2324
2425``` mermaid
2526sequenceDiagram
26- actor C as Coke User
27- actor P as Pepsi User
27+ actor C1 as Coke User (Americas)
28+ actor C2 as Coke User (Europe)
29+ actor P as Pepsi User (Americas)
2830 participant M as Multitenant Persistence
29- participant A as Authorizer
31+ participant A as Authorizer(+Instancer)
3032 participant DB as Postgres
3133
3234 rect rgb(200, 225, 250)
33- C ->>+ M: Find VM1
35+ C1 ->>+ M: Find VM1
3436 M ->>+ A: GetOrgID
3537 A -->>- M: Coke
36- M ->>+ DB: set_config(org_id, Coke)
38+ M ->>+ A: GetInstanceID
39+ A -->>- M: Americas
40+ M ->>+ DB: set_config(org_id=Coke, instance_id=Americas)
3741 M ->>+ DB: SELECT * FROM VM WHERE ID=VM1
38- DB -->>- M: | CokeWebServer1 | ID=VM1 |
39- M -->>- C: Return {Name=CokeWebServer1, ID=VM1}
42+ DB -->>- M: | CokeWebServer1 | ID=VM1 | us-west-1|
43+ M -->>- C1: Return {Name=CokeWebServer1, region=us-west-1, ID=VM1}
44+ end
45+
46+ rect rgb(225, 250, 250)
47+ C2 ->>+ M: Find VM1
48+ M ->>+ A: GetOrgID
49+ A -->>- M: Coke
50+ M ->>+ A: GetInstanceID
51+ A -->>- M: Europe
52+ M ->>+ DB: set_config(org_id=Coke, instance_id=Europe)
53+ M ->>+ DB: SELECT * FROM VM WHERE ID=VM1
54+ DB -->>- M: | CokeWebServer1 | ID=VM1 | eu-central-1 |
55+ M -->>- C2: Return {Name=CokeWebServer1, region=eu-central-1, ID=VM1}
4056 end
4157
4258 rect rgb(200, 250, 225)
4359 P ->>+ M: Find VM1
4460 M ->>+ A: GetOrgID
4561 A -->>- M: Pepsi
46- M ->>+ DB: set_config(org_id, Pepsi)
62+ M ->>+ A: GetInstanceID
63+ A -->>- M: Americas
64+ M ->>+ DB: set_config(org_id=Pepsi, instance_id=Americas)
4765 M ->>+ DB: SELECT * FROM VM WHERE ID=VM1
48- DB -->>- M: | PepsiWebServer1 | ID=VM1 |
49- M -->>- P: Return {Name=PepsiWebServer1, ID=VM1}
66+ DB -->>- M: | PepsiWebServer1 | ID=VM1 | us-west-2 |
67+ M -->>- P: Return {Name=PepsiWebServer1, region=us-west-2, ID=VM1}
5068 end
5169```
5270
@@ -56,15 +74,28 @@ Currently, following features are supported:
5674
5775- ** CRUD operations** on persisted objects, where data is persisted in Postgres
5876 database
59- - ** Role-based access control (RBAC)** .
60- - ** Metadata support** like CreatedAt, UpdatedAt, DeletedAt (using gorm.Model)
61- - ** Versioning** . If a record persisted in data store has a field named
62- _ revision_ , versioning (revisioning) will be supported on that table. Among
63- multiple concurrent updates, only one will succeed.
64- - ** Multi-tenancy** . DAL uses row-level security (RLS) feature of Postgres and
65- a pluggable ` Authorizer ` interface to support multi-tenancy. User's with
66- tenant-specific roles (` TENANT_WRITER ` , ` TENANT_READER ` ) will be able to
67- access only their own tenant's data.
77+
78+ - ** Multi-tenancy** persistence is supported with ` org_id ` as the column used
79+ .for accessing data for different tenants using row-level security (RLS)
80+ feature of Postgres. A pluggable ` Authorizer ` interface to support multi-tenancy.
81+ User's with tenant-specific roles (` TENANT_WRITER ` , ` TENANT_READER ` ) will be
82+ able to access only their own tenant's data.
83+
84+ - ** Role-based access control (RBAC)** based on the role mappings from the
85+ .user to DBRole Mappings.
86+
87+ - ** Metadata support** like CreatedAt, UpdatedAt, DeletedAt (using ` gorm.Model ` )
88+
89+ - ** Revisioning** is supported if a record being persistent has a field named
90+ .` revision ` . Among concurrent updates on same revision of the record only
91+ .one of the operations would succeed.
92+
93+ - ** Multi-instance** persistence is supported with ` instance_id ` as the column used
94+ for accessing data for different deployment instances using row-level security
95+ (RLS) feature of Postgres. ` Instancer ` interface is used to support multi-instances.
96+ .If instancer is not configured ` instance_id ` column doesnt have any special meaning
97+ .and treated as normal attribute.
98+
6899
69100
70101## Documentation
@@ -73,6 +104,10 @@ Following interfaces are exposed by the Golang library to be consumed by the use
73104
74105### [ Authorizer] ( docs/DOCUMENTATION.md#authorizer )
75106
107+ #### [ Tenancer] ( docs/DOCUMENTATION.md#tenancer )
108+
109+ #### [ Instancer] ( docs/DOCUMENTATION.md#instancer )
110+
76111### [ DataStore] ( docs/DOCUMENTATION.md#datastore )
77112
78113### [ ProtoStore] ( docs/DOCUMENTATION.md#protostore )
@@ -81,9 +116,7 @@ Following interfaces are exposed by the Golang library to be consumed by the use
81116
82117## Future Support
83118
84- - Some of the topics that require further discussion are the following:
85- - Do we want to provide functionality for microservices to subscribe for updates in certain tables?
86- - Do we need to provide pagination or streaming support using channels?
119+ - Do we want to provide functionality for microservices to subscribe for updates in certain tables?
87120
88121## Contributing
89122
0 commit comments