هل يجب أن أتخطى التفويض ، مع كانكان ، عن إجراء يقوم بتثبيت مورد؟
-
26-09-2019 - |
سؤال
أنا أكتب تطبيق ويب لاختيار قوائم بطاقات عشوائية من مجموعات أكبر من البطاقات. لدي طراز بطاقة وطراز بطاقة. يحتوي كلا النموذجين على مجموعة كاملة من 7 إجراءات (: الفهرس ،: جديد ،: إظهار ، إلخ). لدى CardseStsController إجراء إضافي لإنشاء مجموعات عشوائية: :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
لقد أضفت ابتكار للمصادقة و 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
عرض Action مخفي (كما هو مصمم) من مستخدمي الضيوف. المشكلة هي ، أول شيء :random
الإجراء هو إنشاء مثيل جديد لنموذج CardSet لملء العرض. عندما يحاول كانكان ذلك load_and_authorize_resource
بطاقة بطاقة جديدة ، ترمي استثناء كانان :: Accessdenied. لذلك ، لا يتم تحميل العرض أبدًا ويتم تقديم رسالة "تحتاج إلى تسجيل الدخول أو التسجيل قبل المتابعة".
# 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
المحلول
لقد وجدت مشكلتي. لم يكن كانسان القضية على الإطلاق! كان السطر التالي في وحدة تحكم CardSet الخاصة بي هو رمي الاستثناء وإعادة توجيه ضيفتي (لم يتم تسجيل الدخول) إلى صفحة تسجيل الدخول:
before_filter :authenticate_user!, :except => [:show, :index]
لقد غيرتها لقراءة:
before_filter :authenticate_user!, :except => [:show, :index, :random]
والآن يعمل الرمز على النحو المقصود: يمكن لمستخدمي الضيوف عرض المجموعات العشوائية الجديدة التي تم إنشاؤها ، لكن لا يمكنهم "حفظها" إلا إذا قاموا بتسجيل الدخول لأول مرة.
لذلك ، كانت مشكلتي الحقيقية مع ابتكار (أو ، في الواقع ، تكوين ابتكار) وليس مع كانكان على الإطلاق.
نصائح أخرى
حسنًا ، سيكون الشيء الصحيح هو استخدام فئة القدرة Cancan لتحديد قواعد التفويض الصحيحة.
في القدرة
def initialize(user)
#everyone
can [:read, :random], [CardSet]
#everyone who is editor
if user.editor?
can [:new, :create], [CardSet]
إلخ
المشكلة هي أن أول شيء: الإجراء العشوائي هو إنشاء مثيل جديد لنموذج CardSet لملء العرض. عندما يحاول Cancan تحميل _Anuthorize_resource بطاقة بطاقة جديدة ، فإنه يلقي استثناءً من cancan :: accessdenied.
بينما يسمح Cancan بإجراء وحدة التحكم ، فإن إنشاء مثيل جديد في إجراء عشوائي (IE CardSet.new) ليس في نطاق Cancan. ربما تحصل على الخطأ لأنه ليس لديك قواعد محددة في القدرة. rb للعمل العشوائي. مثالي أعلاه يجب أن يحل مشكلتك