在Rails中设计w/Subdirectories

Kyl*_*cot 0 ruby ruby-on-rails devise

我正在构建一个rails应用程序,我需要通过以下方式支持多个租户:

example.com/:tenant_1
example.com/:tenant_2
Run Code Online (Sandbox Code Playgroud)

对于这些租户中的每一个,我想要单独登录:

example.com/:tenant_1/sign_in
example.com/:tenant_2/sign_in
Run Code Online (Sandbox Code Playgroud)

对于每个租户,我希望他们的登录会话的范围限定在适用的租户子目录中.这是设计支持的东西,如果是这样的话,如何实现这个?

Ric*_*eck 5

如果您拥有模型并sessions正确设置,Devise将支持身份验证.

-

你做的非常类似于你有一个subdomain:

#config/routes.rb
scope Tenant do
   root "application#dashboard"
   devise_for :users, controllers: {}
end

#lib/tenant.rb
module CompanyDispatch

    def initializer(router)
        @router = router
    end

    def self.matches?(request)
        Account.exists? request.path.split("/").first
    end

end
Run Code Online (Sandbox Code Playgroud)

以上将使您能够访问url.com/:tenant_1/sign_in(可能需要调整等).

您可能必须调整Devise方法 - 使用其Warden策略或find方法:

# app/models/user.rb
class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, request_keys: [:x]

  def self.find_for_authentication(warden_conditions)
    account = Account.find warden_conditions[:x]
    where(email: warden_conditions[:email], account_id: account.id ).first
  end
end
Run Code Online (Sandbox Code Playgroud)

上面的代码需要传递给Devise的正确请求参数; 然后,您需要确保session仅限于每个租户:

#config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: '_[app_name]_session' #-> need to add something here so paths will be used
Run Code Online (Sandbox Code Playgroud)

-

这是你如何做到这一点的整体.上面的代码需要调整,但我现在非常累,所以我会事后更新,除非你更喜欢我删除它.