12

認証にDeviseを使用するRails 3.2アプリに取り組んでいます。ユーザー ロールを管理するために単一テーブルの継承を試すことにしましたが、すぐに問題が発生しました。現在、 と の 3 つの User モデルがUser < ActiveRecordありAdmin < Userます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のdeviseのヘルパーメソッドにありました。current_user、現在 current_admin と current_collaborator があり、フィルターとメソッドの前に作成することで「解決」しました。

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

4

これがまだ解決策として必要かどうかはわかりません...

二重認証を行うより洗練された方法は、次のようにすることです。

private

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

次に before_filter :authenticate! を呼び出します。

ユニバーサル '@current_user' 変数が必要ない場合は、2 行目を省略してください。

お役に立てれば。

于 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 に答える