Dois-je sauter l'autorisation, avec Cancan, d'une action qui instancie une ressource?

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

  •  26-09-2019
  •  | 
  •  

Question

J'écris une application Web pour choisir des listes aléatoires de cartes à partir de plus grands ensembles de cartes. J'ai un modèle de carte et un modèle de carton. Les deux modèles ont un ensemble complet de 7 actions (: index ,: nouveau ,: show, etc.). Le cartesetsController a une action supplémentaire pour créer des ensembles aléatoires: :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

J'ai ajouté le conçu pour l'authentification et le canne pour les autorisations. J'ai des utilisateurs avec un rôle «éditeur». Les éditeurs sont autorisés à créer de nouveaux cartes. Les utilisateurs invités (les utilisateurs qui ne se sont pas connectés) ne peuvent utiliser que :index et :show Actions. Ces autorisations fonctionnent comme conçue. Les éditeurs peuvent actuellement utiliser les deux :random et le :new actions sans aucun problème. Les utilisateurs invités, comme prévu, ne le peuvent pas.

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

Je souhaite permettre aux utilisateurs invités d'utiliser le :random action, mais pas le :new action. En d'autres termes, ils peuvent voir de nouveaux ensembles aléatoires, mais pas les sauver. Le bouton "Enregistrer" sur le :random La vue de l'action est masquée (telle que conçue) des utilisateurs invités. Le problème est la première chose la :random Action fait est de créer une nouvelle instance du modèle Cardset pour remplir la vue. Quand Cancan essaie de load_and_authorize_resource Un nouvel carton, il lance une exception Cancan :: AccessEnedied. Par conséquent, la vue ne se charge jamais et l'utilisateur invité est servi un message "Vous devez vous connecter ou vous inscrire avant de continuer".

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

Je me rends compte que je peux dire load_and_authorize_resource pour sauter le :random Action en passant :except => :random à l'appel, mais c'est juste "mauvais" pour certaines raisons.

Quel est le "droit" façon de faire ça? Dois-je créer le nouvel ensemble aléatoire sans instancier un nouveau carton? Dois-je aller de l'avant et ajouter l'exception?

Mise à jour

Je n'ai pas inclus ma classe de capacité ci-dessus. Je l'ai mis à jour pour inclure l'action «: aléatoire», mais cela ne fonctionne toujours pas tout à fait correct.

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
Était-ce utile?

La solution

J'ai trouvé mon problème. Cancan n'était pas du tout le problème! La ligne suivante dans mon contrôleur de cartes a lancé l'exception et rediriger mes utilisateurs (non connectés) vers la page du journal:

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

Je l'ai changé pour lire:

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

Et maintenant, le code fonctionne comme prévu: les utilisateurs invités peuvent afficher les nouveaux ensembles aléatoires créés, mais ne peuvent pas les «enregistrer» à moins qu'ils ne se connectent d'abord.

Ainsi, mon vrai problème était avec Devise (ou, en fait, ma configuration de divise) et non avec Cancan du tout.

Autres conseils

Eh bien, la bonne chose serait d'utiliser la classe Cancan Capacité pour définir les règles d'autorisation correctes.

en capacité.rb

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

etc

Le problème est que la première chose: l'action aléatoire est de créer une nouvelle instance du modèle Cardset pour remplir la vue. Lorsque Cancan essaie de charger_and_authorize_resource un nouvel carton, il lance une exception Cancan :: AccessEnedied.

Bien que Cancan autorise l'action du contrôleur, la construction d'une nouvelle instance dans l'action aléatoire (c'est-à-dire CardSet.new) n'est pas dans la portée de Cancan. Vous obtenez probablement l'erreur car vous n'avez aucune règle définie dans Ability.rb pour une action aléatoire. Mon exemple ci-dessus devrait résoudre votre problème

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top