-
-
Notifications
You must be signed in to change notification settings - Fork 267
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
User to have access to many tenants #231
Comments
I like this idea and could certainly see this being useful for some apps I'm working on. Are you envisioning that the interface would change such that if you passed in an Enumerable to Something like this? set_current_tenant(current_user.accounts) ActsAsTenant.with_tenant(current_user.accounts) do
end |
@timmyd87 the gem leaves that for you to configure, depending on your needs. basically you will need to do the following:
here's an app where I was playing around with what you want to achieve (unfinished) p.s. @excid3 haha you're fast |
Wow, thanks for the fast responses @excid3 and @yshmarov!! So i can only go on what I've used in the past which is the Milia Gem. It's implementation did what you're suggesting @excid3 and find all tenants for a user and simply returned the first one in that list. Here's the code from their lib: `def set_current_tenant( tenant_id = nil )
So I'm looking for something similar. @yshmarov i like the approach here but to clarify this would require a user to come to a landing page that listed out all tenants/accounts which when one was selected it would pass the tenant id and set the tenant? |
Sorry @yshmarov i now understand what you were saying. I've been able to build additional account/tenant creation which is all working, just working on a 'switch tenant' action. I'll post my solution here. |
Righto, so i've had a go at this and have been able to successfully:
The problem I'm facing is as i have a rails api application and I'm making requests with a web tokens and can't see a way to persist a tenant. I have tried session storage but that is reset to nil on every request along with the current_tenant so i end up back with the last account created every time I try and change the tenant. `
end` Like the example from @yshmarov I could try and pass the :account_id params on every request however I would need to pass that in to the JWT payload which is defined in my User Model...and you can't access the ActsAsTenant.current_tenant method in models. Basically it's close but no cigar. What would you suggest? Is there a way to access the current_tenant method in models I'm missing? What's best practice here? |
@yshmarov what happened to your test repo here: https://github.com/yshmarov/acts-as-tenant I would love to take a look at how you handled multi tenant user sign-ons. |
@senorlocksmith I've renamed it, you can access it here https://github.com/yshmarov/actsastenant-demo I didn't think anybody would be looking at it:) |
I have this # frozen_string_literal: true
# app/controllers/concerns/tenantable.rb
require 'active_support/concern'
module Tenantable
extend ActiveSupport::Concern
included do
set_current_tenant_through_filter
before_action :set_workspace
end
private
def set_workspace
workspace_id = request.headers['Workspace']
current_workspace = Workspace.find(workspace_id)
set_current_tenant(current_workspace)
end
end So my front-end app just needs to send a |
@taschetto
Concerns (as you have) are also a very good way to go with |
@yshmarov but how can a user be part of multiple tenants if have a single |
@taschetto Imagine slack or trello. A user can be a member in multiple teams there and he can switch from one team/board to another. You can have a method to switch from one tenant to another (change user.tenant_id) Here's a source code of a very basic implementation https://github.com/yshmarov/actsastenant-demo/ And here's a much more advanced demo of all the beauty of acts_as_tenant put to the maximum https://saas.corsego.com/ |
Hello @yshmarov. Is the http://ewlit.herokuapp.com/ link ok? I was checking it but seems link an empty demo heroku page. I would like to check if that demo can help me, I was looking for some similar feature, i have a resource i need to be listed for two different "tenants", so i was thinking on having the resource with multiple tenants ids, but I can't figure out if there is a way to resolve it with the gem, for example making the query clause custom for this model Of course i can get it working without having the resource with the acts_as_tenant and add the tenant on the where clause directly. The User/Member/Tenant schema is not good for me unfortunately cause I have different user types, and the member in my case has a lot of information so i prefer not to have the member duped with all its information. Thanks |
@pldavid2 sorry, I've updated the link to heroku. Now it's correct |
@pldavid2 in your case maybe you don't need multitenancy - maybe just role-based access to specific data? |
Hello @yshmarov thanks for the update! The thing is I have different kind of users (where I already use rolify), and each of these user types can have different tenants so that is where I use acts_as_tenants. |
Hi guys, I need to create a multitenant Rails app that basically follows these requirements. And I think this discussion is in some way related to what I want to build. Basically the platform can accept Admin Users to signup and are able to create multiple Restaurants and for each restaurant connect a unique Domain name to be accessed by customers.
Can anybody share any thoughts on how to tackle it or the best approach to follow? |
@pldavid2 can you rephrase and give another example? |
|
Thx @yshmarov for your response! Two questions:
|
it's getting more and more complicated 😂
With HABTM: Without HABTM: |
Hello @yshmarov . Well to give my easier use case, basically I have companies and clients. Both of them are users on my system. Companies have a tenant and or only shown to clients that have that tenant. As I need to filter both companies and clients by tenant in several places of my app is useful for me to in the act_as_tenant as gem, and was trying to avoid removing the act_as_tenant in the client model. |
@pldavid2 see my answer to @alexventuraio - it should be also valid for you. Basically to make a platform where a
Basically @hazelsparrow @borisd - this is the kind of architecture you are building, right? |
My needs are more similar to what Chris said near the beginning of the thread:
The application is where one of my tenants has their own resources, but can also manage other tenants' resources on their behalf. Instead of switching between tenants, I'd like the "on behalf of" tenant to have the resources scoped to all the tenants they have access to. For example (assuming an class OrdersController < ApplicationController
set_current_tenant_through_filter
before_action :set_tenant
def index
@orders = Order.all
end
def set_tenant
set_current_tenant(Organisation.where(id: current_user.delegated_organisations))
end
end I basically have two questions:
I'm basically planning to diff --git a/lib/acts_as_tenant/model_extensions.rb b/lib/acts_as_tenant/model_extensions.rb
index b9a1030..d96b38a 100644
--- a/lib/acts_as_tenant/model_extensions.rb
+++ b/lib/acts_as_tenant/model_extensions.rb
@@ -21,7 +21,12 @@ def acts_as_tenant(tenant = :account, **options)
end
if ActsAsTenant.current_tenant
- keys = [ActsAsTenant.current_tenant.send(pkey)].compact
+ if options[:multiple_tenants] && !ActsAsTenant.current_tenant.is_a?(ActiveRecord::Base)
+ keys = [ActsAsTenant.current_tenant.pluck(pkey)].compact
+ else
+ keys = [ActsAsTenant.current_tenant.send(pkey)].compact
+ end
+
keys.push(nil) if options[:has_global_records]
query_criteria = {fkey.to_sym => keys}
@@ -37,7 +42,7 @@ def acts_as_tenant(tenant = :account, **options)
# - validate that associations belong to the tenant, currently only for belongs_to
#
before_validation proc { |m|
- if ActsAsTenant.current_tenant
+ if ActsAsTenant.current_tenant && (!options[:multiple_tenants] || ActsAsTenant.is_a?(ActiveRecord::Base))
if options[:polymorphic]
m.send("#{fkey}=".to_sym, ActsAsTenant.current_tenant.class.to_s) if m.send(fkey.to_s).nil?
m.send("#{polymorphic_type}=".to_sym, ActsAsTenant.current_tenant.class.to_s) if m.send(polymorphic_type.to_s).nil? I don't have any test coverage or documentation for this, but if there's interest, I could probably tidy this up and make it into a PR. Alternatively, a PR which allows you to pass a custom proc to replace Thoughts? Sorry for hijacking this issue a bit! |
@lewiseason I have a very similar need for my multitenant app. I have 'partners' where i would like them to have access to multiple tenants but also persist access to their own tenant or 'partner portal' where they can view data from their accessible tenants (in their case, their business clients). Are we on the same page? or have i misunderstood what you're trying to achieve? |
@timmyd87 Yes, exactly. Ideally, I'd use this for our own staff too—to access the customer area of the app, you have to specify which customer you're accessing it as. The other thing which I anticipate needing is the ability to further filter records for a partner, so they can see their own records, a specific tenant they have access to, or everything that's visible to them. With all that in mind, I'm beginning to think a simple concern, and doing this explicitly might be easier. For (untested) example: class Account < ApplicationRecord
belongs_to :partner, class_name: "Account"
has_many :accessible_accounts, class_name: "Account", foreign_key: :partner_id
end
class Widget < ApplicationRecord
include HasAccount
end
module HasAccount
extend ActiveSupport::Concern
included do
belongs_to :account
end
class_methods do
def for_account(account)
where(account: account)
end
def accessible_by_account(account)
where(account: [account] + account.accessible_accounts)
end
end
end
class ApplicationController < ActionController::Base
# <snip>
def current_account
@current_account ||= begin
# You'd want to do something more sophisticated here, but this allows
# staff (and partners) to "impersonate" a specific account
Account.find(session[:account_id]) || current_user.account
end
end
end You don't get all the enforcement and automatic behaviour that |
I love this gem. It's amazingly simple to use and thank you for building it!
One enhancement I would love to see is the ability for a user to have many accounts/tenants so they can jump between them. I'm not talking about sharing tenant data (contacts, posts etc) between tenants, but simply so a user is unscoped and the current_tenant methos looks for all possible tenants rather than a single object.
A user could then jump between tenants as they need, sign up for more accounts etc etc.
I have never contributed to a Gem before but wold be keen to give this a go. Thoughts?
The text was updated successfully, but these errors were encountered: