Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial PR for allowing multi tenant strategies #5

Closed
wants to merge 5 commits into from

Conversation

mailaneel
Copy link
Contributor

#3

@icebob This is my initial PR to get feedback on if I am right path or not, Right now all tests are passing.

Big change you will see is changing from this.adapter to this.getAdapter(ctx)

Example of how I am thinking of using tenantStrategy

const getHash = (ctx) => ctx.meta.tenantId

module.exports = {
  name: 'role',
  mixins: [DBService],
  tenantStrategy: {
    getAdapterHash: getHash,
    getAdapter: (ctx) => {
      return new MongooseAdapter({
        schema: RoleSchema,
        modelName: 'Role',
        uri: `${process.env.MONGO_URI_1}/${getHash(ctx)}`,
        opts: Object.assign({}, {
          useMongoClient: true
        })
      })
    }
  }
}

Pending Tasks:

  • Add Tests for tenantStrategy
  • Implement adding tenantKeys to queries

…ter, so we can support multiple adapters i.e per tenant

all tests passing, need to add tests for tenantStrategy, this is initial design for tenantStrategy to see if it works and also to get feedback
@coveralls
Copy link

coveralls commented Jan 28, 2018

Coverage Status

Coverage decreased (-0.5%) to 96.344% when pulling d74b06b on mailaneel:master into 91ad674 on ice-services:master.

@mailaneel
Copy link
Contributor Author

Approach 2:

This can be instead of tenantStrategy we can accept adapter as a function which gets called every time and must return adapter. In this case we do not cache and allow the adapter function to take care of caching.

mailaneel added a commit to mailaneel/moleculer-db that referenced this pull request Jan 28, 2018
…rvices. This allows for use cases where we need to create models dynamically @see moleculerjs#5
mailaneel added a commit to mailaneel/moleculer-db that referenced this pull request Jan 28, 2018
…rvices. This allows for use cases where we need to create models dynamically @see moleculerjs#5
@mailaneel mailaneel mentioned this pull request Jan 28, 2018
@icebob
Copy link
Member

icebob commented Jan 29, 2018

@mailaneel I am not familiar with tenants. Could you show me a simple use case why it is good and need to implement? Thank you!

@mailaneel
Copy link
Contributor Author

mailaneel commented Jan 29, 2018

for my use case I want to use separate database for each each business that subscribes to my product.

I am calling each business here as tenant and they will have a separate database. In my code I want to be able to connect to these databases dynamically based on some parameters that are available in my context.

Example JWT Token

{
"name": "ABC company",
"tenantId": "123456"
}

Now in my middleware I will set this data into context.meta key so I can access this information in all ctx.call

And based on the data available in ctx.meta I want to use different adapter which might be pointing to a different database ex: mydatabase_123456 in mongo

@icebob
Copy link
Member

icebob commented Jan 29, 2018

Thanks. And how does tenantKeys work?

@mailaneel
Copy link
Contributor Author

tenantKeys work similar to shardKey in mongodb or mongoose

lets say, we have configured tenantkeys as [“tenantId”]

this is useful when all tenants data is stored in same collection where every doc will have tenantId

We will need a getter, to get all tenantKeys values from ctx.. this should be provides in tenantStrategy as a function

if tenantKeys are not present in query throw Error

If we get a query for userId:1 -> this will be converted to userId:1, tenantId:12345 before passing to adapter

@mailaneel
Copy link
Contributor Author

the other way to think about it is just allow to get adapter based on context and let user deal with implementation details i.e whether to use tenantkeys or to use multiple databases..

@icebob
Copy link
Member

icebob commented Feb 8, 2018

Sorry, I need more time to consider it. Currently, I'm working on other things.

@mailaneel mailaneel closed this Jun 4, 2019
@Karnith
Copy link

Karnith commented Apr 10, 2020

I feel this is a valuable addition to the db adapters. As it stands out of the box, the db adapters are considered single app adapters (meaning that the adapters are primarily for apps that would have single or multiple dbs for the entire app to consume with user data and content mingling with other user data in the same collection relational to it). By adding multi tenant capabilities a developer is able to architect the app segregating user data by user and securing it. To give a better idea around multi tenant apps, user data is typically contained in one of 3 ways in MongoDB:

  • on document level (cheap and easy to administer but only secured by app logic)

  • on collection level (not recommended, due to breaking mongoDB concepts)

  • on database level (very flexible and secure)

the preference would be segregation on the database level. Aside from security, this also enables the ability of no impact to other tenants of the system when a tenant requires recovery of lost data. Since the backup & disaster recovery strategy would consist of backups done per tenant database, if a tenant requires a restore of their data nothing would be altered or changed in any other tenant database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants