Hey,

I'm wondering what's the best way for a Pyramid app that uses URL dispatch 
rather than traversal to handle requests that reference resources that don't 
exist.

For example imagine a JSON API request like this, to edit the role of a member 
in a group:

    HTTP PATCH /api/groups/{groupid}/members/{memberid}

(Where the JSON body of the request would be something like this: `{"role": 
"admin"}`.)

And imagine someone makes a request with a {groupid} and/or {memberid} that 
doesn't exist:

    HTTP PATCH /api/groups/UNKNOWN_GROUPID/members/UNKNOWN_MEMBERID

And imagine that this request routes to a view callable with a config like this:

    @view_config(
        route_name="whatever",
        request_method="PATCH",
        permission="edit",
    )
    def edit_membership(context, request):
        ...

Because of the `permission` when Pyramid handles the request it's going to call 
the permits() method of the app's security policy with the request, context and 
"edit" for the permission. This is where I get confused: permits() must return 
either Allowed or Denied, and neither seems correct:

1. It doesn't seem quite right to me for permits() to return Denied in this 
situation. It's not that the request doesn't have permission to edit the 
membership, the problem is that the membership doesn't exist. Returning Denied 
would cause Pyramid to send a 401 response, when a 404 would be more 
appropriate.

2. permits() could return Allowed and then the view could raise HTTPNotFound. 
This would return the correct response but it seems wrong to me for permits() 
to say that the request is permitted to edit a membership that doesn't exist 
and I imagine there could even be race conditions resulting in security issues 
(if a membership with the matching IDs gets created by a concurrent request and 
it happens to be a membership that the API request should *not* have been 
permitted to edit).

(1) might be acceptable if you're happy for requests to unknown resources to 
401 rather than 404ing. Is that the answer?

Otherwise I don't see an acceptable option. Am I missing something?

If using either traversal or hybrid traversal + URL dispatch 
(https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/hybrid.html) 
there is a solution: if the groupid and/or memberid doesn't exist then the 
app's resource lookup code can raise KeyError which will cause Pyramid to 404 
without ever calling the security policy. The security policy code can be 
simpler because it can assume that if it is called then the groupid and 
memberid must have already been found by resource lookup. And the view code can 
be simpler because it can assume that if it is called then the groupid and 
memberid have been found and the permissions check has passed. Perfect!

But how should a URL dispatch-based app that doesn't use traversal handle this 
situation? Or do you just have to use traversal?

Thanks!

-- 
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 view this discussion visit 
https://groups.google.com/d/msgid/pylons-discuss/d9337096-7d9d-461b-8972-391b0a62fe69%40app.fastmail.com.

Reply via email to