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.

Reply via email to