OK, here is something I made, by looking at pviews util.

def route_allowed(request, route_name):
    from zope.interface import providedBy
    from pyramid.interfaces import IRouteRequest
    from pyramid.interfaces import IRequest
    from pyramid.view import _find_views


    reg = request.registry
    request_iface = reg.queryUtility(IRouteRequest, name=route_name, default
=IRequest)
    context_iface = providedBy(request.context)
    views = _find_views(reg, request_iface, context_iface, '')


    assert len(views) == 1


    view = views[0]
    permission = view.__permission__


    return bool(request.has_permission(permission))

Can you explain why this is wrong or how can I make it better? It is 
limited to the exactly one matching view case (assert len(views) == 1), but 
I believe it's a fair limitation and is not a problem for a typical URL 
Dispatch app, and definitely not a problem for my use case.

Zsolt




On Saturday, 12 November 2016 18:25:45 UTC+1, Zsolt Ero wrote:
>
> Here is what I see:
> - The way Pyramid does everything super flexibly (URL structure, the view 
> callables, the role concepts, and the permissions as you said it) can make 
> it very complicated to do otherwise simple things, such as making a 
> request.route_allowed()...
> - If request.route_url() exists and works, why can we not make 
> request.route_allowed()? I understand that one route *may* point to 
> multiple views, but that mechanism is implemented already, since Pyramid 
> can decide what to do on every incoming request.
> - The *only* thing what I can imagine is not obvious from a request and a 
> route_url is the GET/POST, etc. kind, since the user might want to change 
> that between requests. (For example calling a form, etc.). 
>
> So why can we not make a simple request.route_allowed(**kwargs, 
> method='GET') method, where kwargs would be the same as for route_url()?
>
> Zsolt
>
>
> On Saturday, 12 November 2016 00:40:17 UTC+1, Mike Orr wrote:
>>
>> On Thu, Nov 10, 2016 at 12:48 PM, Zsolt Ero <[email protected]> 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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/pylons-discuss/648eb04e-4036-4161-985a-c7317e8cd653%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to