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. 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)
participants (1)
-
Andy Gayton