naming/styling changes; change base response schema
parent
26b6dc1907
commit
3640d1b1de
169
server.py
169
server.py
|
@ -5,66 +5,70 @@ import cherrypy
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import json
|
import json
|
||||||
|
|
||||||
dbname = "data.sqlite"
|
|
||||||
|
|
||||||
|
dbname = "data.sqlite"
|
||||||
with sqlite3.connect(dbname) as _c:
|
with sqlite3.connect(dbname) as _c:
|
||||||
if not db.user_resolve(_c, "anonymous"):
|
db.anon_object = db.user_resolve(_c, "anonymous")
|
||||||
db.user_register(_c, *db.anonymous)
|
if not db.anon_object:
|
||||||
|
db.anon_object = db.user_register(_c, *db.anon_credentials)
|
||||||
|
|
||||||
|
|
||||||
# creates a database connection for each thread
|
# creates a database connection for each thread
|
||||||
def connect(_):
|
def db_connect(_):
|
||||||
cherrypy.thread_data.db = sqlite3.connect(dbname)
|
cherrypy.thread_data.db = sqlite3.connect(dbname)
|
||||||
cherrypy.engine.subscribe('start_thread', connect)
|
cherrypy.engine.subscribe('start_thread', db_connect)
|
||||||
|
|
||||||
|
|
||||||
def bbjapi(function):
|
def api_method(function):
|
||||||
"""
|
"""
|
||||||
A wrapper that handles encoding of objects and errors to a
|
A wrapper that handles encoding of objects and errors to a
|
||||||
standard format for the API, resolves and authorizes users
|
standard format for the API, resolves and authorizes users
|
||||||
from header data, and prepares thread data to handle the
|
from header data, and prepares cherrypy.thread_data so other
|
||||||
request.
|
funtions can handle the request.
|
||||||
|
|
||||||
In addition, all BBJException's will return their attached
|
In the body of each api method and all the functions
|
||||||
schema, and unhandled exceptions return a code 1 error schema.
|
they utilize, BBJExceptions are caught and their attached
|
||||||
|
schema is dispatched to the client. All other unhandled
|
||||||
|
exceptions will throw a code 1 back at the client and log
|
||||||
|
it for inspection.
|
||||||
"""
|
"""
|
||||||
@wraps(function)
|
@wraps(function)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
headers = cherrypy.request.headers
|
response = None
|
||||||
username = headers.get("User")
|
|
||||||
auth = headers.get("Auth")
|
|
||||||
anon = False
|
|
||||||
|
|
||||||
if not username and not auth:
|
|
||||||
user = db.user_resolve(cherrypy.thread_data.db, "anonymous")
|
|
||||||
anon = True
|
|
||||||
elif not username or not auth:
|
|
||||||
return json.dumps(schema.error(5,
|
|
||||||
"User or Auth was given without the other."))
|
|
||||||
|
|
||||||
if not anon:
|
|
||||||
user = db.user_resolve(cherrypy.thread_data.db, username)
|
|
||||||
if not user:
|
|
||||||
return json.dumps(schema.error(4,
|
|
||||||
"Username is not registered."))
|
|
||||||
|
|
||||||
elif auth != user["auth_hash"]:
|
|
||||||
return json.dumps(schema.error(5,
|
|
||||||
"Invalid authorization key for user."))
|
|
||||||
|
|
||||||
cherrypy.thread_data.user = user
|
|
||||||
cherrypy.thread_data.anon = anon
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = function(*args, **kwargs)
|
username = cherrypy.request.headers.get("User")
|
||||||
|
auth = cherrypy.request.headers.get("Auth")
|
||||||
|
anon = False
|
||||||
|
|
||||||
|
if not username and not auth:
|
||||||
|
user = db.anon_object
|
||||||
|
anon = True
|
||||||
|
elif not username or not auth:
|
||||||
|
return json.dumps(schema.error(5,
|
||||||
|
"User or Auth was given without the other."))
|
||||||
|
|
||||||
|
if not anon:
|
||||||
|
user = db.user_resolve(cherrypy.thread_data.db, username)
|
||||||
|
if auth != user["auth_hash"]:
|
||||||
|
return json.dumps(schema.error(5,
|
||||||
|
"Invalid authorization key for user."))
|
||||||
|
|
||||||
|
cherrypy.thread_data.user = user
|
||||||
|
cherrypy.thread_data.anon = anon
|
||||||
|
response = function(*args, **kwargs)
|
||||||
|
|
||||||
except BBJException as e:
|
except BBJException as e:
|
||||||
value = e.schema
|
response = e.schema
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
value = schema.error(1, str(e))
|
response = schema.error(1, repr(e))
|
||||||
|
# TODO: use a logging file or module or something
|
||||||
|
# repr() in this case is more verbose than just passing it in
|
||||||
|
print(repr(e))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
return json.dumps(response)
|
||||||
|
|
||||||
return json.dumps(value)
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,8 +80,8 @@ def create_usermap(connection, obj):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
# this is a message object for a thread, unravel it
|
# this is a message object for a thread, ditch the keys
|
||||||
obj = [value for key, value in obj.items()]
|
obj = obj.values()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user_id: db.user_resolve(
|
user_id: db.user_resolve(
|
||||||
|
@ -114,18 +118,40 @@ APICONFIG = {
|
||||||
}
|
}
|
||||||
|
|
||||||
class API(object):
|
class API(object):
|
||||||
@bbjapi
|
@api_method
|
||||||
|
@cherrypy.expose
|
||||||
|
def get_me(self):
|
||||||
|
"""
|
||||||
|
Requires no arguments. Returns your internal user object,
|
||||||
|
including your authorization hash.
|
||||||
|
"""
|
||||||
|
return schema.response(cherrypy.thread_data.user)
|
||||||
|
|
||||||
|
@api_method
|
||||||
|
@cherrypy.expose
|
||||||
|
def user_get(self):
|
||||||
|
"""
|
||||||
|
Retreive an external user object for the given `user`.
|
||||||
|
Can be a user_id or user_name.
|
||||||
|
"""
|
||||||
|
args = cherrypy.request.json
|
||||||
|
validate(["user"])
|
||||||
|
return schema.response(db.user_resolve(
|
||||||
|
cherrypy.thread_data.db,
|
||||||
|
args["user"],
|
||||||
|
return_false=False,
|
||||||
|
externalize=True))
|
||||||
|
|
||||||
|
|
||||||
|
@api_method
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def thread_index(self):
|
def thread_index(self):
|
||||||
threads = db.thread_index(cherrypy.thread_data.db)
|
threads = db.thread_index(cherrypy.thread_data.db)
|
||||||
usermap = create_usermap(cherrypy.thread_data.db, threads)
|
usermap = create_usermap(cherrypy.thread_data.db, threads)
|
||||||
return schema.response({
|
return schema.response(threads, usermap)
|
||||||
"data": threads,
|
|
||||||
"usermap": usermap
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@bbjapi
|
@api_method
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_in()
|
@cherrypy.tools.json_in()
|
||||||
def thread_create(self):
|
def thread_create(self):
|
||||||
|
@ -142,27 +168,22 @@ class API(object):
|
||||||
cherrypy.thread_data.user
|
cherrypy.thread_data.user
|
||||||
}
|
}
|
||||||
|
|
||||||
return schema.response({
|
return schema.response(thread, usermap)
|
||||||
"data": thread,
|
|
||||||
"usermap": usermap
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@bbjapi
|
@api_method
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_in()
|
@cherrypy.tools.json_in()
|
||||||
def thread_reply(self):
|
def thread_reply(self):
|
||||||
args = cherrypy.request.json
|
args = cherrypy.request.json
|
||||||
validate(args, ["thread_id", "body"])
|
validate(args, ["thread_id", "body"])
|
||||||
return schema.response({
|
return schema.response(db.thread_reply(
|
||||||
"data": db.thread_reply(
|
cherrypy.thread_data.db,
|
||||||
cherrypy.thread_data.db,
|
cherrypy.thread_data.user["user_id"],
|
||||||
cherrypy.thread_data.user["user_id"],
|
args["thread_id"], args["body"]))
|
||||||
args["thread_id"], args["body"])
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@bbjapi
|
@api_method
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_in()
|
@cherrypy.tools.json_in()
|
||||||
def thread_load(self):
|
def thread_load(self):
|
||||||
|
@ -177,38 +198,32 @@ class API(object):
|
||||||
cherrypy.thread_data.db,
|
cherrypy.thread_data.db,
|
||||||
thread["messages"])
|
thread["messages"])
|
||||||
|
|
||||||
return schema.response({
|
return schema.response(thread, usermap)
|
||||||
"data": thread,
|
|
||||||
"usermap": usermap
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@bbjapi
|
@api_method
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_in()
|
@cherrypy.tools.json_in()
|
||||||
def user_register(self):
|
def user_register(self):
|
||||||
args = cherrypy.request.json
|
args = cherrypy.request.json
|
||||||
validate(args, ["user_name", "auth_hash"])
|
validate(args, ["user_name", "auth_hash"])
|
||||||
return schema.response({
|
return schema.response(db.user_register(
|
||||||
"data": db.user_register(
|
cherrypy.thread_data.db,
|
||||||
cherrypy.thread_data.db,
|
args["user_name"],
|
||||||
args["user_name"], args["auth_hash"])
|
args["auth_hash"]))
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@bbjapi
|
@api_method
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_in()
|
@cherrypy.tools.json_in()
|
||||||
def edit_query(self):
|
def edit_query(self):
|
||||||
args = cherrypy.request.json
|
args = cherrypy.request.json
|
||||||
validate(args, ["thread_id", "post_id"])
|
validate(args, ["thread_id", "post_id"])
|
||||||
return schema.response({
|
return schema.response(message_edit_query(
|
||||||
"data": message_edit_query(
|
cherrypy.thread_data.db,
|
||||||
cherrypy.thread_data.db,
|
cherrypy.thread_data.user["user_id"],
|
||||||
cherrypy.thread_data.user["user_id"],
|
args["thread_id"],
|
||||||
args["thread_id"],
|
args["post_id"]))
|
||||||
args["post_id"])
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2
setup.sh
2
setup.sh
|
@ -2,7 +2,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [[ $1 == --init ]]; then
|
if [[ $1 == --init ]]; then
|
||||||
sqlite3 bbj.db < schema.sql
|
sqlite3 data.sqlite < schema.sql
|
||||||
echo cleared
|
echo cleared
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -25,7 +25,8 @@ import pickle
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
anonymous = \
|
anon_object = None
|
||||||
|
anon_credentials = \
|
||||||
("anonymous",
|
("anonymous",
|
||||||
"5430eeed859cad61d925097ec4f53246"
|
"5430eeed859cad61d925097ec4f53246"
|
||||||
"1ccf1ab6b9802b09a313be1478a4d614")
|
"1ccf1ab6b9802b09a313be1478a4d614")
|
||||||
|
@ -228,7 +229,7 @@ def user_resolve(connection, name_or_id, externalize=False, return_false=True):
|
||||||
return False
|
return False
|
||||||
raise BBJParameterError(
|
raise BBJParameterError(
|
||||||
"Requested user element ({})"
|
"Requested user element ({})"
|
||||||
" does not exist".format(name_or_id))
|
" is not registered".format(name_or_id))
|
||||||
|
|
||||||
|
|
||||||
def user_update(connection, user_object, parameters):
|
def user_update(connection, user_object, parameters):
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
def base():
|
def base():
|
||||||
return {
|
return {
|
||||||
"error": False
|
"error": False,
|
||||||
|
"data": None,
|
||||||
|
"usermap": dict()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def response(dictionary):
|
def response(data, usermap={}):
|
||||||
result = base()
|
result = base()
|
||||||
result.update(dictionary)
|
result["data"] = data
|
||||||
|
result["usermap"].update(usermap)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue