Utilizzando dichiarative_authorization per limitare i risultati nel modello
-
28-10-2019 - |
Domanda
Sto usando la gemma dell'autorizzazione dichiarativa per le autorizzazioni in un progetto di Rails e sto cercando di limitare l'output dal modello in base alle autorizzazioni dell'utente.
Il mio file di autorizzazione abbreviato sembra così:
roles do
role :supervisor
has_permission_on :people, :to => :manage_all
end
role :basic_user
has_permission_on :people, :to => :manage_subordinates
end
end
privileges do
privilege :manage_subordinates do
includes :subordinate_records
end
privilege :manage_all do
includes :all_records
end
end
Nel mio modello di gente, ho un metodo statico che voglio assomigliare a questo
def self.supervised_by(user)
if user.permitted_to? :all_records
#return all of the records
elsif user.permitted_to? :subordinate_records
#return some of the records
else
#return none of the records
end
end
Sembra che ci sia supporto per questo utilizzando l'oggetto AutorizationInModel nella documentazione utilizzando con_permissions_to o consentito_to. Non sono stato in grado di capire come utilizzare quelle funzioni in base alla documentazione o come restituire un elenco dei privilegi dell'utente corrente sul modello corrente.
Qualche idea?
Soluzione
Ho trovato una soluzione alternativa usando il metodo IF-attribute integrato. Inizialmente mi sono allontanato da esso perché stavo usando modelli non spaziati e controller e viste spaziate. Questa struttura è una forma di artefatto la versione originale del progetto su cui sto lavorando. La maggior parte del mio lavoro ha ottenuto l'autorizzazione dichiarativa per affrontare questa struttura.
La principale informazione che non mi era chiara era come nominare le autorizzazioni in un ambiente parzialmente nomi. Il modello si aspettava il nome del modello (: persone), il controller si aspettava lo spazio dei nomi e il modello (: staff_people) e le opinioni non importava finché ne hai scelto uno. La soluzione che ho scelto era usare il nome del modello e impostare esplicitamente il contesto in ogni controller. Se il contesto non è impostato nel controller, l'utilizzo di Filter_Access_to non funziona perché sarebbe alla ricerca dell'autorizzazione di Staff_People piuttosto che l'autorizzazione corretta, le persone.
Nel file di configurazione di autorizzazione dichiarativa, sto dando autorizzazioni complete all'amministrazione e alle autorizzazioni parziali al supervisore. Person.Supervised restituisce una serie di se stesso e di tutte le altre persone supervisionate.
roles do
role :administrator
has_permission_on :people, :to => [:create, :read, :update, :delete]
end
role :supervisor
has_permission_on :people do
to => [:create, :read, :update, :delete]
if_attribute :id => is_in { Person.find_by_user_id(user.id).supervised }
end
end
end
Per accedere a queste informazioni in un controller spaziato, sto usando FILER_RESOURCE_ACCESS.
module Staff
class PeopleController < ApplicationController
filter_resource_access :context => :people
def index
@people = People.with_permissions_to(:read)
end
L'ho trovato usando
filter_access_to :all, :with_attribute => true
non ha funzionato per metodi che devono utilizzare con_permissions_to e un'autorizzazione IF_attribute. Non sono sicuro del perché questo fosse un problema
È ancora necessario utilizzare Filter_Access_To per le azioni del controller non standard che non includono un ID che recupera un singolo record come parte degli argomenti. Ad esempio, se un'azione chiamata part_timers restituisce un elenco di persone, questa soluzione sembra funzionare:
filter_resource_access :context => :people, :additional_member => { :part_timers => :read }
La soluzione corretta è mantenere il filtro_resource_access così com'è e aggiungere un filter_access_to per quell'azione
filter_resource_access :context => :people
fitler_access_to :part_timers, :required => :read, :context => people
Altri suggerimenti
Potrebbe esserci un modo migliore per farlo, ma questo dovrebbe funzionare per il tuo supervised_by
Metodo se tutto il resto è impostato bene.
def self.supervised_by(user)
if Person.new.permitted_to? :all_records, :user=>user
#return all of the records
elsif Person.new.permitted_to? :subordinate_records, :user=>user
#return some of the records
else
#return none of the records
end
end