Based on this videos, I built an advanced multitenancy boilerplate app! Video tutorial: ua-cam.com/video/hzfl6h5SlH8/v-deo.html Source code: github.com/yshmarov/moneygun
yeah, that's exactly what I'm trying to do - let you follow my thought process and solve errors that occur along the way while building something. Not just showing a completed solution :)
@@SupeRails This might be an interesting follow-up idea for this tutorial: All rails route helpers would require a tenant. I believe basecamp are mounting their rails app after the tenant in the url "/tenant/:tenant_id" while also having the rails route helpers work like magic. might be some food for thought? i've implemented it, and I do not think it is trivial. You may benefit from such a video.
Does this support inviting a user to multiple projects (tenant in video) I wanted the invite flow which I felt is missing in the video, user A invites user B and only on clicking link in email user B gets added to the project (tenant). user A invites user B to Project 1 (or Tenant 1) and Project 2 (or Tenant 2) Overall the video is great but felt this was missing.
Hey! It Does support inviting same members to different tenants. However there is no "Accept/Reject" invitation mechanism. If you want, you can build it on top, it's not that hard.
@SupeRails Not able to wrap my head how multiple invitations would be stored in DB at the same time with current user schema t.string "invitation_token" t.datetime "invitation_created_at" t.datetime "invitation_sent_at" t.datetime "invitation_accepted_at" t.integer "invitation_limit" t.string "invited_by_type" t.bigint "invited_by_id" t.integer "invitations_count", default: 0
any help on this @SupeRails? I don't think the current setup allows multiple simultaneous invitations to be tracked. Correct me if I am wrong? devise_invitable works for inviting users to an app (where a user would need to be invited just once) but for multi tenancy the database structure does not seem to be correct to me. We need a separate invitations table probably or maybe add invitation related fields to the members table
@@average_engineer You can add an "invitation_status" field to the Member model. By the default when you invite a user via email, we create a membership. It can be in status "pending". Than you can let users accept or reject membership requests.
Had a problem where I couldnt create the Members model because the role field uses jsonb datatype. My rails project was using sqlite3 so I had to change from sqlite3 to pgsql, I would recommend the Medium article from Brenden Thorton (Ruby on Rails: Switch From sqlite3 to Postgres) for anyone else who faced the same problem. Thank you for the in depth tutorial! Really appreciate your content
If I did this in a Rails api only application what is the best way to handle API authentication? Should I use Devise and make the user authenticate or the tenant authenticate? An example of explaining what I want to do: I have a tenant called ABC, this tenant has Departments (a Rails model which belongs to Tenant). Departments have many Memberships (a model which joins Department and User and Role by storing the ID of each of these in the table, the IDs are foreign keys). Role is a model which stores names of User roles. User is a user model that contains the email address, password, etc (a Devise model for now but I can change this if needed). The reason for memberships is that a user must be able to belong to multiple tenants and have different role(s) within each tenant. Each model has Pundit policies for authorization. In a separate (React) front-end, I want to allow users to authenticate as themselves to perform actions via the React web UI. I will also need them to do the same in a React Native app later on. I want to use the devise-api gem to do this. I also want tenants to have API access which will enable them to automate certain tasks on behalf of the user, this is where I'm not sure how to handle authentication. Should each user just provide their credentails/token to the developers or is it possible for the developer to have an API client/some way of authenticating where they can authenticate with and perform actions on behalf of the user without requiring the users to provide their access tokens or refresh tokens?
Hello Yaroslav, thanks for all you do for the ruby on rails community. could you make a video on how to implement an HTML template into rails 7? had a lot of error with turbo lately.
@@SupeRails Am currently having issues with turbo on my toggle button and some of the template interactivity since turbo is caching the page and does not load application.js on page navigation 🤔
Привіт, дякую за твої відео. Знайшов баг (пробував стягнути твій код - там теж відтворюється) Не вдається видалити тенант. Видає помилку PG::ForeignKeyViolation: ERROR: update or delete on table "tenants" violates foreign key constraint "fk_rails_4e4771d44b" on table "members" DETAIL: Key (id)=(1) is still referenced from table "members". Можливо знаєш як пофіксити? Бо я вже 2-години мучаюсь ))) Наперед дякую
Hello ! Love your videos, thanks a lot for what you are doing ! Do you think you could do a video about how to build a mobile app from a ruby on rails web app (with hotwire turbo & stimulus) ?
Hello Andrea! Right now I don't know how to do that, but I know that that's more-less possible (turbo native in jumpstartpro seems to have it). I will sure do that kind of video as soon as I learn the skill!!!
Hey! Great vids. I hired a man to build a RoR site for me and he is in the process of connecting the site to my gmail and google calendar app. I need to share the Oauth and SMP correct? -How do I share this kind of info without opening myself up to a security threat?
in google cloud console you/he should create an oAuth API key for your RoR app; specify in the oAuth setting to request users calendar access. log in into your RoR app via google and allow calendar access.
Great video, thanks! What if I wanted to have multiple different tenant types, and also sub-tenants? Like, TenantTypeA > SubTenantA, SubTenantB; TenantTypeB; TenantTypeC > SubTenantA, SubTenantB?
@@SupeRails yes, for example. We have multiple tenants and each one has sub-tenants that should act like the tenant itself, ie have their own team and resources, files, assets etc. The sub-tenants' members shouldn't be able to access the other sub-tenants' resources, but possibly some of the parent tenant
@@SupeRails we also have multiple types of main tenants. Would I create a new members resource for all of them, or could it be done with the one members list?
@@SupeRails I've watched this over and over again, and probably will have to do so one or two more times. But now it seems like I've got it working, with the following structure: Tenant 1 > Resources > Sub-tenant 1 > Resources > Sub-tenant 2,3... > Resources Tenant 2 > Resources Tenant 3 > Resources I created one tenant_members join table for each tenant and sub-tenant. The only a bit more complicated thing was to set the current tenant accordingly. I have an if-clause with 22 lines inn the AuthorizedController for this, lol (it also includes cases for site admins and site superadmins who can access all resources). Again, thanks a lot! Altogether I've tried this for about a month now, including the time I've tried to get this structure running with ActAsTenant, CanCanCan, Rolify etc., which all didn't work as well as this customised solution of yours. If we ever meet up, you have a drink free!
Based on this videos, I built an advanced multitenancy boilerplate app!
Video tutorial: ua-cam.com/video/hzfl6h5SlH8/v-deo.html
Source code: github.com/yshmarov/moneygun
This is a phenomenal walk through of multitenancy! Thank you for putting this together.
My pleasure, Mitchell! Glad that you enjoyed it!
Awesome, I like your pair programing style of teaching. Keep them coming
yeah, that's exactly what I'm trying to do - let you follow my thought process and solve errors that occur along the way while building something. Not just showing a completed solution :)
Yaroslav, thx for the video tutorial. i like the approach of embedding tenant in the URL!
yeah I like this approach a lot because you can have 2 tenants open in 2 tabs, and it’s less complex than managing subdomains
@@SupeRails This might be an interesting follow-up idea for this tutorial: All rails route helpers would require a tenant. I believe basecamp are mounting their rails app after the tenant in the url "/tenant/:tenant_id" while also having the rails route helpers work like magic. might be some food for thought? i've implemented it, and I do not think it is trivial. You may benefit from such a video.
Excellent video!
Does this support inviting a user to multiple projects (tenant in video)
I wanted the invite flow which I felt is missing in the video, user A invites user B and only on clicking link in email user B gets added to the project (tenant).
user A invites user B to Project 1 (or Tenant 1) and Project 2 (or Tenant 2)
Overall the video is great but felt this was missing.
Hey! It Does support inviting same members to different tenants.
However there is no "Accept/Reject" invitation mechanism. If you want, you can build it on top, it's not that hard.
@SupeRails Not able to wrap my head how multiple invitations would be stored in DB at the same time with current user schema
t.string "invitation_token"
t.datetime "invitation_created_at"
t.datetime "invitation_sent_at"
t.datetime "invitation_accepted_at"
t.integer "invitation_limit"
t.string "invited_by_type"
t.bigint "invited_by_id"
t.integer "invitations_count", default: 0
any help on this @SupeRails? I don't think the current setup allows multiple simultaneous invitations to be tracked. Correct me if I am wrong? devise_invitable works for inviting users to an app (where a user would need to be invited just once) but for multi tenancy the database structure does not seem to be correct to me.
We need a separate invitations table probably or maybe add invitation related fields to the members table
@@average_engineer You can add an "invitation_status" field to the Member model. By the default when you invite a user via email, we create a membership. It can be in status "pending". Than you can let users accept or reject membership requests.
@@SupeRails thanks i got it now. I ended up moving the invitation related fields to members table.
Thanks again!
Had a problem where I couldnt create the Members model because the role field uses jsonb datatype. My rails project was using sqlite3 so I had to change from sqlite3 to pgsql, I would recommend the Medium article from Brenden Thorton (Ruby on Rails: Switch From sqlite3 to Postgres) for anyone else who faced the same problem.
Thank you for the in depth tutorial! Really appreciate your content
you could have changed jsonb to json and it would work
If I did this in a Rails api only application what is the best way to handle API authentication? Should I use Devise and make the user authenticate or the tenant authenticate?
An example of explaining what I want to do:
I have a tenant called ABC, this tenant has Departments (a Rails model which belongs to Tenant). Departments have many Memberships (a model which joins Department and User and Role by storing the ID of each of these in the table, the IDs are foreign keys). Role is a model which stores names of User roles. User is a user model that contains the email address, password, etc (a Devise model for now but I can change this if needed). The reason for memberships is that a user must be able to belong to multiple tenants and have different role(s) within each tenant. Each model has Pundit policies for authorization.
In a separate (React) front-end, I want to allow users to authenticate as themselves to perform actions via the React web UI. I will also need them to do the same in a React Native app later on. I want to use the devise-api gem to do this.
I also want tenants to have API access which will enable them to automate certain tasks on behalf of the user, this is where I'm not sure how to handle authentication. Should each user just provide their credentails/token to the developers or is it possible for the developer to have an API client/some way of authenticating where they can authenticate with and perform actions on behalf of the user without requiring the users to provide their access tokens or refresh tokens?
Hello Yaroslav, thanks for all you do for the ruby on rails community. could you make a video on how to implement an HTML template into rails 7? had a lot of error with turbo lately.
If you have problems with forms and links, most likely you just need to add to the , and tags
@@SupeRails Am currently having issues with turbo on my toggle button and some of the template interactivity since turbo is caching the page and does not load application.js on page navigation 🤔
Great video!!!
Привіт, дякую за твої відео. Знайшов баг (пробував стягнути твій код - там теж відтворюється)
Не вдається видалити тенант. Видає помилку
PG::ForeignKeyViolation: ERROR: update or delete on table "tenants" violates foreign key constraint "fk_rails_4e4771d44b" on table "members"
DETAIL: Key (id)=(1) is still referenced from table "members".
Можливо знаєш як пофіксити? Бо я вже 2-години мучаюсь )))
Наперед дякую
in app/models/tenant.rb
has_many :members, dependent: :destroy
Hello ! Love your videos, thanks a lot for what you are doing !
Do you think you could do a video about how to build a mobile app from a ruby on rails web app (with hotwire turbo & stimulus) ?
Hello Andrea! Right now I don't know how to do that, but I know that that's more-less possible (turbo native in jumpstartpro seems to have it). I will sure do that kind of video as soon as I learn the skill!!!
Hey! Great vids. I hired a man to build a RoR site for me and he is in the process of connecting the site to my gmail and google calendar app. I need to share the Oauth and SMP correct? -How do I share this kind of info without opening myself up to a security threat?
in google cloud console you/he should create an oAuth API key for your RoR app; specify in the oAuth setting to request users calendar access. log in into your RoR app via google and allow calendar access.
@@SupeRails Do you have any videos on this or is it relatively easy to find?
@@whiteknifespeaks #32,35
How do you ensure the tenant scope with the raw sql queries without the model dsl?
why would you need to use raw sql queries? active record is enough for 99% usecases.
if you want additional security, you can add a gem like acts-as-tenant that will ensure that scoped models are not queried without a tenant.
Great video, thanks! What if I wanted to have multiple different tenant types, and also sub-tenants? Like, TenantTypeA > SubTenantA, SubTenantB; TenantTypeB; TenantTypeC > SubTenantA, SubTenantB?
@@danielb.2873 like teams within an organisation?
@@SupeRails yes, for example. We have multiple tenants and each one has sub-tenants that should act like the tenant itself, ie have their own team and resources, files, assets etc. The sub-tenants' members shouldn't be able to access the other sub-tenants' resources, but possibly some of the parent tenant
@@SupeRails we also have multiple types of main tenants. Would I create a new members resource for all of them, or could it be done with the one members list?
@@SupeRails I've watched this over and over again, and probably will have to do so one or two more times. But now it seems like I've got it working, with the following structure:
Tenant 1 > Resources
> Sub-tenant 1 > Resources
> Sub-tenant 2,3... > Resources
Tenant 2 > Resources
Tenant 3 > Resources
I created one tenant_members join table for each tenant and sub-tenant. The only a bit more complicated thing was to set the current tenant accordingly. I have an if-clause with 22 lines inn the AuthorizedController for this, lol (it also includes cases for site admins and site superadmins who can access all resources). Again, thanks a lot! Altogether I've tried this for about a month now, including the time I've tried to get this structure running with ActAsTenant, CanCanCan, Rolify etc., which all didn't work as well as this customised solution of yours. If we ever meet up, you have a drink free!
Thank you...
0.75 speed, ;)
does it mean that I should I go slower or faster? :)
@@SupeRails no, no, no, continue as you have till now, you are great, i'll adapt, thanks for your sharing your knowledge, great content 😂
Stopping all 5 seconds lol