from formless import webform from nevow import rend, loaders, static, tags as T, flat, inevow from pyscrabble.net import interfaces from pyscrabble import util from twisted.internet import reactor from twisted.web import http, xmlrpc from zope.interface import implements import os.path class ScrabbleSite(rend.Page): ''' Main Administration page ''' addSlash = True docFactory = loaders.xmlfile('resources/web/index.html') child_styles = None def __init__(self, path, factory): ''' Constructor @param path: path @param factory: ScrabbleServerFactory ''' rend.Page.__init__(self) flat.registerFlattener(self.flattenTime, util.Time) ScrabbleSite.child_styles = static.File( os.path.join(path, 'resources/web/') ) self.factory = factory def flattenTime(self, original, ctx): ''' Flatten a Time object @param original: @param ctx: ''' return str(original) def renderHTTP(self, ctx): ''' Trap all http requests to make sure the user is logged in @param ctx: ''' request = inevow.IRequest(ctx) username, password = request.getUser(), request.getPassword() # First make sure we have users defined if (self.factory.hasUsers()): # Make sure that the user/password match and the user is an admin if not (self.factory.authenticate(username, util.hashPassword(password)) and self.factory.isUserAdmin(username)): request.setHeader('WWW-Authenticate', 'Basic realm="PyScrabble Server"') request.setResponseCode(http.UNAUTHORIZED) return "Authentication Required." return rend.Page.renderHTTP(self, ctx) def locateChild(self, ctx, segments): ''' Locate child segments @param ctx: @param segments: ''' if (segments[0] == 'user_admin'): return UserAdmin(original=segments[1], ctx=ctx, factory=self.factory), segments[2:] if (segments[0] == 'xmlrpc'): return ScrabbleRPC(self.factory), segments[1:] return super(ScrabbleSite, self).locateChild(ctx, segments) def configurable_bulletinForm(self, ctx): f = BulletinForm() f.factory = self.factory return f def configurable_newGameForm(self, ctx): f = NewGameForm() f.factory = self.factory return f def configurable_deleteUserForm(self, ctx): f = DeleteUserForm() f.factory = self.factory return f def configurable_kickUserForm(self, ctx): f = KickUserForm() f.factory = self.factory return f def configurable_stopServerForm(self, ctx): f = StopServerForm() f.factory = self.factory return f def configurable_resetRankForm(self, ctx): f = ResetRankForm() f.factory = self.factory return f def data_allUsers(self, context, data): return [(user.getUsername(), user.isAdmin(), user.getCreatedDate(), user.getLastLoginDate()) for user in self.factory.getUsers()] def data_allGames(self, context, data): return [(game.getName(), game.getNumberOfPlayers(), game.getPlayers(), repr(game.getStatus())) for game in self.factory.getGameListing()] def data_allBulletins(self, ctx, data): return [ (message.id, repr(message.data), message.date) for message in self.factory.getServerBulletins()] def render_totalUsers(self, context, data): ''' Render the total # of users @param context: @param data: ''' return len( self.factory.getUsers() ) def render_loggedInUsers(self, context, data): return self.factory.getLoggedInPlayers() def render_bulletinRow(self, context, (id, data, date)): context.fillSlots('message',data) context.fillSlots('date', date) return context.tag def render_userRow(self, context, data): context.fillSlots('isAdmin', data[1]) context.fillSlots('createdDate', data[2]) context.fillSlots('lastLogin', data[3]) return context.tag def render_gameRow(self, context, data): context.fillSlots('gameId', data[0]) context.fillSlots('numberOfPlayers', data[1]) context.fillSlots('players', data[2]) context.fillSlots('status', data[3]) return context.tag def render_userAdmin(self, context, data): return T.a(href='user_admin/%s'%data[0])[data[0]] def render_deleteGameForm(self, context, (gameId, num, players, stat)): ret = T.form(action="./freeform_post!newGameForm!deleteGame", enctype="multipart/form-data", method="POST")[ T.input(type="hidden", name="gameId", value=gameId), T.input(type="submit", value="Delete")] return ret def render_deleteBulletinForm(self, context, (bulletinId, data, date)): ret = T.form(action="./freeform_post!bulletinForm!deleteBulletin", enctype="multipart/form-data", method="POST")[ T.input(type="hidden", name="bulletinId", value=bulletinId), T.input(type="submit", value="Delete")] return ret def render_deleteUserForm(self, context, (username, isAdmin, createdDate, lastLoginDate)): ret = T.form(action="./freeform_post!deleteUserForm!deleteUser", enctype="multipart/form-data", method="POST")[ T.input(type="hidden", name="username", value=username), T.input(type="submit", value="Delete")] return ret def render_kickUserForm(self, context, (username, isAdmin, createdDate, lastLoginDate)): ret = T.form(action="./freeform_post!kickUserForm!kickUser", enctype="multipart/form-data", method="POST")[ T.input(type="hidden", name="username", value=username), T.input(type="submit", value="Boot")] return ret def render_stopServerForm(self, context): ret = T.form(action="./freeform_post!stopServerForm!stopServer", enctype="multipart/form-data", method="POST")[ T.input(type="submit", value="Stop Server")] return ret def render_resetRankForm(self, context): ret = T.form(action="./freeform_post!resetRankForm!resetRank", enctype="multipart/form-data", method="POST")[ T.input(type="submit", value="Reset Ranks")] return ret def render_bulletinForm(self, context, data): return webform.renderForms('bulletinForm') class UserAdmin(rend.Page): addSlash = True docFactory = loaders.xmlfile('resources/web/user_admin.html') def renderHTTP(self, ctx): request = inevow.IRequest(ctx) username, password = request.getUser(), request.getPassword() # First make sure we have users defined if (self.factory.hasUsers()): # Make sure that the user/password match and the user is an admin if not (self.factory.authenticate(username, util.hashPassword(password)) and self.factory.isUserAdmin(username)): request.setHeader('WWW-Authenticate', 'Basic realm="PyScrabble Server"') request.setResponseCode(http.UNAUTHORIZED) return "Authentication Required." return rend.Page.renderHTTP(self, ctx) def __init__(self, original, ctx, factory): self.factory = factory self.user = self.factory.getUser(original) rend.Page.__init__(self, original) def configurable_modifyUserForm(self, context): f = EditUserForm(self.original) f.factory = self.factory return f def render_userName(self, context, data): return self.original def render_userForm(self, context, form): isAdmin = "No" if (self.user.isAdmin()): isAdmin = "Yes" return webform.renderForms('modifyUserForm', bindingDefaults = {'modifyUser': {'isAdministrator' : isAdmin}}) class ScrabbleRPC(xmlrpc.XMLRPC): ''' XML-RPC Site that gives information about the Scrabble Server ''' def __init__(self, factory): xmlrpc.XMLRPC.__init__(self) self.factory = factory def xmlrpc_getNumUsers(self): ''' Get the number of users on the server @return: Number of users on the server ''' return len( self.factory.getUsers() ) def xmlrpc_createNewUser(self, username, password): ''' Create a new user @param username: Username @param password: Password @return: Tuple (bool,msg) bool=>True if successful, msg=>Detail message ''' return self.factory.addNewUser(username, password, False) class BulletinForm(object): implements(interfaces.IBulletinForm) def addNewBulletin(self,ctx, message): self.factory.addServerBulletin(message) def deleteBulletin(self,ctx, bulletinId): self.factory.deleteServerBulletin(bulletinId) class EditUserForm(object): implements(interfaces.IEditUserForm) def __init__(self, username): self.username = username def modifyUser(self, ctx, oldPassword, password, isAdministrator): user = self.factory.getUser(self.username) if password is not None: pw = util.hashPassword(password) self.factory.doChangePassword(self.username, pw) user.setPassword( pw ) if isAdministrator == "Yes": user.setIsAdmin(True) else: user.setIsAdmin(False) self.factory.updateUser(user) class NewGameForm(object): implements(interfaces.INewGameForm) def deleteGame(self, ctx, gameId): self.factory.deleteGame(gameId) class DeleteUserForm(object): implements(interfaces.IDeleteUserForm) def deleteUser(self, ctx, username): self.factory.removeUser(username) class KickUserForm(object): implements(interfaces.IKickUserForm) def kickUser(self, ctx, username): self.factory.bootUser(username) class StopServerForm(object): implements(interfaces.IStopServerForm) def stopServer(self, ctx): self.factory.stopFactory() reactor.stop() class ResetRankForm(object): implements(interfaces.IResetRankForm) def resetRank(self, ctx): self.factory.resetRanks()