update database connection logic; reformat some sql transactions

pull/4/head
Blake DeMarcy 2017-04-03 03:31:00 -05:00
parent cf16169027
commit 2fd58556fc
2 changed files with 47 additions and 51 deletions

View File

@ -11,19 +11,17 @@ dbname = "data.sqlite"
# user anonymity is achieved in the laziest possible way: a literal user # user anonymity is achieved in the laziest possible way: a literal user
# named anonymous. may god have mercy on my soul. # named anonymous. may god have mercy on my soul.
with sqlite3.connect(dbname) as _c: _c = sqlite3.connect(dbname)
try:
db.anon = db.user_resolve(_c, "anonymous") db.anon = db.user_resolve(_c, "anonymous")
if not db.anon: if not db.anon:
db.anon = db.user_register( db.anon = db.user_register(
_c, "anonymous", # this is the hash for "anon" _c, "anonymous", # this is the hash for "anon"
"5430eeed859cad61d925097ec4f53246" "5430eeed859cad61d925097ec4f53246"
"1ccf1ab6b9802b09a313be1478a4d614") "1ccf1ab6b9802b09a313be1478a4d614")
finally:
_c.close()
# creates a database connection for each thread del _c
def db_connect(_):
cherrypy.thread_data.db = sqlite3.connect(dbname)
cherrypy.engine.subscribe('start_thread', db_connect)
def api_method(function): def api_method(function):
@ -44,6 +42,7 @@ def api_method(function):
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
response = None response = None
try: try:
connection = sqlite3.connect(dbname)
# read in the body from the request to a string... # read in the body from the request to a string...
body = str(cherrypy.request.body.read(), "utf8") body = str(cherrypy.request.body.read(), "utf8")
# is it just empty bytes? not all methods require an input # is it just empty bytes? not all methods require an input
@ -64,7 +63,7 @@ def api_method(function):
user = db.anon user = db.anon
else: else:
user = db.user_resolve(cherrypy.thread_data.db, username) user = db.user_resolve(connection, username)
if not user: if not user:
raise BBJUserError("User %s is not registered" % username) raise BBJUserError("User %s is not registered" % username)
@ -75,7 +74,7 @@ def api_method(function):
# api_methods may choose to bind a usermap into the thread_data # api_methods may choose to bind a usermap into the thread_data
# which will send it off with the response # which will send it off with the response
cherrypy.thread_data.usermap = {} cherrypy.thread_data.usermap = {}
value = function(self, body, cherrypy.thread_data.db, user) value = function(self, body, connection, user)
response = schema.response(value, cherrypy.thread_data.usermap) response = schema.response(value, cherrypy.thread_data.usermap)
except BBJException as e: except BBJException as e:
@ -95,6 +94,7 @@ def api_method(function):
print("logged code 1 exception " + error_id) print("logged code 1 exception " + error_id)
finally: finally:
connection.close()
return json.dumps(response) return json.dumps(response)
return wrapper return wrapper
@ -165,6 +165,8 @@ class API(object):
The newly updated user object is returned on success. The newly updated user object is returned on success.
""" """
if user == db.anon:
raise BBJParameterError("Anons cannot modify their account.")
validate(args, []) # just make sure its not empty validate(args, []) # just make sure its not empty
return db.user_update(database, user, args) return db.user_update(database, user, args)
@ -209,7 +211,8 @@ class API(object):
validate(args, ["body", "title"]) validate(args, ["body", "title"])
thread = db.thread_create( thread = db.thread_create(
database, user["user_id"], args["body"], args["title"]) database, user["user_id"], args["body"], args["title"])
cherrypy.thread_data.usermap = thread cherrypy.thread_data.usermap = \
create_usermap(database, thread["messages"])
return thread return thread
@ -255,7 +258,7 @@ class API(object):
if user == db.anon: if user == db.anon:
raise BBJUserError("Anons cannot edit messages.") raise BBJUserError("Anons cannot edit messages.")
validate(args, ["body", "thread_id", "post_id"]) validate(args, ["body", "thread_id", "post_id"])
return message_edit_commit( return db.message_edit_commit(
database, user["user_id"], args["thread_id"], args["post_id"], args["body"]) database, user["user_id"], args["thread_id"], args["post_id"], args["body"])
@ -272,7 +275,7 @@ class API(object):
if user == db.anon: if user == db.anon:
raise BBJUserError("Anons cannot edit messages.") raise BBJUserError("Anons cannot edit messages.")
validate(args, ["thread_id", "post_id"]) validate(args, ["thread_id", "post_id"])
return message_edit_query( return db.message_edit_query(
database, user["user_id"], args["thread_id"], args["post_id"]) database, user["user_id"], args["thread_id"], args["post_id"])

View File

@ -41,15 +41,17 @@ def thread_get(connection, thread_id, messages=True):
and only get its metadata, such as title, author, etc. and only get its metadata, such as title, author, etc.
""" """
c = connection.cursor() c = connection.cursor()
c.execute("SELECT * FROM threads WHERE thread_id = ?", (thread_id,)) thread = c.execute(
thread = c.fetchone() "SELECT * FROM threads WHERE thread_id = ?",
(thread_id,)).fetchone()
if not thread: if not thread:
raise BBJParameterError("Thread does not exist.") raise BBJParameterError("Thread does not exist.")
thread = schema.thread(*thread) thread = schema.thread(*thread)
if messages: if messages:
c.execute("""SELECT * FROM messages WHERE thread_id = ? c.execute("""
SELECT * FROM messages WHERE thread_id = ?
ORDER BY post_id""", (thread_id,)) ORDER BY post_id""", (thread_id,))
# create a list where each post_id matches its list[index] # create a list where each post_id matches its list[index]
thread["messages"] = [schema.message(*values) for values in c.fetchall()] thread["messages"] = [schema.message(*values) for values in c.fetchall()]
@ -65,10 +67,10 @@ def thread_index(connection):
Please note that thred["messages"] is omitted. Please note that thred["messages"] is omitted.
""" """
c = connection.cursor() c = connection.execute("""
c.execute("""
SELECT thread_id FROM threads SELECT thread_id FROM threads
ORDER BY last_mod DESC""") ORDER BY last_mod DESC""")
threads = [ threads = [
thread_get(connection, obj[0], messages=False) thread_get(connection, obj[0], messages=False)
for obj in c.fetchall() for obj in c.fetchall()
@ -91,29 +93,23 @@ def thread_create(connection, author_id, body, title):
thread_id, author_id, title, thread_id, author_id, title,
now, now, -1) # see below for why i set -1 instead of 0 now, now, -1) # see below for why i set -1 instead of 0
connection.cursor().execute(""" connection.execute("""
INSERT INTO threads INSERT INTO threads
VALUES (?,?,?,?,?,?) VALUES (?,?,?,?,?,?)
""", schema_values("thread", scheme)) """, schema_values("thread", scheme))
connection.commit() connection.commit()
scheme["messages"] = [
thread_reply(connection, author_id, thread_id, body, time_override=now) thread_reply(connection, author_id, thread_id, body, time_override=now)
] # fetch the new thread out of the database instead of reusing the returned
scheme["reply_count"] = 0 # objects, just to be 100% sure what is returned is what was committed
# note that thread_reply returns a schema object return thread_get(connection, thread_id)
# after committing the new message to the database.
# here i mimic a real thread_get by including a mock
# message array, and then setting the reply_count
# to reflect its new database value, so the response
# can be loaded as a normal thread object
# this hackery needs a bit more testing
return scheme
def thread_reply(connection, author_id, thread_id, body, time_override=None): def thread_reply(connection, author_id, thread_id, body, time_override=None):
""" """
Submit a new reply for thread_id. Return the new reply object. Submit a new reply for thread_id. Return the new reply object.
time_overide can be time() value to set as the new message time.
This is to keep post_id 0 in exact parity with its parent thread.
""" """
validate([("body", body)]) validate([("body", body)])
@ -124,14 +120,12 @@ def thread_reply(connection, author_id, thread_id, body, time_override=None):
thread_id, count, author_id, thread_id, count, author_id,
now, False, body) now, False, body)
c = connection.cursor() connection.execute("""
c.execute("""
INSERT INTO messages INSERT INTO messages
VALUES (?,?,?,?,?,?) VALUES (?,?,?,?,?,?)
""", schema_values("message", scheme)) """, schema_values("message", scheme))
c.execute(""" connection.execute("""
UPDATE threads SET UPDATE threads SET
reply_count = ?, reply_count = ?,
last_mod = ? last_mod = ?
@ -154,7 +148,7 @@ def message_edit_query(connection, author, thread_id, post_id):
except IndexError: except IndexError:
raise BBJParameterError("post_id out of bounds for requested thread") raise BBJParameterError("post_id out of bounds for requested thread")
if not user["admin"]: if not user["is_admin"]:
if not user["user_id"] == message["author"]: if not user["user_id"] == message["author"]:
raise BBJUserError( raise BBJUserError(
"non-admin attempt to edit another user's message") "non-admin attempt to edit another user's message")
@ -172,15 +166,16 @@ def message_edit_commit(connection, author_id, thread_id, post_id, new_body):
message_edit_query first. Returns the newly updated message object. message_edit_query first. Returns the newly updated message object.
""" """
validate([("body", new_body)]) validate([("body", new_body)])
message = message_edit_query(author_id, thread_id, post_id) message = message_edit_query(connection, author_id, thread_id, post_id)
message["body"] = new_body message["body"] = new_body
message["edited"] = True message["edited"] = True
connection.cursor().excute(""" connection.execute("""
UPDATE messages SET UPDATE messages SET
body = ? edited = ? body = ?,
WHERE edited = ?
thread_id = ? AND post_id = ? WHERE thread_id = ?
AND post_id = ?
""", (new_body, True, thread_id, post_id)) """, (new_body, True, thread_id, post_id))
connection.commit() connection.commit()
@ -208,7 +203,7 @@ def user_register(connection, user_name, auth_hash):
uuid1().hex, user_name, auth_hash, uuid1().hex, user_name, auth_hash,
"", "", 0, False, time()) "", "", 0, False, time())
connection.cursor().execute(""" connection.execute("""
INSERT INTO users INSERT INTO users
VALUES (?,?,?,?,?,?,?,?) VALUES (?,?,?,?,?,?,?,?)
""", schema_values("user", scheme)) """, schema_values("user", scheme))
@ -226,14 +221,12 @@ def user_resolve(connection, name_or_id, externalize=False, return_false=True):
RETURN_FALSE determines whether to raise an exception or just RETURN_FALSE determines whether to raise an exception or just
return bool False if the user doesn't exist return bool False if the user doesn't exist
""" """
c = connection.cursor() user = connection.execute("""
c.execute("""
SELECT * FROM users SELECT * FROM users
WHERE user_name = ? WHERE user_name = ?
OR user_id = ? OR user_id = ? """,
""", (name_or_id, name_or_id)) (name_or_id, name_or_id)).fetchone()
user = c.fetchone()
if user: if user:
user = schema.user_internal(*user) user = schema.user_internal(*user)
if externalize: if externalize:
@ -265,7 +258,7 @@ def user_update(connection, user_object, parameters):
"user_name", "quip", "auth_hash", "user_name", "quip", "auth_hash",
"bio", "color", "user_id") "bio", "color", "user_id")
connection.cursor().execute(""" connection.execute("""
UPDATE users SET UPDATE users SET
user_name = ?, quip = ?, user_name = ?, quip = ?,
auth_hash = ?, bio = ?, auth_hash = ?, bio = ?,