[Twisted-web] Finer-Grained Security System for Twisted Web/Nevow?

Valentino Volonghi dialtone at gmail.com
Mon Apr 20 15:17:31 EDT 2009

On Apr 20, 2009, at 4:05 AM, Jeff Rush wrote:

> Drew Perttula wrote:
>> Jeff Rush wrote:
>> I did openid logins as a mixin class that replaces locateChild:
>> http://bigasterisk.com/darcs/?r=exchangeMeeting;a=headblob;f=/nevowopenid.py
> Draw (and Glyph with his suggestion of Mantissa's approach), thanks  
> for the
> mentions of source I can study to better understand how I might wrap  
> the web
> delivery mechanism.


This is a presentation I gave at europython 07 about some of the  
practices, that
I consider best, in developing with Nevow.

Basically I define a function that touches the database for some  
reason, then
I append that function to a role (or a set of roles) using a decorator:

def deleteUser(avatar, email):
     def _(email):
         return users.delete(users.c.email==email).execute()
     return _(email)

@forRoles('anonymous', 'user', 'admin')
def findUser(avatar, email):
     def _(email):
         return users.select(sq.and_(users.c.email==email,
     return _(email)

This is one example of such a thing. The avatar object is exactly  
what's returned
by cred/guard and it's defined in the following way:

import zope.interface as z

class Avatar(object):
     def __init__(self, behavior, *args, **kw):
         self.username = None
         self.email = None
         self.role = None
         self.password = None
         self.conf = None
         super(Avatar, self).__init__(*args, **kw)
         self._actions = dict(((f.__name__, f) for f in behavior))

     def __getattr__(self, name):
             fun = self._actions[name]
         except KeyError:
             raise NoPermission(name)
         return lambda *args, **kwargs: fun(self, *args, **kwargs)

So that it takes a set of methods that it knows and allows you to call  
if a method is not present you probably don't have enough permissions
(or you made a mistake in writing it).

This is paired with some clever use of patterns:

  <nevow:invisible nevow:render="optional">
              <nevow:invisible nevow:pattern="None">
                Login to upload images.

              <nevow:invisible nevow:pattern="default">
                <nevow:invisible nevow:render="form upload" />

The optional (bad name I know) checks for the role of the current  
if it's None it means that the user is not logged in, otherwise you  
can use
a specific role or default for 'all the others':

This is how it's implemented:

def render_optional(self, ctx, data):
     iq = inevow.IQ(ctx)
         t = iq.onePattern(str(self.avatar.role))
     except stan.NodeNotFound:
             t = iq.onePattern('default')
         except stan.NodeNotFound:
             t = ''
     return ctx.tag[t]

I'm not sure it's still usable though with newer nevow versions,  
it might still be.

The other part (navigating in the tree) should be solvable by using
another decorator that could look like this:

def requiresRole(role, loginPage=LoginPage):
     def _f(fun):
         def __f(avatar, *args, **kwargs):
             if role not in avatar.roles:
                  return loginPage(avatar)
             return fun(avatar, *args, **kwargs)
        return __f
     return _f

Or something similar (this is not tested).

It's been a while since I last used this code but it's concept is  
still good.

Valentino Volonghi aka Dialtone
Now running MacOS X 10.5
Home Page: http://www.twisted.it

-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 194 bytes
Desc: This is a digitally signed message part
Url : http://twistedmatrix.com/pipermail/twisted-web/attachments/20090420/bc5ad838/PGP.pgp

More information about the Twisted-web mailing list