Autorización de pirámide para artículos almacenados.

Estoy intentando crear una política de autorización que tenga en cuenta la propiedad del “elemento”. Por ejemplo, algunos usuarios X “poseen” los elementos A, B, C. Se accede a ellos a través de URL como /item/{item}/some_options .

¿Cómo puedo obtener la información sobre {item} al objeto de la política de autorización (permisos () llamada)? Es una buena idea poner la información adicional en contexto (estoy haciendo enrutamiento basado en rutas solamente). ¿Como podría hacerlo?

Puede hacer esto utilizando la ACLAuthorizationPolicy combinada con el Envío de URL utilizando un árbol de recursos personalizado diseñado para este propósito.

Por ejemplo, tiene permisos para objetos Foo y permisos para objetos Bar . Estas ACL se pueden encontrar al atravesar el árbol de recursos usando las direcciones URL:

 /foos/{obj} /bars/{obj} 

Su árbol de recursos se convierte en una jerarquía de permisos, donde en cualquier punto del árbol puede colocar un __acl__ en el objeto de recurso:

 root (Root) |- foos (FooContainer) | `- {obj} (Foo) `- bars (BarContainer) `- {obj} (Bar) 

Puedes representar esta jerarquía en un árbol de recursos:

 class Root(dict): # this is the root factory, you can set an __acl__ here for all resources __acl__ = [ (Allow, 'admin', ALL_PERMISSIONS), ] def __init__(self, request): self.request = request self['foos'] = FooContainer(self, 'foos') self['bars'] = BarContainer(self, 'bars') class FooContainer(object): # set ACL here for *all* objects of type Foo __acl__ = [ ] def __init__(self, parent, name): self.__parent__ = parent self.__name__ = name def __getitem__(self, key): # get a database connection s = DBSession() obj = s.query(Foo).filter_by(id=key).scalar() if obj is None: raise KeyError obj.__parent__ = self obj.__name__ = key return obj class Foo(object): # this __acl__ is computed dynamically based on the specific object @property def __acl__(self): acls = [(Allow, 'u:%d' % o.id, 'view') for o in self.owners] return acls owners = relation('FooOwner') class Bar(object): # allow any authenticated user to view Bar objects __acl__ = [ (Allow, Authenticated, 'view') ] 

Con una configuración como esta, puede asignar patrones de ruta a su árbol de recursos:

 config = Configurator() config.add_route('item_options', '/item/{item}/some_options', # tell pyramid where in the resource tree to go for this url traverse='/foos/{item}') 

También deberá asignar su ruta a una vista específica:

 config.add_view(route_name='item_options', view='.views.options_view', permission='view', renderer='item_options.mako') 

Genial, ahora podemos definir nuestra vista y usar el objeto de contexto cargado, ¡sabiendo que si la vista se ejecuta, el usuario tiene los permisos apropiados!

 def options_view(request): foo = request.context return { 'foo': foo, } 

Con esta configuración, está utilizando la ACLAuthorizationPolicy predeterminada y está proporcionando permisos de nivel de fila para sus objetos con el envío de URL. Tenga en cuenta también que, debido a que los objetos establecen la propiedad __parent__ en los hijos, la política boostá el linaje y heredará los permisos de los padres. Esto se puede evitar simplemente poniendo un DENY_ALL ACE en su ACL, o escribiendo una política personalizada que no use el linaje del contexto.

* Actualización * He convertido esta publicación en una demostración real en Github. Esperemos que ayude a alguien. https://github.com/mmerickel/pyramid_auth_demo

* Actualización * He escrito un tutorial completo sobre el sistema de autenticación y autorización de pirámide aquí: http://michael.merickel.org/projects/pyramid_auth_demo/