On Thu, Nov 10, 2016 at 12:48 PM, Zsolt Ero <zsolt....@gmail.com> wrote: > Hi, I'd like to do the simplest possible thing in Pyramid / URL Dispatch, > yet it seems almost impossibly hard to do it. > > So it's the super common case of having a menu, and I'd only like to insert > menu items which are available for the current user. > > I'm looking for a function to fit in this usage: > > {% macro nav_item(request, route_name, text) -%} > {% if request.view_execution_permitted(route_name) %} > <li> > <a href="{{ request.route_url(route_name) }}">{{ text }}</a> > </li> > {% endif %} > {%- endmacro %} > > > My problems are the following: > > 1. view_execution_permitted doesn't work like this, unlike other security > functions, for example request.has_permission(). Why?
There seems to be a logic problem here. Routes aren't authorization-significant entities; a route is just a URL pattern. Users belong in roles/groups (Pyramid calls all of these "principals" -- defined by the "groupfinder" callback in the authentication policy). Principles have permissions -- defined in the ACLs others have talked about. A simple URL Dispatch application may have just one ACL for everything: a root factory defined at startup sets all the permissions that all the pages need. A more complex URL Dispatch application may have different roots for different parts of the application (different view configurations), and each of these can do their own private traversal to sub-objects. But it's easier to start with a single root for the entire application. Each request will have its own instance of that root, which is the "context" available to the view and the authorization system. Finally, the view configuration ties all of these together: the view, the route, the root factory with its ACL, and the permission required to execute the view. The reason all these are separate is to keep some independence between the URL structure, the view callables, the role concepts, and the permissions: so you can design each one autonomously to its best structure, and you can change one (within limits) without affecting the others. So the answer to your question is, what determines which menu items should be displayed? Not the routes, the *roles* (principles). The roles imply permissions, and r'equest.has_permission' tells whether the user has that permission (i.e., can execute the views that require that permission). However, there's no formal listing of which routes go with which permissions; that's all tied up in the complex view confugrations. But you should know which permission each page requires. So you should do a (in Mako syntax which I'm more familiar with) '% if request.has_permission("foo_permission"): <a href="${request.route_url('foo_route')}">text</a> % endif'. I have one application with permissions and I use 'pyramid_layout', so I define several boolean attributes in the layout object ('can_do_this', 'can_do_that'), and use those to decide which menu items to display in the site template. For links in individual pages, the view sets similar booleans. Actually, I don't always use booleans because I like to generate the URLs outside the templates, so I use None to indicate no URL (no link), or I give a list of permitted URLs that doesn't include the unpermitted ones. If you need to do something dynamically (e.g., user-defined URLs and permissions that the developer doesn't know about), then studying Kotti might be useful, because it allows site admins to define users and roles and pages and link them together. So I don't think you'll need to ask whether a route is permitted to a user; that concept belongs in the principles and ACLs. But there may be something I'm missing. As for 'view_execution_permitted', I've never used that and I'm not sure it's useful for application developers, especially in a URL Dispatch application. It may be something Pyramid uses more internally. The fact that it requires a view name is a red flag. Routes kind of replace view names in URL Dispatch. Traversal uses view names extensively to choose between multiple views for a resource. URL Dispatch uses mostly the route name to choose a view, and specifying a view name could accidentally make the view configuration not match the request. -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discuss+unsubscr...@googlegroups.com. To post to this group, send email to pylons-discuss@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/CAH9f%3DuquKsLMKpT%2BR4oSS6ERDfTkB-h3%3D8LnZxgj6CsbLaZ2Mg%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.