[Twisted-web] civil guards
Andy Gayton
andy at thecablelounge.com
Sun Jun 27 21:03:49 MDT 2004
I'm looking for a convenient way to show login error messages. I've
made an attempt in the attached civilguard.tac which is a modified
version of examples/guarded.tac.
It abuses that checkers.ANONYMOUS is really an empty tuple, and instead
of returning failure.Failure(error.UnauthorizedLogin()) returns a tuple
with the appropiate error message.
The realm then stretches its definition of ANONYMOUS to be any tuple,
and hands the NotLoggedIn page this tuple so it gets a chance to render
the error messages.
It seems like a pretty round about way of doing things though.
Just hoping to get feedback on how others are doing this sort of thing.
cheers!
Andy.
-------------- next part --------------
from twisted.internet import defer
from twisted.application import service, internet
from twisted.cred import portal, checkers, credentials
from nevow import inevow, rend, tags, appserver, guard, loaders
### Renderers
class NotLoggedIn(rend.Page):
def __init__( self, errors=() ):
rend.Page.__init__( self )
self.errors = errors
def render_errors( self, ctx, data ):
if self.errors:
return [
"Login Error:",
tags.br(),
[ tags.strong[error] for error in self.errors ]
]
return ""
docFactory = loaders.stan(
tags.html[
tags.head[tags.title["Not Logged In"]],
tags.body[
render_errors,
tags.form(action=guard.LOGIN_AVATAR)[
tags.table[
tags.tr[
tags.td[ "Username:" ],
tags.td[ tags.input(type='text',name='username') ],
],
tags.tr[
tags.td[ "Password:" ],
tags.td[ tags.input(type='password',name='password') ],
]
],
tags.input(type='submit'),
tags.p,
]
]
]
)
class LoggedIn(rend.Page):
"""The resource that is returned when you login"""
docFactory = loaders.stan(
tags.html[
tags.head[tags.title["Logged In"]],
tags.body[
tags.h3(render=tags.directive("welcome")),
tags.a(href=guard.LOGOUT_AVATAR)["Logout"]
]
]
)
def render_welcome(self, context, data):
return context.tag[ "Hello, %s!" % data]
def logout(self):
## self.original is the page's main data -- the object that was passed in to the constructor, and
## the object that is initially passed as the 'data' parameter to renderers
print "%s logged out!" % self.original
### Users
class User:
def __init__( self, name, password ):
self.name = name
self.password = password
userdb = {
"fred" : User( "fred", "fred" ),
"ned" : User( "ned", "ned" ),
}
### Authentication
class SimpleChecker:
__implements__ = checkers.ICredentialsChecker
credentialInterfaces = (credentials.IUsernamePassword,)
def __init__(self, userdb):
self.userdb = userdb
def requestAvatarId(self, credentials):
user = self.userdb.get( credentials.username, None )
if user is not None:
return defer.maybeDeferred(
credentials.checkPassword, user.password).addCallback(
self._cbPasswordMatch, credentials.username)
else:
return ( "No user named: %s" % credentials.username, )
def _cbPasswordMatch(self, matched, username):
if matched: return username
return ( "password didn't match: %s" % username, )
class SimpleRealm:
__implements__ = portal.IRealm,
def requestAvatar(self, avatarId, mind, *interfaces):
for iface in interfaces:
if iface is inevow.IResource:
if type(avatarId) is type(checkers.ANONYMOUS):
resc = NotLoggedIn( avatarId )
resc.realm = self
return ( inevow.IResource, resc, lambda : None )
else:
resc = LoggedIn( avatarId )
resc.realm = self
return ( inevow.IResource, resc, resc.logout )
raise NotImplementedError("Can't support that interface.")
### Application setup
realm = SimpleRealm()
portal = portal.Portal(realm)
myChecker = SimpleChecker( userdb )
portal.registerChecker(checkers.AllowAnonymousAccess(), credentials.IAnonymous)
portal.registerChecker(myChecker)
site = appserver.NevowSite(
resource=guard.SessionWrapper(portal)
)
application = service.Application("guarded")
internet.TCPServer(8080, site).setServiceParent(application)
More information about the Twisted-web
mailing list