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.

Reply via email to