Multi Tennant Saas

Hi,

I’m using strapi to for a SaaS product to help gyms manage their members, trainers and content.

I’m having a really hard time figuring out how to provide a multi-tenant solution, given that this core functionality is not implemented on the strapi side yet see this issue

I’m currently thinking of having a content collection called Organization, with a relation to an Admin User (User type, admin role). Then, in the controllers, filtering out all the data that does not pertain to that Org.

There are many issues with this approach, for example the inefficiency of querying the db and then programatically filtering out most of the query result.

Could you please provide some guidance as to the best way to achieve this given the current strapi release?

2 Likes

Is the issue you are referring to within the Admin panel or the REST/GraphQL routes?

I’m not sure I understand your question.

I’m asking for guidance on how best to implement a multi-tenant solution, given the current strapi constraints (i.e., without waiting for this feature to be implemented).

If I understand you’re asking about which controllers I’d be implementing the cross-organization data blocking functionality:
I was thinking about doing it in the REST api controllers by filtering for data that only pertains to the org that the authenticated admin pertains to. But this solution is sub-optimal

Does that make sense?

Where will each of your tenants be contributing content? Via the Strapi Admin panel or are you sending that from other frontend via REST/GraphQL?

the latter.

I’ll say that my concerns here are:

  1. data isolation
  2. permission and role enforcement for superadmin, tenant admin, tenant employee, tenant’s end user
  3. query performance (is like i mentioned before - if I have to do the isolation on a query result, then i’m executing an unoptimized query)
  4. superadmin visibility across tenants (in a single admin panel)
  5. datamodel (how should I desing my content_types s.t. the above concerns are addressed)

In that case it’s much simpler, you just need to implement some policies, forgive the old example, but this is one I constructed a few months back that more or less focuses on a similar request from another user. You are welcome to take a look and pull whatever you can from it:

And to apply the policies is as simple as defining them via the routes:

In this case the policy was designed to be multi-purpose but you could just as easily create multiple policies for very specific purposes, note that policy logic is basically executed as a scoped Koa middleware, it’s executed before the controller as long as the code sits before the await next() anything after the await next() will be executed after the controller (basically the request chain working in reverse to return the information to the user).

A very rough tree of the request chain would be something like:

  • User makes request
  • Request middlewares are called
  • Users-Permissions plugin validates the request (Also sets the ctx.state.user)
  • Koa matches the route via regex
  • Execute any policies
  • Execute the handler (controller => service => query)
  • Begin reverse back up through all the steps (bypassing Users-Permissions since nothing is ran there)

Hopefully that helps, please do let me know if you figure out a useful solution as I would be interested in taking a look at your code, and don’t hesitate to ask for more information if you need. :slight_smile:

6 Likes

@DMehaffy, thanks for your sample, I too am attempting to solve a similar issue, I was able to isolate all data per organization (using your examples), but I am having trouble with having users (API consumers) under each organization.

I’d like it to be possible for the same person (same email/username) to be able to register twice, under each organization (maybe even using a different password). This means there would potentially be 2 records in the Users table with the same email/username, which is currently not possible.

Any ideas on how I could do that? Thanks in advance!

I am trying to create a SaaS where my clients can sell things to their users, but there’s a chance the same user subscribes to 2 of my clients, and considering the rest of the data structure is identical (and not very complicated) it would be great to use a single Strapi project.

Currently that is not possible, if something like this starts to become a requirement for you, it’s quite likely you need to consider multiple Strapi projects to handle your use-case.

Hello @DMehaffy. Really thank you for your contributions to the forum and the community. I’m in the same situation as @anzorb. I’m about to start a SaaS project and I would love to use Strapi as my CMS, however I don’t think Multi Tenancy will be implemented anytime soon. Could you recommend or let me know any CMS alternatives that would work for this? Thank you once again!

None that I can think of that really handle multi-tenancy. It’s an extremely difficult type of application to handle in a general use-case (meaning everyone has different expectations of what is needed).

But yeah probably not anytime in 2021