12

我正在开发一个使用 Devise 进行身份验证的 Rails 3.2 应用程序。我决定尝试单表继承来管理用户角色,但很快就遇到了问题。我目前有三个用户模型User < ActiveRecordAdmin < UserCollaborator < User。Admin 和 Collaborator 共享大多数 User 列,但它们的行为和权限略有不同。我的模型目前看起来像这样:

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :token_authenticatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :name, :password, :password_confirmation, :remember_me

  before_save :ensure_authentication_token

  [...]

end

class Admin < User
  has_one :account, dependent: :destroy 
  attr_accessible :account_attributes 
  accepts_nested_attributes_for :account
end


class Collaborator < User
  has_one :account
end

class Account < ActiveRecord::Base
  attr_accessible :name
  validates_presence_of :name 
  has_many :projects, dependent: :destroy
  has_many :users
end

当我尝试在我的 ProjectController(以及我需要身份验证的其他控制器)中对管理员和协作者进行身份验证时,问题就出现了:

# Causes problem, no one can access anything.
before_filter :authenticate_admin!
before_filter :authenticate_collaborator!

我遇到的一个类似问题是设计的 ie 辅助方法。current_user,现在我有了 current_admin 和 current_collaborator,我通过创建一个 before 过滤器和方法“解决了”这个问题:

def set_current_user
  @current_user = current_admin || current_collaborator
end

对于我的 Devise 身份验证问题是否有类似或简单的解决方案,或者您会推荐其他方法而不是单表继承,那会是什么?

我的目标是,1.当新用户注册时,他们成为管理员,当他们创建帐户时,也会创建一个帐户模型。2. 然后,新(管理员)用户可以邀请其他用户加入帐户,这些用户将是协作者。3. 管理员和协作者应该有不同的权限。协作者在注册时不会创建新的“帐户”(公司可能是我的帐户模型的更好名称),因此管理员和协作者将需要稍微不同的表单来注册和编辑。

谢谢。

更新

我通过创建一个类似的前置过滤器来“解决”它:

def authenticate!
  if @current_user == current_admin
    :authenticate_admin!
  elsif @current_user == current_collaborator
    :authenticate_collaborator!
  end
end

关于可能更优雅的解决方案的建议仍然会受到赞赏。

4

3 回答 3

6

您可以使用以下解决方案解决此问题

def 认证!
    如果模型A_user_signed_in?
      @current_user = current_modelA
      真的
    别的
      验证模型B!
    结尾

  结尾
于 2013-12-17T19:23:06.273 回答
4

不知道这是否仍然需要解决这个问题......

进行双重身份验证的更优雅的方法可能是执行以下操作:

private

def authenticate!
   :authenticate_admin! || :authenticate_collaborator!
   @current_user = admin_signed_in? ? current_admin : current_collaborator
end

然后调用 before_filter :authenticate!

如果您不需要通用的“@current_user”变量,只需省略第二行。

希望这可以帮助。

于 2013-06-03T20:36:27.497 回答
1

您可以将所有常见逻辑分离到模块并仅使用同一张表。

module UserMethods
  #...
end

class User < ActiveRecord::Base
  include UserMethods
  devise ...

end  

class Admin < ActiveRecord::Base
  include UserMethods
  self.table_name = "users"
  devise ...
end

并在路由、视图中分别配置所有设计模型(如有必要,请参阅配置视图)。在这种情况下,您可以轻松处理所有不同的逻辑。

于 2012-04-26T08:49:07.413 回答