6

I'm following security guidelines found on Pyramid docs along with wiki tutorial Adding Authorization

Now I need to add restrictions based un single user rather than groups.

Let's say for example that, if any blog editor can have permission to review all comments, only post author can edit the post itself.

For the first task I will have in my Root ACL like this:

__acl__ = [ (Allow, Everyone, 'view'),
            (Allow, Authenticated, 'view_profile'),
            (Allow, 'groups:editor', 'edit_comment')
]

but whay about for edit_post?

I've read this answer but seems overkill to me for my needs since I don't need to build a resource tree.

Community
  • 1
  • 1
neurino
  • 11,500
  • 2
  • 40
  • 63

2 Answers2

8

You already have a "Resource Tree" by creating the Root resource in your project. You just need to add a node on it for posts that will return a Post object with a particular __acl__ that contains only the authorized user id. You can then have your edit_posts route use traverse='/posts/{post_id}' to traverse your resource tree to the Post object with the __acl__ on it.

This isn't difficult, and is the way to have Pyramid do this stuff for you.

If you don't want to use the permission argument you can do the authorization inside of the view itself, like Kirk suggested.

Also, if you don't like this method of adding __acl__ properties and traversal for authorization, you can implement your own AuthorizationPolicy to do what you'd like it to do with a given list of principals and a permission.

The point of Pyramid's auth system is that it's there, which is great. Pyramid by no means requires you to use it and for views that don't use it, there is no performance impact of dealing with it.

Michael Merickel
  • 23,153
  • 3
  • 54
  • 70
  • 2
    Thank you, it's getting clearer to me, for my needs is much more appropriate (and easy) to me to add a check in the view itself rather than creating classes for resources and so on. It's what I was trying to avoid but, like Kirk said, there's nothing wrong with it (now I know it). – neurino Jul 06 '11 at 08:38
  • 1
    I really like your approach, Michael, and it's probably the "right" solution for most cases. In my own project, there are some exceedingly complex business rules that go into the decision process and those rules are different per view. That's probably what makes me ready and willing to jump off the global config train in favor of handling some stuff locally. – Kirk Strauser Jul 06 '11 at 13:06
  • Kirk, you're correct about rate limiting and special considerations. However those requirements are generally orthogonal to the necessity of simply checking ownership of an object or the high-level gateway allowing a user to actually do something in the first place. Also a lot of those extra checks are things a lot of people do in middleware (especially rate limiting), thus would be solved before even getting to your application. Also don't forget that each object can provide its __acl__ dynamically, so it could remove a user's ownership temporarily based on some criteria. – Michael Merickel Jul 06 '11 at 15:18
  • That feels like a lot of extra work to me. This probably isn't the place to hash that out, but do you have a link to an article explaining why I might want to reconsider? I'm extremely open to change, especially as I'm still quite early into the largish project I'm working on. – Kirk Strauser Jul 07 '11 at 01:04
4

You might be making this too complicated. First, only show a link to the edit_post view if the visitor is the post's author. That will handle 99% of the problem by making that view invisible to people who shouldn't see it. For the other 1% - clever users hand-editing the URL to directly access the editing view - add something like this:

def edit_post(request):
    ...
    if authenticated_userid(request) != author:
        raise pyramid.httpexceptions.HTTPForbidden("You are not this post's author.")
Kirk Strauser
  • 30,189
  • 5
  • 49
  • 65
  • I was thinking right to remaining 1% willing to mess up things... anyway since part of auth (ex. `edit_comment`) is made out views I was willing to keep things working all the same way. At least until this does not become too complicated as you stare... +1 for now. – neurino Jul 05 '11 at 18:55
  • 1
    Well, there's nothing wrong with the idea of building such restrictions into a global policy instead of implementing them inside views. Sometimes the views are the right place, though. I can easily imagine many more complex restrictions based on time of day, server load, expensive calculations, etc. where it would be painful to attempt to write a comprehensive top-level policy. – Kirk Strauser Jul 05 '11 at 19:13
  • Thanks, it makes sense to me now. – neurino Jul 06 '11 at 08:39