リソースをインスタンス化するアクションの認可をカンカンでスキップする必要がありますか?

StackOverflow https://stackoverflow.com/questions/2831720

  •  26-09-2019
  •  | 
  •  

質問

私は、より大きな完全なカードのセットからカードのランダムリストを選択するためのWebアプリを作成しています。カードモデルとカードセットモデルがあります。両方のモデルには、7つのアクションの完全な安らかなセットがあります(:index、:new、:showなど)。 CardSetsControllerには、ランダムセットを作成するための追加のアクションがあります。 :random.

# app/models/card_set.rb
class CardSet < ActiveRecord::Base
  belongs_to :creator, :class_name => "User"
  has_many :memberships
  has_many :cards, :through => :memberships

# app/models/card.rb
class Card < ActiveRecord::Base
  belongs_to :creator, :class_name => "User"
  has_many :memberships
  has_many :card_sets, :through => :memberships

認証用のDeviseを追加し、CANCANは承認用に追加しました。 「編集者」の役割を持つユーザーがいます。編集者は新しいカードセットを作成できます。ゲストユーザー(ログインしていないユーザー)は、 :index:show 行動。これらの承認は、設計どおりに機能しています。編集者は現在、両方を使用できます :random そしてその :new 問題のないアクション。予想通り、ゲストユーザーはできません。

# app/controllers/card_sets_controller.rb
class CardSetsController < ApplicationController
  before_filter :authenticate_user!, :except => [:show, :index]
  load_and_authorize_resource

ゲストユーザーが使用できるようにしたい :random アクションはそうではありません :new アクション。言い換えれば、彼らは新しいランダムセットを見ることができますが、それらを保存することはできません。の「保存」ボタン :random アクションのビューは、ゲストユーザーから(設計されたように)隠されています。問題は、最初のことです :random アクションは、ビューを記入するためにカードセットモデルの新しいインスタンスを構築することです。カンカンが試みるとき load_and_authorize_resource 新しいカードセットでは、Cancan :: Accessdenied Exceptionをスローします。したがって、ビューは決してロードされず、ゲストユーザーには「継続する前にサインインまたはサインアップする必要がある」メッセージが提供されます。

# app/controllers/card_sets_controllers.rb
def random
  @card_set = CardSet.new( :name => "New Set of 10", :set_type => "Set of 10" )

わかります load_and_authorize_resource スキップします :random 合格することによるアクション :except => :random 電話に、しかしそれはただ感じます "違う" 何らかの理由で。

何ですか "右" これを行う方法は?新しいカードセットをインスタンス化することなく、新しいランダムセットを作成する必要がありますか?先に進んで例外を追加する必要がありますか?

アップデート

上記の能力クラスは含まれていませんでした。 「:ランダム」アクションを含めるように更新しましたが、それでもまったく正しく機能していません。

class Ability
  include CanCan::Ability

  def initialize( user )
    user ||= User.new # User hasn't logged in

    if user.admin?
      can :manage, :all if user.admin?
    else
      # All users, including guests:
      can :read, [Card, CardSet]
      can :random, CardSet

      # All users, except guests:
      can :create, [Card, CardSet] unless user.role.nil?
      can :update, [Card, CardSet] do |c|         
        c.try( :creator ) == user || user.editor?
      end

      if user.editor?
        can [:create, :update], [Card, CardSet]
      end
    end
  end
end
役に立ちましたか?

解決

私は自分の問題を見つけました。カンカンはまったく問題ではありませんでした!カードセットコントローラーの次の行は、例外をスローし、ゲスト(ログインしていない)ユーザーをログインページにリダイレクトしていました。

before_filter :authenticate_user!, :except => [:show, :index]

読むように変更しました:

before_filter :authenticate_user!, :except => [:show, :index, :random]

そして、コードは意図したとおりに機能します。ゲストユーザーは、作成された新しいランダムセットを表示できますが、最初にログインしない限り「保存」することはできません。

したがって、私の本当の問題は、Devise(または実際には、Devise構成)であり、Cancanではなくでした。

他のヒント

まあ、正しいことは、CANCAN能力クラスを使用して正しい承認ルールを定義することです。

infily.rb

  def initialize(user)
#everyone
    can [:read, :random], [CardSet]
#everyone who is editor
    if user.editor?
      can [:new, :create], [CardSet]

問題は、最初にランダムアクションが行うことは、ビューを記入するためにカードセットモデルの新しいインスタンスを構築することです。 Cancanが新しいカードセットをload_and_anuthorize_resourceにしようとすると、cancan :: accessdenied例外がスローされます。

Cancanはコントローラーのアクションを承認しますが、ランダムアクション(IE Cardset.new)で新しいインスタンスを構築することはCancanの範囲内ではありません。ランダムアクションのためにability.RBで定義されているルールがないため、おそらくエラーが発生します。上記の私の例はあなたの問題を解決する必要があります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top