import sys sys.path.append('../') # to appease pickle from twisted.internet import defer from twisted.python import components from nevow import rend, loaders, tags, inevow, accessors import config, util, store from store import * import keepalive, controlconn components.registerAdapter(accessors.ObjectContainer, store.Record, inevow.IContainer) wfd = defer.waitForDeferred class IRCPage(rend.Page): __conn = None def getConn(self): if not IRCPage.__conn: IRCPage.__conn = controlconn.connect((config.SERVER, int(config.PORT)), config.CONTROLNICK) d = defer.Deferred() def copyChain(method): def cb(val): method(val) return val return cb IRCPage.__conn.addCallbacks(copyChain(d.callback), copyChain(d.errback)) return d def renderHTTP(self, *a, **kw): keepalive.ping() return rend.Page.renderHTTP(self, *a, **kw) def httpUser(self, ctx): return inevow.IRequest(ctx).environ.get('REMOTE_USER', None) def remote(self, cmd, *args): return self.getConn().addCallback(lambda conn: conn.cmd(cmd, *args)) def getNetID(self, ctx): return self.remote('getNetID', self.httpUser(ctx)) def updateNetID(self, netid): return self.remote('updateNetID', netid) def getIRCUser(self, username): return self.remote('getIRCUser', username) def deleteIRCUser(self, username): return self.remote('deleteIRCUser', username) def updateIRCUser(self, user): return self.remote('updateIRCUser', user) def addIRCUser(self, user): return self.remote('addIRCUser', user) class Index(IRCPage): addSlash = True docFactory = loaders.xmlfile(config.WEBDIR + '/templates/index.xml') def data_netid(self, ctx, data): return self.getNetID(ctx).addCallback(accessors.ObjectContainer) # convert to ObjectContainer def render_addForm(self, ctx, data): if len(data.child(ctx, 'names')) < data.child(ctx, 'namesallowed'): pat = inevow.IQ(ctx).patternGenerator('form') return [pat()] else: pat = inevow.IQ(ctx).patternGenerator('error') return [pat()] def child_edit(self, ctx): return EditFactory() def child_new(self, ctx): return self.getNetID(ctx).addCallback(NewNick) class EditFactory(IRCPage): addSlash = True def renderHTTP(self, ctx): req = inevow.IRequest(ctx) req.redirect('../') return "No username given." def locateChild(self, ctx, segments): name = segments[0] def onNetID(netid): if name in netid.names: return EditNick(name), segments[1:] else: return super(EditFactory, self).locateChild(ctx, segments) return self.getNetID(ctx).addCallback(onNetID) class EditNick(IRCPage): addSlash = True docFactory = loaders.xmlfile(config.WEBDIR + '/templates/edit.xml') def __init__(self, nick): self.nick = nick def data_ircUser(self, ctx, data): return self.getIRCUser(self.nick).addCallback(accessors.ObjectContainer) def child_save(self, ctx): return SaveNick(self.nick) def child_delete(self, ctx): return DeleteNick(self.nick) class DeleteNick(IRCPage): addSlash = False docFactory = loaders.xmlfile(config.WEBDIR + '/templates/delete.xml') def __init__(self, nick): self.nick = nick def data_ircUser(self, ctx, data): return self.getIRCUser(self.nick).addCallback(accessors.ObjectContainer) def renderHTTP(self, ctx): req = inevow.IRequest(ctx) if req.method.upper() == 'POST': if 'delete' in req.args: if not 'password' in req.args: return "no password provided" def onUser(user): if req.args['password'][0] == user.password: def onDelete(_): req.redirect('../../') return "" return self.deleteIRCUser(self.nick).addCallback(onDelete) else: return "invalid password" return self.getIRCUser(self.nick).addCallback(onUser) else: req.redirect('./') return "" else: return super(DeleteNick, self).renderHTTP(ctx) class SaveNick(IRCPage): addSlash = False def __init__(self, nick): self.nick = nick @defer.deferredGenerator def renderHTTP(self, ctx): req = inevow.IRequest(ctx) if req.method.upper() == 'POST' and 'oldpass' in req.args: user = wfd(self.getIRCUser(self.nick)) yield user user = user.getResult() if req.args['oldpass'][0] == user.password: if 'password' in req.args: user.password = req.args['password'][0] yield wfd(self.updateIRCUser(user)) req.redirect('./') yield "" class NewNick(IRCPage): addSlash = False docFactory = loaders.xmlfile(config.WEBDIR + '/templates/new.xml') def __init__(self, netid): self.netid = netid @defer.deferredGenerator def data_addUser(self, ctx, data): req = inevow.IRequest(ctx) nick = ('nick' in req.args) and req.args['nick'][0].lower() or "" password = ('password' in req.args) and req.args['password'][0] or util.genpass() ctx.fillSlots('nick', nick) ctx.fillSlots('password', password) if len(self.netid.names) >= self.netid.namesallowed: yield "toomany" elif not util.validnick(nick): yield "invalid" else: user = wfd(self.getIRCUser(nick)) yield user user = user.getResult() if user: ctx.fillSlots('owner', user.netid) yield "exists" else: newuser = IRCUser(nick, self.netid.netid, password) result = wfd(self.addIRCUser(newuser)) yield result result = result.getResult() if result: yield "success" else: print "updateUser tells us:", result yield "error" def render_resultMessage(self, ctx, data): patName = data return [inevow.IQ(ctx).patternGenerator(patName)()]