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?

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top