Dovrei saltare l'autorizzazione, con Cancan, di un'azione che istanzia una risorsa?
-
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
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