Pregunta Recurso de la pirámide: en inglés sencillo


He estado leyendo sobre las formas de implementar la autorización (y la autenticación) en mi aplicación Pyramid recién creada. Sigo chocando con el concepto llamado "Recurso". Estoy usando python-couchdb en mi aplicación y no uso RDBMS en absoluto, por lo tanto no hay SQLAlchemy. Si creo un objeto de producto así:

class Product(mapping.Document):
  item = mapping.TextField()
  name = mapping.TextField()
  sizes = mapping.ListField()

¿Puede alguien decirme si esto también se llama recurso? He estado leyendo toda la documentación de las pirámides, pero en ningún lugar explica el término recurso en inglés sencillo (tal vez soy estúpido). Si este es el recurso, ¿significa esto que simplemente pongo mi ACL aquí así?

class Product(mapping.Document):
  __acl__ = [(Allow, AUTHENTICATED, 'view')]
  item = mapping.TextField()
  name = mapping.TextField()
  sizes = mapping.ListField()

  def __getitem__(self, key):
      return <something>

Si tuviera que usar Traversal, ¿esto significa que agregue el obtiene el objeto función en mi python-couchdb clase de producto / recurso?

Lo siento, es realmente confuso con todos los términos nuevos (vine de Pylons 0.9.7).

Gracias por adelantado.


9
2018-03-02 20:09


origen


Respuestas:


Creo que la pieza que te falta es la parte transversal. Es producto el recurso? Bueno, depende de lo que produce tu recorrido, podría producir productos .....

Tal vez sea mejor caminar desde la vista hacia atrás cómo se configura cuando se crea la aplicación ...

Aquí hay una vista típica.

  @view_config(context=Product, permission="view")
  def view_product(context, request):
      pass # would do stuff  

Entonces se llama a esta vista cuando el contexto es una instancia de Producto. Y Si el acl atributo de esa instancia tiene la "vista" permiso. Entonces, ¿cómo se convertiría una instancia de Producto en contexto?

Aquí es donde entra la magia del cruce. La misma lógica de transversal es simplemente un diccionario de diccionarios. Entonces, una forma de que esto podría funcionar para usted es si tuviera una url como

/product/1

De alguna manera, algunos recursos deben ser atravesados ​​por los segmentos de la url para determinar un contexto para que se pueda determinar una vista. Y si Tuvimos algo así como ...

  class ProductContainer(object):
      """
      container = ProductContainer()
      container[1]
      >>> <Product(1)>
      """
      def __init__(self, request, name="product", parent=None):
          self.__name__ = name
          self.__parent__ = parent
          self._request = request

      def __getitem__(self, key):
          p = db.get_product(id=key)

          if not p:
              raise KeyError(key)
          else:
              p.__acl__ = [(Allow, Everyone,"view")]
              p.__name__ = key
              p.__parent__ = self
              return p

Ahora esto está cubierto en la documentación y estoy tratando de hervirlo hasta lo básico que necesitas saber. El ProductContainer es un objeto que se comporta como un diccionario. Los "nombre"y"padre" atributos son requeridos por la pirámide para la generación de URL métodos para trabajar bien.

Entonces ahora tenemos un recurso que puede atravesarse. Como decimos pirámide para atravesar ProductContainer? Hacemos eso a través del Objeto configurador.

  config = Configurator()
  config.add_route(name="product",
                   path="/product/*traverse",
                   factory=ProductContainer)
  config.scan()
  application = config.make_wsgi_app()

El parámetro de fábrica espera un invocable y lo entrega el actual solicitud. Da la casualidad de que ProductContainer.en eso va a hacer eso está bien.

Esto podría parecer demasiado para un ejemplo tan simple, pero con suerte puedes imaginar las posibilidades. Este patrón permite muy modelos de permisos granulares.

Si no quiere / necesita un modelo de permisos muy granular como una fila nivel de acl es probable que no necesite cruce, en su lugar puede usar rutas con una sola fábrica de raíz.

  class RootFactory(object):
      def __init__(self, request):
          self._request = request
          self.__acl__ = [(Allow, Everyone, "view")]  # todo: add more acls


  @view_config(permission="view", route_name="orders")
  def view_product(context, request):
      order_id, product_id = request.matchdict["order_id"], request.matchdict["product_id"]
      pass # do what you need to with the input, the security check already happened

  config = Configurator(root_factory=RootFactory)

  config.add_route(name="orders",
                   path="/order/{order_id}/products/{product_id}")

  config.scan()
  application = config.make_wsgi_app()

nota: Hice el ejemplo del código de memoria, obviamente necesita todas las importaciones necesarias, etc. en otras palabras, esto no va a funcionar como copiar / pegar


6
2018-03-02 22:26



Has trabajado http://michael.merickel.org/projects/pyramid_auth_demo/ ? Si no, sospecho que puede ser útil. La última sección http://michael.merickel.org/projects/pyramid_auth_demo/object_security.html implementa el patrón que está buscando (tenga en cuenta que las clases ejemplo "modelo" heredan de nada más complejo que object)


0
2018-03-03 22:22