https://github.com/strongloop/poc-loopback-multitenancy
Proof of concept for multitenancy in LoopBack.
https://github.com/strongloop/poc-loopback-multitenancy
Last synced: 7 months ago
JSON representation
Proof of concept for multitenancy in LoopBack.
- Host: GitHub
- URL: https://github.com/strongloop/poc-loopback-multitenancy
- Owner: strongloop
- Created: 2016-04-06T23:21:13.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2019-05-10T12:59:49.000Z (over 6 years ago)
- Last Synced: 2025-05-02T10:51:01.416Z (9 months ago)
- Language: JavaScript
- Homepage:
- Size: 28.3 KB
- Stars: 8
- Watchers: 15
- Forks: 4
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
# poc-loopback-multitenancy
Basic proof of concept for multitenancy in LoopBack.
## Design
- Customer1
- datasource: `db`
- instances: `[{name: 'Andy', name: 'Bob', name: 'Carol'}]`
- Customer2
- datasource: `db2`
- instances: `[{name: 'Dan', name: 'Eric', name: 'Francis'}]`
```
START :
| : +---------------+ +--------------+
+--/api/customers?tenant=1----->|tenant resolver|--tenantId-->|model resolver|
: +---------------+ +--------------+
: |
: v
+--[{relevant models}]<--------------------------- (Customer + tenantId).find()
| :
END :
```
## How it works
A request to `/api/customers?tenant=1` comes in.
The tenant-resolver middleware parses the tenant identifier passed in the query
string. The tenant id is then stored in `req.tenantId` and passed down to the
next middleware.
Next, the model-resolver middleware is triggered (and given the request with the
tenant identifier set -- `req.tenantId`). The model resolver uses the tenant
id to determine which model to call.
For example, If tenant id is 1, use the Customer1 model (which is attached to
datasource 1 -- `db`) and fetch it's associated data. If tenant id is 2,
use the Customer2 model (which is attached to datasource 2 -- `db2`) and fetch
it's associated data.
## Concepts
We basically use a combination of middleware to get the tenant id and use it to
determine which physical model to call during runtime. In this case, we've
already preconfigured the physical models (using the logical models defined in
`model.json` files) before the application is started.
## Considerations
- The way LB is coded today do not allow for multiple model definitions (we are
forced to create two separate models to prevent naming collisions --
`Customer1` and `Customer2` instead of just one definition `Customer`
- In this POC, we hardcode model resolution to simplify the implemention (ie.
`Customer + tenantId`, but in the real version, we should probably also
dynamically determine the model to call (ie. Model.name + tenantId). This can
easily be done by parsing the endpoint for the model name (ie.
/api/**customers**]?tenant=1 -- the customers part of the URI for example)
- Datasources cannot be changed dynamically during runtime since they are mapped
in the configuration file before the app is started. We could probably do this
with another resolution layer before actually fetching the instances
## Tests
Run `npm test` in the project root.