I'm trying to use Nevow to build a site which displays the results of a series of SQL queries. It looks good so far, I have the basic site structure all sorted out in my mind (it's *very* impressive how quick that was in Nevow). Before I flesh things out much further, I want to add some authentication - basically, "guest" users will be able to see a limited subset of the data. Adding authentication including a "login" form in the sidebar (a bit like Roundup does) was again very easy. I basically cribbed from the existing examples. But there are a few things I's now like to add: 1. Ultimately, I want to proxy the app through Apache, so I was using the Virtual Host Monster. Im ny original, unauthenticated, application, I added a "vhost" child to the main application resource, and that was it. I can no longer do that, as the resource is wrapped in a guard.SessionWrapper, which doesn't have a putChild method. I'm not clear that I want the vhost child to be authenticated anyway - what I *think* I want is for "/" to be authenticated, but "/vhost" not to be. Or do I? Any suggestions? 2. I'd like to add a "remember me" checkbox, which if checked sets a cookie to remember the user's ID, so that they don't have to log in again for (say) 2 weeks. Much like gmail, or Yahoo, do. But I'm not too sure how I'd go about this. I'm not even sure where I'd *put* auto-login code: the page is too late (the guard has done its thing by then) but anything else seems to be too early (ie, not per-session, if you see what I mean). I suspect I need to subclass the Portal, or something, but I'm not sure... I've scanned the various examples, both in the distribution and in the Nevow sandbox, but nothing seems to do what I want. Can anyone give me some pointers? <off on a tangent> This is the sort of area where the lack of documentation really hurts. Examples are great (and the wealth of Nevow examples is realy nice) but there's a lack of "general principle" documentation to make it easy to generalise the example code. My best example of this is that I can't work out what to return from a render_* method - should it be a function, or a string, or a stan tree, or what? I suspect that by the magic of interfaces, the answer is "anything that can be adapted to an ISomething" (which needs further documentation to say what standard adapters from string, sequence, whatever to ISomething exist) - but it's not stated anywhere, which makes writing render_* methods an exciting exercise in experimentation :-) At the other end of the scale, the source is really too low-level to follow for this sort of thing (I have tried). Is there any documentation effort for Nevow going on anywhere? I'd happily contribute, although it would more likely be in the form of questions than answers at the moment :-) FWIW, I attach my driver script below, in case it clarifies my authentication question above. from twisted.application import internet from twisted.application import service from twisted.web import static from nevow import appserver from nevow import vhost from nevow import guard from nevow import inevow from twisted.cred import portal from twisted.cred import checkers from twisted.cred import credentials from testapp.web import pages # Authorisation setup. # First we need a realm, which provides requestAvatar # TODO: need NotLoggedIn, LoggedIn and noLogout class MyRealm: """A simple implementor of cred's IRealm. For web, this gives us the LoggedIn page. """ __implements__ = portal.IRealm def requestAvatar(self, avatarId, mind, *interfaces): for iface in interfaces: if iface is inevow.IResource: # do web stuff if avatarId is checkers.ANONYMOUS: resc = pages.BasePage() else: resc = pages.BasePage(avatarId) resc.realm = self return (inevow.IResource, resc, resc.logout) raise NotImplementedError("Can't support that interface.") # Now create a portal to our realm realm = MyRealm() portal = portal.Portal(realm) # Create a checker for a static list of test users myChecker = checkers.InMemoryUsernamePasswordDatabaseDontUse() myChecker.addUser("user","password") myChecker.addUser("fred", "flintstone") # Register our checker, and an anonymous user checker, with the portal portal.registerChecker(checkers.AllowAnonymousAccess(), credentials.IAnonymous) portal.registerChecker(myChecker) application = service.Application('testapp') # Instead of the application resource being the base page, it becomes a # SessionWrapper round the portal we created. The base page is part of the # realm - see above... # appResource = pages.BasePage() appResource = guard.SessionWrapper(portal) #appResource.putChild('robots.txt', static.File('static/robots.txt')) # SessionWrapper doesn't have a putChild method... #vResource = vhost.VHostMonsterResource() #appResource.putChild('vhost', vResource) webServer = internet.TCPServer(8080, appserver.NevowSite(appResource)) webServer.setServiceParent(application) # vim:ft=python: Paul -- The scientific name for an animal that doesn't either run from or fight its enemies is lunch. -- Michael Friedman