2011-10-23 6 views
5

Aquí está el código:Mongoid: ¿Cómo evitar que se creen campos indefinidos mediante la asignación masiva?

class M 
    include Mongoid::Document 
    field :name 
end 

params = { name: "foo", age: 20 } 
M.create(params) 
#=> #<M name: "My Name", age: 20> 

en cuenta que age no se ha definido, sin embargo, se salvó.

Esto es problemático (potencialmente una fuente de denegación de servicio), ya que un usuario malintencionado puede añadir cualquier parámetro en su puesto y campos desconocidos con una cadena grande puede colarse. (Por ejemplo name=foo&bogus=#{'x'*1000000})

Hasta ahora, no podría encuentre cualquier cosa excepto attr_accessible, pero no es muy bueno para Mongoid ya que debe mantener los mismos nombres de campo en ambos field y attr_accessible todo el tiempo, en todos los modelos. No esta seco.

Creo que la API attr_accessible es ideal para ActiveRecord, porque hay a. no define explícitamente los campos en los modelos (DRY) y b. se garantiza que no hay posibilidad de que un campo inexistente se guarde en RDB. Pero para Mongoid, creo que debería haber una solución mejor que attr_accessible.

Tenga en cuenta que hay una configuración global allow_dynamic_fields pero no se trata de asignación masiva, por lo que está fuera del alcance de esta discusión, sin embargo, creo que debería ser una macro por modelo y también debería ocuparse de la asignación masiva.

¿Cómo está lidiando con este problema?

+1

¿Has encontrado una solución para esto? También estoy enfrentando el mismo problema. – Rohit

Respuesta

1

Siempre estoy usando attr_accessible en los modelos. Raramente me encontré incluyendo todos los campos como accesibles. Por lo general, siempre hay algunos campos que no deberían ser accesibles para la asignación masiva. Si a menudo necesita incluir todos los atributos y usted está preocupado acerca de la duplicación:

attr_accessible *fields.keys 
0

Lo que he hecho para resolver este problema, es utilizar una devolución de llamada antes de guardar en mi modelo:

set_callback(:save, :before) do |doc| 
    (doc.attributes.keys - fields.keys).each { |f| doc.unset(f) } 
end 

Este manera, incluso si hay atributos adicionales, se eliminan antes de ser guardados.

Cuestiones relacionadas