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.