Route Factory seems to be the proper term, see http://pyramid.readthedocs.org/en/latest/narr/urldispatch.html#route-factories
On Fri, Aug 31, 2012 at 11:37 AM, Robert Forkel <[email protected]> wrote: > I guess I'm doing something similar. At least as far as having > resource specific permissions. But I've chosen to implement this using > context factories. So the > > resource_id = int(request.matchdict["resource_id"]) > resource = DBSession().query(Resource).get(resource_id) > if not resource: > raise NotFound() > > code which you have in the view is in my case part of the context > factory. Additionally, the context factory attaches a trivial __acl__ > attribute to the context (allowing or denying the current user) to > make the standard authorization policy work. > > > On Thu, Aug 30, 2012 at 4:47 PM, Vlad K. <[email protected]> wrote: >> >> Hello all, >> >> >> I have an app with relatively complex security/permissions requirements and >> I decided to build it modeled after SELinux. >> >> The default Pyramid authz policy revolves around checking if a user belongs >> to a group, or has certain principal, the check of which is facilitated per >> view (with `permission` argument). >> >> In my app I have several roles and each role can only access some resources, >> and only perform some actions upon those resources (read, write, delete, >> ...), and the permission is not static per view, but depends on data >> retrieved from database according to some identifier given through >> matchdict. >> >> For example, "regular" users can create new and edit only own content of >> class X, Y, Z. Users belonging to a "editor" role can view other people's X, >> Y, Z but can't modify them except some properties thereof (like >> active/inactive). Perhaps editors can't write their own content, so they >> would only have `read` permission. Users belonging to a "billing" role can >> only view billing data of users, create invoices, activate/deactivate >> profiles, but not view or change their content, etc.... >> >> >> >> I decided to make a class which I reify as request.permits property (via >> config.set_request_property()), then do a following check: >> >> >> @view_config(route_name="some_route", ...): >> def some_view(request): >> resource_id = int(request.matchdict["resource_id"]) >> >> resource = DBSession().query(Resource).get(resource_id) >> if resource and not request.permit(resource, read=True): >> raise Forbidden() >> >> if not resource: >> raise NotFound() >> >> ... >> >> >> The permit() method is a __call__ method of the policy class. It does >> several things: >> >> 1. Checks the type of first parameter (the "tcontext" in SELinux lingo) >> 2. According to its type (isinstance), delegates check to a private method >> responsible for that resource class (content classes, menu links, ...) >> 3. The private method does whatever check required to see if the user >> (authenticated in the system with some principal like ID, the "scontext" in >> SELinux lingo) has access to the resource for given action (read, write, >> delete) >> >> Example checks (which would be policy rules in SELinux): >> >> # request.userauth is also an object created with >> config.set_request_property() >> if resource.owner_id == request.userauth.user_id and (read or write): >> return True >> if "required_role" in request.userauth.roles and (read and not write): >> return True >> >> >> etc... The default, of course, being no permission at all. It can be more >> DRY if the `permits` callable threw Forbidden() automatically, but I need it >> in the templates to return True or False which defines parts to be rendered. >> Alternatively I can supply a `nothrow=True` kwarg to return False instead of >> raising Forbidden(). >> >> This way I maintain the policy in single file, the policy can be "pluggable" >> if required (instantiate different policy depending on configuration) and it >> can even be compounded with the view_config's permission argument, and the >> custom authorization policy factory which implements the proper interface. >> >> >> Too complicated? Overkill? Anyone doing something similar? >> >> >> >> -- >> >> >> .oO V Oo. >> >> >> Work Hard, >> Increase Production, >> Prevent Accidents, >> and >> Be Happy! ;) >> >> -- >> You received this message because you are subscribed to the Google Groups >> "pylons-discuss" group. >> To post to this group, send email to [email protected]. >> To unsubscribe from this group, send email to >> [email protected]. >> For more options, visit this group at >> http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
