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 :-) </off on a tangent>
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
On Oct 30, 2004, at 11:03 AM, Paul Moore wrote:
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:
- 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?
Are you using 0.3 or SVN head? I think Tv was working on fixing guard-related problems in this area. You might have more luck using SVN head, if you are not.
- 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'm not sure guard is sufficiently flexible to allow this. Perhaps one of the guard replacements that is being worked on will help? mg, can you comment? Also, indigo, can you comment on the session system you wrote and/or perhaps turn it into an example or a module?
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?
Sorry I can't be of more help. Guard is one of nevow's weak spots, since I didn't write it and therefore don't understand it, because it is pretty horrifically complex.
<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 :-)
Yes.
At the other end of the scale, the source is really too low-level to follow for this sort of thing (I have tried).
Yes.
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 :-) </off on a tangent>
There should be, and it is creeping up higher on my priority list. However, life prevents me. Hopefully sometime in the next few months.
Perhaps lurking on #twisted.web on irc.freenode.net would help?
dp
Donovan Preston dp@divmod.org writes:
Are you using 0.3 or SVN head? I think Tv was working on fixing guard-related problems in this area. You might have more luck using SVN head, if you are not.
I'm using SVN head. Actually, grubbing round in the source, it looks like putChild comes from ChildLookupMixin, which Page subclasses, but SessionGuard doesn't. So an empty class derived from both SessionGuard and ChildLookupMixin should work...
[Tries it] Yes, that works. Feels like a hack, but it's a working hack :-) I'm still not sure if that leaves the vhost guarded or not, and what that means...
- 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'm not sure guard is sufficiently flexible to allow this. Perhaps one of the guard replacements that is being worked on will help? mg, can you comment? Also, indigo, can you comment on the session system you wrote and/or perhaps turn it into an example or a module?
Interesting. I was getting that impression, too. Also, the code of guard looks very hairy, so I'm not surprised that replacements are under development. If a guinea pig is needed, let me know...
I looked at the current guard code, and it seems odd. I don't see the point of things like __session_just_started__ (particularly as it's user-visible :-() and the fact that login/logout are represented by separate URLs, rather than just posting back to the current URL and reading the form data is different from other approaches I have seen.
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 :-)
There should be, and it is creeping up higher on my priority list. However, life prevents me. Hopefully sometime in the next few months.
Perhaps lurking on #twisted.web on irc.freenode.net would help?
I'll certainly do that. I'll also see if I can add any useful bits to the Wiki...
Paul.
On Sat, 2004-10-30 at 12:26 -0400, Donovan Preston wrote:
On Oct 30, 2004, at 11:03 AM, Paul Moore wrote:
[...]
- 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'm not sure guard is sufficiently flexible to allow this. Perhaps one of the guard replacements that is being worked on will help? mg, can you comment? Also, indigo, can you comment on the session system you wrote and/or perhaps turn it into an example or a module?
Hmm, I don't think there's any way of handling cookie logins right now except maybe redirecting to the __login__ URL with the username and password as query params. But yuck!
One of the problems with guard is that there is no API exposed. It might be nice if guard remembered an IGuard interface for application code to use. What that would look like and how it would behave is something I have not considered.
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?
Sorry I can't be of more help. Guard is one of nevow's weak spots, since I didn't write it and therefore don't understand it, because it is pretty horrifically complex.
Yes. I tried to understand the guard code and got lost so I ended up rewriting it as a learning exercise with the intention of porting bits back into nevow.guard.
My rewrite is *much* simpler. It's not as complete as nevow.guard although it does work and has the distinct advantage that it does not create a session until it's really needed.
Valentino (aka dialtone) recently started patching my version in an attempt to bring it inline with the real guard. He's even started calling it newguard ;-). I guess this is a case of "watch this space".
Cheers, Matt
On Thu, 04 Nov 2004 22:47:01 +0000, Matt Goodall matt@pollenation.net wrote:
One of the problems with guard is that there is no API exposed. It might be nice if guard remembered an IGuard interface for application code to use. What that would look like and how it would behave is something I have not considered.
Actually I think the current implementation is better since it's completely unaware of what it is guarding, thus making it really pluggable and easy to remove.
Probably, a good thing to do is to set as a component the current avatarId in the session. So that from application code one could say:
ICurrentUser(inevow.IRequest(ctx)).name/login/some_other_stuff
and probably also provide some functionality to set some default 'rememberings' which I currently do with the RememberResourceWrapper
My rewrite is *much* simpler. It's not as complete as nevow.guard although it does work and has the distinct advantage that it does not create a session until it's really needed.
indeed it's far better than current nevow and a lot easier to hack.
Valentino (aka dialtone) recently started patching my version in an attempt to bring it inline with the real guard. He's even started calling it newguard ;-). I guess this is a case of "watch this space"
Ehe :), If can get things to work as I want, and get some help from Tv, newguard should be ready soon. Right now it works fairly well and it's backwards compatible with old guard.
And, as I wrote in the note inside guard.py, I'm willing to write some support for database session storage, which will come in handy for my next university project about distributed systems.