Come controllare if_attribute: id => is_in {array di IDS dal metodo ricorsivo}
-
28-10-2019 - |
Domanda
Ho un database delle risorse in cui le risorse possono appartenere a posizioni diverse. Gli utenti e i gruppi (tabella utente autoreferenziale) possono avere ruoli diversi in luoghi diversi. I gruppi possono essere all'interno di altri gruppi. L'autorizzazione funziona bene per gli utenti singoli utilizzando "if_attribute" per verificare se la posizione_id è tra i location_ids che l'utente è autorizzato a mostrare, modificare, ecc.:
has_permission_on :locations do
to [:show, :new, :create, :edit, :update, :destroy]
if_attribute :id => is_in { (user.permissions.where(:role => "admin").collect {|i| Location.find_by_id(i.location_id).subtree_ids}.flatten.uniq )}
end
Poiché i gruppi possono essere "nidificati" l'uno dell'altro, ho pensato che dovrò usare un metodo ricorsivo per trovare tutti gli ID di posizione "legale". Ho provato questo:
has_permission_on :locations do
to [:show, :new, :create, :edit, :update, :destroy]
if_attribute :id => is_in { (user.permissions.where(:role => "admin").collect {|i| Location.find_by_id(i.location_id).subtree_ids} + find_group_location_ids(user)).flatten.uniq }
end
con il metodo definito al di fuori della "autorizzazione Do'-Routine:
def find_group_location_ids(user)
location_ids = []
nested_group_location_ids(user)
def nested_group_location_ids(user)
user.group_memberships.each do |gm|
location_ids = location_ids + gm.user.location.id
nested_group_location_ids(gm.user)
end
end
return location_ids
end
Il problema è che la chiamata del metodo non trova il metodo. Ricevo questo errore:
NomeToDerror (Metodo non definito `Find_Group_Location_ids 'per (autorizzazione :: Engine :: Attributevalidator: 0x7FB63448E2B0)
Ho cercato di posizionare la definizione del metodo in molti posti diversi, ma senza fortuna.
Come posso usare if_attribute per vedere se un ID è all'interno di un array da un metodo ricorsivo?
Soluzione
Ho ricevuto aiuto da STEFFENB presso il gruppo dichiarativo_authorization presso Google Groups (è autore di dichiarativo_authorizzazione). La soluzione era spostare il metodo al modello utente:
def find_group_location_ids
location_ids = []
nested_group_location_ids(self)
def nested_group_location_ids(user)
user.group_memberships.each do |gm|
location_ids = location_ids + gm.user.location.id
nested_group_location_ids(gm.user)
end
end
return location_ids
end
e chiamarlo in questo modo da autorization_rules.rb:
has_permission_on :locations do
to [:show, :new, :create, :edit, :update, :destroy]
if_attribute :id => is_in { (user.memberships.where(:role_id => "admin").collect {|i| Location.find_by_id(i.location_id).subtree_ids} + user.find_group_location_ids).flatten.uniq }
end