debugging sqlobject within mod_python sucked, so I switched to cherrypy before the switch to sqlobject was complete. What works again: login, account creation, game overview, game creation.

This commit is contained in:
phear 2005-11-24 15:39:22 +00:00
parent 6474c7f47c
commit f09a9e86e0
6 changed files with 316 additions and 405 deletions

View file

@ -1,13 +1,30 @@
import helper,database
#,database
maxuser = 1000
def display_create_form(req,form):
"""
"""
class CreateAccount:
def index(self,username = None, password1 = None, password2 = None):
"""
gets a request object and a util.FieldStorage form.
writes a HTML page containing one name and two password fields.
checks if there are some parameters from the form. If not, displays creation form. Else processes form data
"""
data = """
if username != None and password1 != None and password2 != None:
return self.process_form(username,password1,password2)
else:
return self.display_create_form()
def display_create_form(self):
"""
returns a HTML page containing one name and two password fields.
"""
data = helper.header()
data += """
<form method="post">
<p>Your username:<br>
<input name="username" type="text" class="text" size="20"></p>
@ -15,65 +32,41 @@ def display_create_form(req,form):
<input name="password1" type="text" class="text" size="20"></p>
<p>Please retype your Password:<br>
<input name="password2" type="text" class="text" size="20"></p>
<input type="hidden" name="sessionid" value="%s">
<input type="hidden" name="createaccount" value="process">
<i nput type="hidden" name="sessionid" value="%s">
<i nput type="hidden" name="createaccount" value="process">
<p><input type="submit" class="submit" value="create account"></p>
</form>
""" % helper.generate_session_id()
req.write(data)
data += helper.footer()
return(data)
def process_form(req,form):
def process_form(self,username, password1, password2):
"""
gets a request object and a util.FieldStorage form.
Tries to read out username, password1 and password2 from form.
If all needed data is there, create the named user and return a 'success'
gets username, password1 and password2.
If all data is there and correct, create the named user and return a 'success'
page. Else fail with detailed error.
"""
try:
password1 = form["password1"]
except:
password1 = ""
try:
password2 = form["password2"]
except:
password2 = ""
try:
username = form["username"]
except:
username = ""
if (username != "") and (password1 != "") and (password2 != "") and (password1 == password2):
newuser = database.Users(username=username,password=password1)
data = helper.header()
if (password1 == password2):
#try:
#.add_webgo_user(username,password1)
req.write("User %s has been successfully created. Click the following button to login:<br>" % username)
data = """
<form method="post">
<input name="username" type="hidden" value="%s"></p>
<input name="password" type="hidden" value="%s"></p>
<input type="hidden" name="sessionid" value="%s">
<p><input type="submit" class="submit" value="login"></p>
</form>
""" % (username,password1,helper.generate_session_id())
req.write(data)
newuser = database.Users(username=username,password=password1)
created_user = True
#except:
# #user already exists
# created_user = False
if created_user:
data += ('User %s has been successfully created. Click <a href="/login">here</a> to login.<br>' % username)
else:
data += ("User %s already exists. Please retry with another name." % username)
data += self.display_create_form()
else:
if username == "":
req.write("Please enter a username you would like to have.<br>")
if (password1 == "") or (password2 == "") or (password1 != password2):
req.write("Both given passwords have to be the same and non-empty.<br>")
display_create_form(req,form)
data += ("Both given passwords have to be the same and non-empty.<br>")
data += self.display_create_form()
data += helper.footer()
return data
index.exposed = True
def main(req,form):
req.write(helper.header())
helper.debug(req,form,str(form.keys()))
try:
createvalue = form["createaccount"]
except:
createvalue = ""
if createvalue == "process":
process_form(req,form)
else:
display_create_form(req,form)
req.write(helper.footer(req,form))

View file

@ -39,7 +39,7 @@ class GobanTable(SQLObject):
player1 = StringCol()
player2 = StringCol()
size = IntCol()
name = StringCol(default = helper.generate_game_name(), unique=True,notNone=True,alternateID=True)
#name = StringCol(default=helper.generate_game_name(), unique=True,notNone=True,alternateID=True)
turn_number = 1
description = StringCol(default=None)
sgf = gnugo.create_sgf_file(size)
@ -54,13 +54,8 @@ class GobanTable(SQLObject):
"""updates self.lastmove to current time"""
self.lastmove = int(time.time)
#create table which has been defined above:
# if ifNotExists=True, then an existing table does not get overridden.
GobanTable.createTable(ifNotExists=True)
# add a game to goban table
gob = GobanTable(player1="gast",player2="gast",size=9)
@ -155,16 +150,19 @@ class Users(SQLObject):
def get_users_with_free_game_slots():
"""
returns a list of users who have at least one empty game slot """
idlist = Users.select(Users.q.free_slot_left == True)
idlist = list(Users.select())
retlist = []
for entry in idlist:
retlist.append(Users.get(entry).username)
if entry.free_slot_left() == True:
retlist.append(entry.username)
return retlist
#create table which has been defined above:
# if ifNotExists=True, then an existing table does not get overridden.
Users.createTable(ifNotExists=True)
GobanTable.createTable(ifNotExists=True)
if __name__ == "__main__":
connection_string='sqlite:%s?%s' %(os.path.abspath("webgo.sqlite"),dbdebug)
connection=connectionForURI(connection_string)

View file

@ -1,79 +1,9 @@
from mod_python import *
import helper,login,database
def display_game_creation_form(req,form):
"""
prints a html form with multiple drop-down lists for choosing players,
goban size and so on.
gets a mod_python request, prints to req.write.
"""
username = form["username"]
sessionid = form["sessionid"]
data = helper.header()
p1data = create_user_dropdown_list("player1",username)
p2data = create_user_dropdown_list("player2")
gobansize = create_goban_size_dropdown_list("gobansize")
#start form
#choose player one (black),choose player two (white),choose goban size
#'hidden' session id and username
data += """
<form method="post">
<p>Player One (Black): %s </p>
<p>Player Two (White): %s </p>
<p>Goban Size: %s fields </p>
<p>Optional name for game: <input type="text" name="description" size="20" class="text"></p>
<input type="hidden" name="sessionid" value="%s">
<input type="hidden" name="username" value="%s">
<input type="submit" class="submit" name="create" value="create game">
</form>
""" % (p1data,p2data,gobansize,sessionid,username)
from cherrypy import cpg
from cherrypy.lib import httptools
data+=helper.footer(req,form)
req.write(data)
def process_creation_form(req,form):
"""
validates and processes the game creation form.
If everything was ok, a game will be created.
TODO: change this function, so that the original database state canbe
restored, if for example one of the users does not have a free game slot.
"""
player1 = form["player1"]
player2 = form["player2"]
username = form["username"]
try:
description = form["description"]
except:
description = ""
helper.debug(req,form,"game creation: will use '%s' as description." % description)
#check if at least one of the players is the current user
if (player1 == username) or (player2 == username):
#create game
mygame = database.GobanTable(player1=player1,player2=player2,size=int(form["gobansize"]),description = description)
gamename = mygame.name
#update entries for player one and player two
for player in [player1,player2]:
myplayer = database.Users.byUsername(player)
if myplayer.free_slot_left:
myplayer.add_game(gamename)
else:#should not happen: no free game slot.
#print error msg
req.write("Error: No free game slots for player "+player+"!")
#display form again
display_game_creation_form(req,form["sessionid"],username)
#TODO:game created, now display game overview form
login.game_overview_form(req,form)
else:
#give error message
req.write("Sorry, you must be one of the players!<br>")
#display form again
display_game_creation_form(req,form["sessionid"],username)
def create_user_dropdown_list(listname,selected = ""):
"""
@ -105,20 +35,87 @@ def create_goban_size_dropdown_list(listname):
""" % listname
return data
def main(req,form):
class GameCreation:
"""
display and process forms for game creation.
gets a request object and a util.FieldStorage form.
returns nothing.
manages the creation of games.
"""
req.write(str(form.keys())+"<hr>")
username = form["username"]
#TODO:check if valid session id
sessionid = form["sessionid"]
if "gobansize" in form.keys(): #user already clicked on create
process_creation_form(req,form)
def index(self,player1 = None, player2 = None, description = None,gobansize = None):
username = cpg.request.sessionMap["username"]
myuser = database.Users.byUsername(username)
sessionid = cpg.request.sessionMap["_sessionId"]
if myuser.sessionid == sessionid:
if player1 != None and player2 != None and gobansize != None:
return self.process_creation_form(player1,player2,gobansize,description)
else:
display_game_creation_form(req,form,)
return self.display_game_creation_form()
else:
httptools.redirect("/login")
def display_game_creation_form(self):
"""
prints a html form with multiple drop-down lists for choosing players,
goban size and so on.
"""
username = cpg.request.sessionMap["username"]
myuser = database.Users.byUsername(username)
sessionid = cpg.request.sessionMap["_sessionId"]
data = helper.header()
p1data = create_user_dropdown_list("player1",username)
p2data = create_user_dropdown_list("player2")
gobansize = create_goban_size_dropdown_list("gobansize")
#start form
#choose player one (black),choose player two (white),choose goban size
data += """
<form method="post">
<p>Player One (Black): %s </p>
<p>Player Two (White): %s </p>
<p>Goban Size: %s fields </p>
<p>Optional name for game: <input type="text" name="description" size="20" class="text"></p>
<input type="submit" class="submit" value="create game">
</form>
""" % (p1data,p2data,gobansize)
data += helper.footer()
return data
def process_creation_form(self,player1,player2,gobansize,description=None):
"""
validates and processes the game creation form.
If everything was ok, a game will be created.
TODO: change this function, so that the original database state canbe
restored, if for example one of the users does not have a free game slot.
"""
username = cpg.request.sessionMap["username"]
myuser = database.Users.byUsername(username)
sessionid = cpg.request.sessionMap["_sessionId"]
data = helper.header()
#check if at least one of the players is the current user
if (player1 == username) or (player2 == username):
#create game
mygame = database.GobanTable(player1=player1,player2=player2,size=gobansize,description = description)
gamename = mygame.id
#update entries for player one and player two
for player in [player1,player2]:
myplayer = database.Users.byUsername(player)
if myplayer.free_slot_left:
myplayer.add_game(gamename)
else:#should not happen: no free game slot.
#print error msg
data += "Error: No free game slots for player %s!<br>" % player
#display form again
return self.display_game_creation_form()
httptools.redirect("/overview")
else:
#give error message
data += "Sorry, you must be one of the players!<br>"
#display form again
return self.display_game_creation_form()
data+=helper.footer(req,form)
return data
index.exposed = True

View file

@ -12,7 +12,7 @@ def header():
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<link rel="stylesheet" media="screen" href="default.css" type="text/css" />
<link rel="stylesheet" media="screen" href="/default.css" type="text/css" />
</head>
<h1> WebGo </h1>
<body>
@ -31,7 +31,7 @@ def debug(req,form, optstr = ""):
else:
req.write("Debug: "+optstr+"<br>\n")
def footer(req,form,display_buttons=0):
def footer(display_buttons=0):
"""return html footer"""
try:
username=form["username"]
@ -63,11 +63,7 @@ def generate_session_id():
def generate_game_name():
from whrandom import choice
chars = string.letters
name = ''
for i in range(16):
name = name + choice(chars)
return name.lower()
return generate_session_id()
def check_for_int(data):

266
login.py
View file

@ -1,143 +1,27 @@
import database,init_webgo,helper,gamecreation
#import database,init_webgo,helper,gamecreation
import helper,database
from sets import Set as set
from mod_python import *
def process_form(req,form):
"""
reads username and password from form
"""
#req.write("<br>"+"name="+form['name']+", password="+form['password']+"<hr>")
if form.keys() != []:
if ("username" in form.keys()) and ("password" in form.keys()):
#extract name and password
username = form["username"]
myuser = database.Users.byUsername(username)
password = form["password"]
sessionid = form["sessionid"]
origpassword = myuser.password
#debug:
helper.debug(req,form,'<hr>--password:'+str(password)+' ---origpassword:'+str(origpassword)+'<hr>')
#check if user exists (else we would get an error string)
if origpassword != "no such user": #no error message, now check password
if password == origpassword:
#login accepted
myuser.sessionid = sessionid
myser.set_timeout()
#now display list of games.
game_overview_form(req,form)
else:
req.write("Login incorrect. Please try again.<br>")
req.write(login_form(req,form))
else: #no such user
req.write("Login incorrect. Please try again.-<br>")
req.write(login_form(req,form))
else: #one of (name,password) is missing:
req.write("Please enter your name and password.")
req.write(login_form(req,form))
from cherrypy import cpg
from cherrypy.lib import httptools
"""
def game_overview_form(req,form):
"""
gets: request object, util.FieldStorage form, name of user, sessionid.
prints a form with the option to select,create and delete games.
"""
username = form["username"]
sessionid = form["sessionid"]
data = helper.header()+ """
<h2> Current Games: </h2>
"""
gamelist = myuser.gamelist()
#debug
helper.debug(req,form,str(gamelist)+"<hr>\n")
#display list of current games
counter = 10 - len(helper.clean_list(gamelist))
tmp = ""
if helper.clean_list(gamelist) != []:
tmp += "<table><tr><td></td><td>Name of game</td><td>White</td>"
tmp += "<td>Black</td><td>Time of Creation</td><td>Time of last move</td>"
tmp += "<td></td></tr>"
for item in set(helper.clean_list(gamelist)):
if (item != None) and (item != "None"):
tmp += '<tr><form method="post">\n'
tmp += '<input type="hidden" name="sessionid" value="%s">\n' % sessionid
tmp += '<input type="hidden" name="username" value="%s">\n' % username
tmp += '<input type="hidden" name="game" value="%s">\n' % item
tmp += '<td><input type=submit class="submit" name="play" value="Play"></td>\n'
mygame = database.GobanTable.byName(item)
description = mygame.description
if (description == None) or (description == "None") or (description == ""):
description = item
tmp += '<td>%s</td>\n' % description
players = mygame.players()
tmp += '<td>%s</td>\n' % players[0]
tmp += '<td>%s</td>\n' % players[1]
tmp += '<td>%s</td>\n' % helper.format_time(mygame.created)
tmp += '<td>%s</td>\n' % helper.format_time(mygame.lastmove)
tmp += '<td><input type=submit class="submit" name="delete" value="Delete"></td>\n'
tmp += '</tr></form>\n'
if helper.clean_list(gamelist) != []:
tmp += '</table>'
if gamelist == []: #no current games
data += "You don't have any running games.\n"
else:
data += tmp
#now comes the option for creating new games.
data += "<h2>New Game:</h2>\n"
if counter > 0:
data+= "You have %s free game slots.<br>" % counter
data += """
<form method="post">
<input type="hidden" name="sessionid" value="%s">
<input type="hidden" name="username" value="%s">
<input type=submit class="submit" name="create" value="Start a new game">
</form>
""" % (sessionid, username)
else:
data+= "Sorry, all your game slots are in use."
data+=helper.footer(req,form,1)
req.write(data)
def login_form(req,form):
"""
print welcome message and html form.
"""
data = helper.header() + """
<form method="post">
<p>Name:<br>
<input name="username" type="text" class="text" size="20"></p>
<p>Password:<br>
<input name="password" type="text" class="text" size="20"></p>
<input type="hidden" name="sessionid" value="%s">
<p><input type="submit" class="submit" value="login"></p>
</form>
<form method="post">
<input type="hidden" name="createaccount" value="init">
<input type="submit" class="submit" value="create account">
</form>
""" % helper.generate_session_id()
data += helper.footer(req,form)
return data
"""
"""
def navigation_bar(req,form):
"""
"" "
gets request object and util.FieldStorage form.
writes the following to req:
- a button to return to the game overview
- a logout button
returns string
"""
" ""
username = form["username"]
sessionid = form["sessionid"]
game = form["game"]
#TODO: buttons
data="""
data=" ""
<form method="post">
<input type="hidden" name="username" value="%s">
<input type="hidden" name="sessionid" value="%s">
@ -146,15 +30,15 @@ def navigation_bar(req,form):
<input type="submit" class="submit" name="game overview" value="game overview">
<input type="submit" class="submit" name="refresh" value="refresh">
</form>
""" % (username,sessionid,game)
"" " % (username,sessionid,game)
return(data)
def logout(req,form):
"""
"" "
gets request object and util.FieldStorage form.
reads username from form and clears timeout and sessionid from users table.
"""
"" "
username = form["username"]
myuser = database.Users.byUsername(username)
myuser.sessionid = ""
@ -174,3 +58,127 @@ def main(req,form):
process_form(req,form)
else:
process_form(req,form)
"""
class Login:
def index(self,username=None,password=None):
"""
Without arguments, this function writes a login form. Else the login data is evaluated
and the user is eventually logged in.
"""
if username == None and password == None:
return self.login_form()
else:
return self.process_form(username,password)
def login_form(self):
"""
print welcome message and html form.
"""
data = helper.header()
data += """
<form method="post">
<p>Name:<br>
<input name="username" type="text" class="text" size="20"></p>
<p>Password:<br>
<input name="password" type="text" class="text" size="20"></p>
<p><input type="submit" class="submit" value="login"></p>
</form>
<a href="/createaccount"> create account</a><br>
"""
data += helper.footer()
return data
def process_form(self,username,password):
"""
gets username and password, checks for validity, eventually the user is logged in.
TODO: check for session timeout
"""
data = helper.header()
sessionid = cpg.request.sessionMap["_sessionId"]
myuser = database.Users.byUsername(username)
origpassword = myuser.password
if password == origpassword:
#login accepted
myuser.sessionid = sessionid
myuser.set_timeout()
cpg.request.sessionMap["username"] = username
#now display list of games.
httptools.redirect("/overview")
#data += "Login accepted."
else:
data += "Login incorrect. Please try again.<br>"
data += self.login_form()
data += helper.footer()
return data
index.exposed=True
class Overview:
"""
give out a list of current games and stuff."""
def index(self):
username = cpg.request.sessionMap["username"]
myuser = database.Users.byUsername(username)
sessionid = cpg.request.sessionMap["_sessionId"]
if myuser.sessionid == sessionid:
return self.game_overview_form(username)
else:
return "You must be logged in to access this page."
def game_overview_form(self,username):
"""
gets:name of user,
prints a form with the option to select,create and delete games.
"""
myuser = database.Users.byUsername(username)
data = helper.header()+ """
<h2> Current Games: </h2>
"""
gamelist = myuser.gamelist()
#display list of current games
counter = 10 - len(helper.clean_list(gamelist))
tmp = ""
if helper.clean_list(gamelist) != []:
tmp += "<table><tr><td></td><td>Name of game</td><td>White</td>"
tmp += "<td>Black</td><td>Time of Creation</td><td>Time of last move</td>"
tmp += "<td></td></tr>"
for item in helper.clean_list(gamelist):
if (item != None) and (item != "None"):
tmp += '<tr><form method="post">\n'
tmp += '<input type="hidden" name="username" value="%s">\n' % username
tmp += '<input type="hidden" name="game" value="%s">\n' % item
tmp += '<td><input type=submit class="submit" name="play" value="Play"></td>\n'
mygame = database.GobanTable.get(item)
description = mygame.description
if (description == None) or (description == "None") or (description == ""):
description = item
tmp += '<td>%s</td>\n' % description
players = mygame.players()
tmp += '<td>%s</td>\n' % players[0]
tmp += '<td>%s</td>\n' % players[1]
tmp += '<td>%s</td>\n' % helper.format_time(mygame.created)
tmp += '<td>%s</td>\n' % helper.format_time(mygame.lastmove)
tmp += '<td><input type=submit class="submit" name="delete" value="Delete"></td>\n'
tmp += '</tr></form>\n'
if helper.clean_list(gamelist) != []:
tmp += '</table>'
if gamelist == []: #no current games
data += "You don't have any running games.\n"
else:
data += tmp
#now comes the option for creating new games.
data += "<h2>New Game:</h2>\n"
if counter > 0:
data+= "You have %s free game slots.<br>" % counter
data += '<a href="/gamecreation"> Start a new game</a><br>'
else:
data+= "Sorry, all your game slots are in use."
data+=helper.footer()
return data
index.exposed = True

127
main.py
View file

@ -1,110 +1,29 @@
import sys, traceback,string,time
import init_webgo,database
import login,createaccount,helper,gamecreation
from cherrypy import cpg
from mod_python import *
DEBUG = 1
def handler(req):
# "Content-type: text/html\n\n"
req.content_type = "text/html"#was:text/html
try: # use explicit exception handling
#reinitialize database
#init_webgo.main()
#load form, then delegate request
form = util.FieldStorage(req)
try:
sessionid=form["sessionid"]
username=form["username"]
except:
sessionid=""
username=""
try:
myuser = database.Users.byUsername(username)
valid_user = True
except:
#no such user
valid_user = False
if username != "" and valid_user:
if (myuser.timeout > int(time.time())) and (sessionid == myuser.sessionid):
myuser.set_timeout()
if "create" in form.keys():
gamecreation = apache.import_module("gamecreation")
gamecreation.main(req,form)
elif "delete" in form.keys():
deletegame = apache.import_module("deletegame")
deletegame.main(req,form)
elif ("play" in form.keys()) or ("refresh" in form.keys()):
playgame = apache.import_module("playgame")
playgame.main(req,form)
elif "logout" in form.keys():
logout = apache.import_module("logout")
logout.main(req,form)
else:
#call login.py
login = apache.import_module("login")
login.main(req,form)
else:
#call login.py
login = apache.import_module("login")
login.main(req,form)
else:
if "createaccount" in form.keys():
createaccount = apache.import_module("createaccount")
createaccount.main(req,form)
else:#call login.py
login = apache.import_module("login")
login.main(req,form)
return apache.OK
except:
errtime = '----- '+ time.ctime(time.time()) +' -----\n'
errlog = open('/tmp/cgi_errors.log', 'a')
errlog.write(errtime)
errlog.write(ErrorMsg())
data = """<html><head><title>CGI Error Encountered!</title></head>
<body><p>Sorry, a problem was encountered running WebGo.</p>
<p>Please check the error log on the server for details.</p>
<hr><pre>"""
data += ErrorMsg()
data+="</pre>\n</body></html>"
req.write(data)
return apache.OK
def ErrorMsg(escape=0):
class WebGoSite:
def index(self):
data = helper.header()
data += """ This is WebGo.<br>
<a href="/login">login</a><br>
<a href="/createaccount">create an account</a><br>
"""
returns: string
data += helper.footer()
return data
index.exposed = True
simualtes the traceback output and if argemument
<escape> set to 1 (true) the string will be
converted to fit into html documents without problems.
from Dirk Holtwick
"""
import traceback, sys, string
cpg.root = WebGoSite()
cpg.root.createaccount = createaccount.CreateAccount()
cpg.root.login = login.Login()
cpg.root.overview = login.Overview()
cpg.root.gamecreation = gamecreation.GameCreation()
type=None
value=None
tb=None
limit=None
type, value, tb = sys.exc_info()
body = "Traceback (innermost last):\n"
list = traceback.format_tb(tb, limit) + traceback.format_exception_only(type, value)
body = body + "%-20s %s" % (
string.join(list[:-1], ""),
list[-1],
cpg.server.start(configMap={'sessionStorageType' : 'ram',
'sessionCookieName' : 'WebGoSessionCookie',
'sessionTimeout' : 15, #Session expires in n minutes
'staticContentList':
[['default.css','default.css']]
}
)
if escape:
import cgi
body = cgi.escape(body)
return body