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.