Finbuckle.MultiTenant icon indicating copy to clipboard operation
Finbuckle.MultiTenant copied to clipboard

Question: Multitenant within Multitenant?

Open hbermani opened this issue 3 years ago • 4 comments

So here is an interesting scenario.

You have 6 tenants, each with their own tenant-id. Three tenants decide they want to collaborate and want their data connected whilst still respecting data sovereignty. My immediate thinking is that the three tenants will need to share the same tenant-id and then segregation would be done through business logic so EF just talks to one tenant instance. But what would be really nice is the ability to maintain each tenant's tenant-id, perhaps keep them in the same Db, and get EF Core to query across the whole Db (Perhaps get the library to recognise multi-level tenant identifier (e.g. projectAlpha-tenant1 , projectAlpha-tenant2... and have the option to selectively query filter by projectAlpha)

Would welcome your thoughts as to how best to achieve such scenario with this amazing library.

hbermani avatar Apr 22 '21 15:04 hbermani

Hi @hbermani Sorry for the late reply -- I think what you described is a good approach. Nothing in the library specifically addresses this type of need. I think it also depends on what the tenant specific requirements are -- separate users? data? authentication? etc. And for the "sibling" tenants what information would they be sharing as common between them?

If you treat the "supertenant" as the Finbuckle tenant then you effectively treat all the subtenants the same and would haev to do your own separation within -- kinda defeats teh point of Finbuckle.MultiTenant but at least it helps at the super level.

AndrewTriesToCode avatar Apr 28 '21 03:04 AndrewTriesToCode

Hi @AndrewTriesToCode , Thank you for your input, honestly no need to apologise, it must be challenging keeping this ticking.

So here is my current thinking.

The simplified version:

  • Create two db contexts for the controllers to consume through DI, a primary and shared contexts. The primary would behave as Finbuckle current implementation, the shared context would apply the Like/Contains comparator when query filtering by tenant-id and use parameter tenant-id when saving changes. Is that even possible for one request?

The over engineered version:

Get Scenario:

  1. Authentication can be managed externally,
  2. bearer token claims gets passed into custom Multitenant strategy, getIdentifierAsync return tenant-id (projectAlpha-tenant2) .
  3. The request reaches a controller action that is dedicated to a shared resource (e.g. A controller that returns a list of shared forms/documents/projects). The controller will amend the tenant id in the DI injected db context to (projectAlpha) (Perhaps expose a helper method to do that, unless it's as simple as changing a value on the fly)
  4. EF would generate the query and append query filter "tenant-id CONTAINS / SQL Like projectAlpha" instead of what I expect the library does now (==), this is an internal library workings.

Post Scenario (Gets a bit complicated, E.g. a shared form with tasks users across multiple tenants in the same Db):

  1. Authentication can be managed externally,
  2. bearer token claims gets passed into custom Multitenant strategy, getIdentifierAsync return tenant-id (projectAlpha-tenant2) .
  3. The request reaches a controller action that is dedicated to a shared resource (e.g. A controller that stores a shared form/document/project and associated tasks users). The controller will need to generate queries like the following:
    • Store a record with tenant-id (projectAlpha-tenant2), this will have a bool property to say it's a shared record.
      • Then SaveChangeAsync()
    • Now amend the context tenant-id to 'projectAlpha' to retrieve task users from siblings with query filter "tenant-id CONTAINS / SQL Like projectAlpha"
    • For each task user for that record
      • Use the existing task users tenant-id and store by calling SaveChangesAsync()
  • I think step 3 can be simplified if we have control to assign tenant-id value on the entities and just use the connection string for the shared Db (Essentially overriding Finbuckle default behaviour to assign tenant-id on SaveChanges/Async). I suppose we would just be using a default EF Db context with connection string that has been passed from the TenantInfo.

How easy would it be to enable a 'Contains'/'Like' tenant-id comparator to be triggered after a MultitenantDbContext has been instantiated / when it's created as a shared context in the simplified version, as that seems to be the key to enable this functionality?

Thank you

hbermani avatar Apr 28 '21 10:04 hbermani

I keep coming across more and more use cases where a "tenant group" or similar would be useful to have. Did you make any progress on this in your use case?

AndrewTriesToCode avatar Jun 04 '21 05:06 AndrewTriesToCode

Hi Andrew,

Unfortunately, I haven't, the project priorities changed and I haven't had a chance to progress this yet.

hbermani avatar Jun 04 '21 12:06 hbermani