Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multitenancy (acts_as_tenant) with Devise (users default scoped by subdomain) breaks sessions

Gems

ruby 1.9.3
rails 3.2.11
devise 2.2.3
acts_as_tenant 0.2.9

Code

All my models are scoped by a domain_id:

class User < ActiveRecord::Base
  acts_as_tenant(:domain)
  #...
end

Then, in my application_controller, I set the current tenant from the domain:

class ApplicationController < ActionController::Base
  set_current_tenant_through_filter
  before_filter :set_tenant
  protect_from_forgery
  #...

  def set_tenant
    #...
    @domain = Domain.find_or_create_by_name(request.host)
    set_current_tenant(@domain)
  end
end

All works well for all models except for sessions: Everytime a page is loaded, it will log-out the first user who load a page with another tenant. By loading this page, it will log-out the first user who [... etc.]

Hypothesis: when Alice visits a domain, Rails loads current_tenant=alice_domain (ok). All works as expected, until Bob visits another domain, load current_tenant=bob_domain. When Alice refreshes her page, Rails still has current_tenant==bob_domain. Rails checks session: Alice does not exist with bob_domain scope, so Devise forces Alice logout. Then application_controller sets current_tenant=alice_domain... which logs-out Bob.

Dirty workaround: do not use acts_as_tenant in user model, scope users by domain myself in every controllers, then overwrite devise to scope login and registration by domain. And I'm unsure how to get Devise aware of current domain in sessions stuff. By the way, replacing acts_as_tenant by a manual default_scope in user falls in the same strange bugs. It seems very dirty to go this way.

I'm looking for a clean solution for days. I would be very grateful for any help.

like image 878
Habax Avatar asked Oct 21 '22 18:10

Habax


1 Answers

Fixed, in application_controller, change

before_filter :set_tenant

to

prepend_before_filter :set_tenant

in order to default_scope everything, including User, before Devise checks the user's session.

like image 84
Habax Avatar answered Oct 27 '22 18:10

Habax