Cómo verificar if_attribute: id => is_in {matriz de IDS del método recursivo}
-
28-10-2019 - |
Pregunta
Tengo una base de datos de recursos donde los recursos pueden pertenecer a diferentes ubicaciones. Los usuarios y grupos (tabla de usuario autorreferencial) pueden tener diferentes roles en diferentes ubicaciones. Los grupos pueden estar dentro de otros grupos. La autorización funciona bien para usuarios únicos que usan 'IF_ATtribute' para verificar si el Ubicación_ID se encuentra entre los Ubicación_IDS que el usuario puede mostrar, editar, etc.:
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
Dado que los grupos pueden estar "anidados" entre sí, he pensado que tendré que usar un método recursivo para encontrar todas las identificaciones de ubicación "legales". Intenté esto:
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 el método definido fuera de la 'autorización do'-rutine:
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
El problema es que la llamada del método no encuentra el método. Entiendo este error:
NomethodError (método indefinado `find_group_location_ids 'para (autorización :: motor :: attributeValidator: 0x7fb63448e2b0)
He tratado de colocar la definición del método en muchos lugares diferentes, pero sin suerte.
¿Cómo puedo usar IF_ATtribute para ver si una ID está dentro de una matriz desde un método recursivo?
Solución
Obtuve ayuda de Steffenb en el grupo de autorización de Declarative en Google (él es el autor de Declarative_Authorization). La solución era mover el método al modelo de usuario:
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
y llamarlo de esta manera desde 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