Traversal et URL dispatch avec pyramid ======================================= On utilise au sein d'enDi à la fois le mécanisme de *traversal* et celui d'URL dispatch. Le traversal nous permet, sur les vues concernées (option ``traverse`` de ``add_view()``) d'attacher automatiquement à l'objet de requête HTTP, un objet métier (instance de modèle SQLAlchemy), à travers l'attribut ``request.context``. On déclare donc des *traversal* puis on les attache à une ou plusieurs routes, ce qui rend le contexte accessible aux vues branchées sur ces routes. .. note:: Ce document décrit l'usage qui est fait du traversal dans enDi, l'approche peut différer selon les projets. Déclaration d'un traversal ^^^^^^^^^^^^^^^^^^^^^^^^^^ Se fait dans ``endi.utils.security.RootFactory.leaves`` avec un 3-uplet : - nom du traversal - nom du type d'objet (ça peuplera obj.__name__ automatiquement avec ce nom) - factory (la classe SQLAlchemy, qui doit avoir une propriété nommée ``id`` correspondant à l'id en BDD) .. code-block:: python ('companies', 'company', Company, ), Utilisation d'un traversal pour une route donnée ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On utilise `add_route`_ pour configurer le traversal à utiliser, pour reprendre l'exemple précédent : .. code-block:: python config.add_route( '/company/{id}/suppliers_orders', '/company/{id}/suppliers_orders', traverse='/companies/{id}', ) .. _add_route: https://docs.pylonsproject.org/projects/pyramid/en/latest/api/config.html#pyramid.config.Configurator.add_route Utilisation du contexte du traversal depuis la vue ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Pour une vue mappée (via `config.add_view`_) sur une route qui « traverse » un traversal : - l'attribut ``request.context`` contiendra l'objet automatiquement l'objet « traversé » . - une 404 sera déclenchée si l'objet n'existe pas - l'éventuelle `permission` passée à `add_view` sera vérifiée pour l'utilisateur courant, sur l'objet traversé, pouvant déboucher sur une 403 si accès non autorisé. .. warning:: Utiliser un traversal n'est pas suffisant pour protéger l'accès, il faut aussi requérir la bonne permission dans le `add_view`. C'est là que se niche la magie : pyramid décompose l'URL tout seul pour établir la correspondance entre `/companies/{id}` et le traversal nommé ``companies``. Il est impératif d'avoir dans le pattern d'URL de la route un champ ``{id}`` qui sera utilisé pour récupérer automatiquement la ``Company`` avec l'id correspondant. .. _config.add_view: https://docs.pylonsproject.org/projects/pyramid/en/latest/api/config.html#pyramid.config.Configurator.add_view Références ^^^^^^^^^^ * https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/hybrid.html#using-the-traverse-argument-in-a-route-definition * https://pyramid.readthedocs.io/en/latest/narr/hellotraversal.html * https://framagit.org/endi/endi/-/blob/master/endi/utils/security.py * https://pyramid.readthedocs.io/en/latest/narr/traversal.html * https://pyramid.readthedocs.io/en/latest/narr/muchadoabouttraversal.html