多租户rails应用程序与设计

时间:2014-03-10 06:37:55

标签: ruby-on-rails devise multi-tenant

我正在尝试构建一个多租户应用,其中不同的银行由子域分隔。这部分工作正常。现在银行产品还有一个多租户级别。

  • 每家银行都有多个产品
  • 设计用户只能属于产品
  • 这意味着您必须为同一个银行的两个产品注册两次,即使它们位于相同的子域下(客户要求无法更改)
  • 因此,您可以为两种产品使用相同的电子邮件地址。唯一性范围为product_id
  • 所以我必须在登录和注册时选择产品

这就是我试图实现上述解决方案的方法

around_filter :scope_current_bank, :scope_current_product
before_filter :authenticate_user!

helper_method :current_bank, :current_product

def current_bank
  @current_bank = Bank.find_by_subdomain!(request.subdomains.first)
end

def current_product
  if user_signed_in?
    @current_product = current_bank.products.find_by_id(params[:product_id])
  else
    @current_product = current_user.product
  end
end

def scope_current_bank
  Bank.current_id = current_bank.id
  yield
ensure
  Bank.current_id = nil
end

def scope_current_product
  Product.current_id = (current_product.id rescue nil)
  yield
ensure
  Product.current_id = nil
end

现在的问题是当用户输入时, scope_current_product 方法调用user_signed_in ?,显然它失败了,因为product_id是nil。现在它进入了else块,之后我希望它将 authenticate_user!称为before_filter,但它不会发生,因为身份验证已经完成。所以我得到一条消息说认证失败了。

他们是否可以再次调用authenticate_user?

1 个答案:

答案 0 :(得分:1)

虽然不是直接的答案,但希望这会给你一些想法:


<强>授权

也许你应该看一下 - Is there a difference between authentication and authorization? - 关于这个问题有一个good RailsCast

我认为您的问题归结为您需要对用户进行身份验证一次(登录/注销),但应该授权该用户使用不同的资源


<强>代码

A devise user can belong to only on product - 我建议这样做:

#app/models/product_user.rb
Class ProductUser < ActiveRecord::Base
    belongs_to :product
    belongs_to :user
end

#app/models/product.rb
Class Product < ActiveRecord::Base
    has_many :product_users
    has_many :users, through: :product_users
end

#app/models/user.rb
Class User < ActiveRecord::Base
    has_many :product_users
    has_many :products, through: :product_users
end

这是典型的has_many :through关联:

@user.products
@product.users

<强>惭惭

这意味着您可以使用CanCan执行以下操作:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user
      can :manage, Product, users.exists?(user.id)
    else
      can :read, :all
    end
  end
end

这使您可以控制用户可以编辑/访问的产品。显然我的代码需要调整,但我希望它向您展示授权的价值,而不是尝试进行多次身份验证