ruby on rails - Authorization in multi tenant app -
in railscasts episode 388 - multitenancy scopes, ryan adding default scope ensure security:
alternatively can use authorization library such cancan handle scoping isn’t designed multi-tenant apps , won’t solve problem well. 1 case it’s acceptable use default scope that’s we’ll do.
class tenant < activerecord::base attr_accessible :name, :subdomain has_many :topics end class topic < activerecord::base attr_accessible :name, :content belongs_to :user has_many :posts default_scope { where(tenant_id: tenant.current_id) } end my question is: want implement authorization (for example cancan) , define abilities these:
class ability include cancan::ability def initialize(user) user ||= user.new # guest user (not logged in) if user.admin? can :manage, topic else can :read, topic end end end does user have ability manage topics of tenants or within tenants scope?
or more general question: what's right method of authorization multi tenant applications?
you on right track using cancan, or cancancan since cancan deprecated, think.
i don't default_scope reason not threadsafe. user id stored in class variable, means 2 or more concurrent users in app break unless use unicorn or other web server makes sure no more 1 single client connection access same thread.
you should therefore use cancan.
class ability include cancan::ability def initialize(user) user ||= user.new # guest user (not logged in) if user.admin? # user's own topics only: can :manage, topic, user_id: user.id # or, tenant can :manage, topic, tenant_id: user.tenant.id if user.tenant # user belongs_to tenant can :manage, topic, tenant_id: user.tenants.map(&:id) if user.tenants.any? # user has_many tenants else can :read, topic # can read topic. end end end pick strategy need 3 examples above.
edit more complicated example multi-tenant admins @joshdoody's question in comments:
class admin < user; end class tenantadmin belongs_to :tenant belongs_to :admin, class_name: user end class ability include cancan::ability def initialize(user) user ||= user.new # guest user (not logged in) if user.admin? can :manage, topic, tenant_id: tenantadmin.where(admin: user).map(&:tenant_id) else can :read, topic # can read topic end end end now, might not performant like, general idea have tenantadmins able manage topics within tenants.
hope helps.
Comments
Post a Comment