Dovrei saltare l'autorizzazione, con Cancan, di un'azione che istanzia una risorsa?

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

  •  26-09-2019
  •  | 
  •  

Domanda

Sto scrivendo un'app Web per scegliere elenchi casuali di carte da set di carte più grandi e complete. Ho un modello di carta e un modello di cardset. Entrambi i modelli hanno un set completo di 7 azioni (: indice ,: nuovo ,: show, ecc.). CardsetController ha un'azione aggiuntiva per la creazione di set casuali: :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

Ho aggiunto un'idea per l'autenticazione e Cancan per le autorizzazioni. Ho utenti con un ruolo di "editor". Gli editori sono autorizzati a creare nuovi cardoni. Gli utenti ospiti (utenti che non hanno effettuato l'accesso) possono solo utilizzare il :index e :show Azioni. Queste autorizzazioni funzionano come previsto. Gli editori possono attualmente utilizzare sia il :random e il :new azioni senza problemi. Gli utenti ospiti, come previsto, non possono.

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

Voglio consentire agli utenti ospiti di utilizzare il :random azione, ma non il :new azione. In altre parole, possono vedere nuovi set casuali, ma non salvarli. Il pulsante "Salva" sul file :random L'opinione di Action è nascosta (come progettata) dagli utenti ospiti. Il problema è la prima cosa :random L'azione fa è costruire una nuova istanza del modello di cardset per compilare la vista. Quando Cancan ci prova a farlo load_and_authorize_resource Un nuovo set di carte, lancia un'eccezione Cancan :: Accessdenied. Pertanto, la vista non si carica mai e all'utente ospite viene servito un messaggio "è necessario accedere o iscriversi prima di continuare".

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

Mi rendo conto di poterlo dire load_and_authorize_resource per saltare il :random azione passando :except => :random alla chiamata, ma questo si sente solo "sbagliato" per qualche ragione.

Qual è il "Giusto" modo per farlo? Dovrei creare il nuovo set casuale senza istanziare un nuovo set di carte? Dovrei andare avanti e aggiungere l'eccezione?

Aggiornare

Non ho incluso la mia classe di abilità sopra. L'ho aggiornato per includere l'azione ": casuale", ma non funziona ancora bene.

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
È stato utile?

Soluzione

Ho trovato il mio problema. Cancan non era affatto il problema! La seguente riga nel mio controller di cardset stava lanciando l'eccezione e il reindirizzamento dei miei utenti ospiti (non accede) alla pagina di accesso:

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

L'ho cambiato per leggere:

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

E ora il codice funziona come previsto: gli utenti ospiti possono visualizzare i nuovi set casuali creati, ma non possono "salvarli" a meno che non accecino per la prima volta.

Quindi, il mio vero problema è stato con Devise (o, in realtà, la mia configurazione di idea) e non con Cancan.

Altri suggerimenti

Bene, la cosa giusta sarebbe quella di utilizzare Cancan Abilità Class per definire le regole di autorizzazione corrette.

In Ability.rb

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

eccetera

Il problema è che la prima cosa: Azione casuale fa è costruire una nuova istanza del modello di cardset per compilare la vista. Quando Cancan cerca di caricare_and_authorize_resource un nuovo set di carte, lancia un'eccezione Cancan :: Accessdenied.

Mentre Cancan autorizza l'azione del controller, la costruzione di una nuova istanza in Action Random (IE Cardset.New) non è nell'ambito di Cancan. Probabilmente ottieni l'errore perché non hai regole definite nell'abilità.rb per un'azione casuale. Il mio esempio sopra dovrebbe risolvere il tuo problema

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top