Skip to content

Instantly share code, notes, and snippets.

@faddai
Forked from inklesspen/gist:4222841
Created December 6, 2012 09:28
Show Gist options
  • Save faddai/4223224 to your computer and use it in GitHub Desktop.
Save faddai/4223224 to your computer and use it in GitHub Desktop.
ACLs, context objects, and URL Dispatch in Pyramid
# A worked example based on http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/urldispatch.html#using-pyramid-security-with-url-dispatch
# in your configuration section (typically in myapp/__init__.py)
config.add_route('articles.edit', 'article/{id}/edit', factory='myapp.acl.ArticleACL')
# in myapp/acl.py
class ArticleACL(object):
def __init__(self, request):
# First, we assume this ACL object is used only in routes that provide an article id; if need be, you can add some sanity checking here, or some if/else branching
assert request.matched_route.name == 'articles.edit'
# Now, if all articles can be edited by the same group of people, you could do like this:
self.__acl__ = [(pyramid.security.Allow, 'group:editors', 'edit')]
# This means that any user with the principal 'group:editors' has the edit permission. You would have your authentication policy add the 'group:editors' principal on your editor users.
# But what if each article can only be edited by the person who created it?
# First, let's load in the article, and set it on self; that'll come in handy later
try:
self.article = myapp.model.Article.find_by_id(request.matchdict['id'])
except NoResultFound, e:
# This is a SQLAlchemy exception, but you can use whatever method of catching nonexistant articles you like
# Since the article doesn't exist, we'll trigger a 404 Not Found. You might like to return 403 Forbidden on missing articles as well, to avoid giving an idea of which article ids exist and which do not. Up to you.
raise pyramid.httpexceptions.HTTPNotFound()
# This assumes that the article has an editor_id property which matches a principal provided by your auth policy.
self.__acl__ = [(pyramid.security.Allow, self.article.editor_id, 'edit')]
# finally, your view:
@view_config(route_name='articles.edit', permission='edit')
def article_edit(request):
# the instance of ArticleACL that had self.article set on it is available on the request.
article = request.context.article
# Now, do whatever's necessary to render the editing form.
return render_editing_form(article)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment