Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise and ActsAsTenant not playing nicely together

I am using ActsAsTenant, and I keep getting the error below on any Devise route (i.e. any Devise controller). It seems that Devise tries to get the current_user or something to do with getting a User before the tenant has been set, so ActsAsTenant then raises an error. I tried using a prepend_before_action to set the tenant but that didnt work.

class ApplicationController < ActionController::Base  
    protect_from_forgery with: :exception

    prepend_before_action :secure_app
    before_action :authenticate_user!

    private

    def secure_app
        self.class.set_current_tenant_by_subdomain_or_domain
    end
end

How do I make sure that the tenant is set before Devise starts looking for the current_user?

ActsAsTenant::Errors::NoTenantSet at /edit ActsAsTenant::Errors::NoTenantSet

block in User.acts_as_tenant
() home/lee/.rvm/gems/ruby-2.1.1/bundler/gems/acts_as_tenant-1b7d146d750b/lib/acts_as_tenant/model_extensions.rb, line 54
block (3 levels) in User.build_default_scope
activerecord (4.1.4) lib/active_record/scoping/default.rb, line 103
User::ActiveRecord_Relation#scoping
activerecord (4.1.4) lib/active_record/relation.rb, line 285
block (2 levels) in User.build_default_scope
activerecord (4.1.4) lib/active_record/scoping/default.rb, line 103
block in User.build_default_scope
activerecord (4.1.4) lib/active_record/scoping/default.rb, line 102
User.evaluate_default_scope
activerecord (4.1.4) lib/active_record/scoping/default.rb, line 125
User.build_default_scope
activerecord (4.1.4) lib/active_record/scoping/default.rb, line 101
User.default_scoped
activerecord (4.1.4) lib/active_record/scoping/named.rb, line 33
User.all
activerecord (4.1.4) lib/active_record/scoping/named.rb, line 28
User.where
activerecord (4.1.4) lib/active_record/querying.rb, line 10
OrmAdapter::ActiveRecord#get
orm_adapter (0.5.0) lib/orm_adapter/adapters/active_record.rb, line 17
User.serialize_from_session
devise (3.2.4) lib/devise/models/authenticatable.rb, line 208
block (2 levels) in Warden::SessionSerializer#user_deserialize
devise (3.2.4) lib/devise.rb, line 462
Warden::SessionSerializer#fetch
warden (1.2.3) lib/warden/session_serializer.rb, line 34
Warden::Proxy#user
warden (1.2.3) lib/warden/proxy.rb, line 212
Warden::Proxy#_perform_authentication
warden (1.2.3) lib/warden/proxy.rb, line 318
Warden::Proxy#authenticate!
warden (1.2.3) lib/warden/proxy.rb, line 127
RegistrationsController#authenticate_user!
devise (3.2.4) lib/devise/controllers/helpers.rb, line 50
RegistrationsController#authenticate_scope!
devise (3.2.4) app/controllers/devise/registrations_controller.rb, line 124
block in ActiveSupport::Callbacks::Callback#make_lambda
activesupport (4.1.4) lib/active_support/callbacks.rb, line 424
block in ActiveSupport::Callbacks::Filters::Before.halting_and_conditional
activesupport (4.1.4) lib/active_support/callbacks.rb, line 143
RegistrationsController#run_callbacks
activesupport (4.1.4) lib/active_support/callbacks.rb, line 86
RegistrationsController#process_action
actionpack (4.1.4) lib/abstract_controller/callbacks.rb, line 19
RegistrationsController#process_action
actionpack (4.1.4) lib/action_controller/metal/rescue.rb, line 29
block in RegistrationsController#process_action
actionpack (4.1.4) lib/action_controller/metal/instrumentation.rb, line 31
like image 550
Lee Avatar asked Jan 29 '26 18:01

Lee


1 Answers

This is an old post, but the only one that asks about this exact issue, and there's no real solution. I was getting an error when attempting to use devise and acts_as_tenant without subdomains. I wanted to look up the tenant based on the user. This is the error I was getting: ActsAsTenant::Errors::NoTenantSet.

There are solutions here, but these didn't work for me.

The solution I found was to override some methods that Devise uses to extend the User model, so that these methods use unscoped as shown here. Using devise 4.6.2, acts_as_tenant 0.4.3, Rails 5.2.3

app/models/devise_overrides.rb

module DeviseOverrides
  def find_for_authentication(conditions)
    unscoped { super(conditions) }
  end

  def serialize_from_session(key, salt)
    unscoped { super(key, salt) }
  end

  def send_reset_password_instructions(attributes={})
    unscoped { super(attributes) }
  end

  def reset_password_by_token(attributes={})
    unscoped { super(attributes) }
  end

  def find_recoverable_or_initialize_with_errors(required_attributes, attributes, error=:invalid)
    unscoped { super(required_attributes, attributes, error) }
  end

  def send_confirmation_instructions(attributes={})
    unscoped { super(attributes) }
  end

  def confirm_by_token(confirmation_token)
    unscoped { super(confirmation_token) }
  end
end

Then in app/models/user.rb:

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :invitable, :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :validatable

  belongs_to :account
  accepts_nested_attributes_for :account

  acts_as_tenant(:account)
  extend DeviseOverrides
end

Now you can add a config/intializers/acts_as_tenant.rb and everything will continue to work.

ActsAsTenant.configure do |config|
  config.require_tenant = true
end

My app/controllers/application_controller.rb looks like this:

class ApplicationController < ActionController::Base
  set_current_tenant_through_filter
  before_action :set_tenant
  before_action :authenticate_user!

  private

  def set_tenant
    current_account = current_user.account
    set_current_tenant(current_account)
  end
end
like image 190
Marcos Galigarcia Avatar answered Jan 31 '26 06:01

Marcos Galigarcia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!