naming/styling changes; change base response schema
This commit is contained in:
		
							parent
							
								
									26b6dc1907
								
							
						
					
					
						commit
						3640d1b1de
					
				
							
								
								
									
										169
									
								
								server.py
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								server.py
									
									
									
									
									
								
							@ -5,66 +5,70 @@ import cherrypy
 | 
			
		||||
import sqlite3
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
dbname = "data.sqlite"
 | 
			
		||||
 | 
			
		||||
dbname = "data.sqlite"
 | 
			
		||||
with sqlite3.connect(dbname) as _c:
 | 
			
		||||
    if not db.user_resolve(_c, "anonymous"):
 | 
			
		||||
        db.user_register(_c, *db.anonymous)
 | 
			
		||||
    db.anon_object = db.user_resolve(_c, "anonymous")
 | 
			
		||||
    if not db.anon_object:
 | 
			
		||||
        db.anon_object = db.user_register(_c, *db.anon_credentials)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# creates a database connection for each thread
 | 
			
		||||
def connect(_):
 | 
			
		||||
def db_connect(_):
 | 
			
		||||
    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
 | 
			
		||||
    standard format for the API, resolves and authorizes users
 | 
			
		||||
    from header data, and prepares thread data to handle the
 | 
			
		||||
    request.
 | 
			
		||||
    from header data, and prepares cherrypy.thread_data so other
 | 
			
		||||
    funtions can handle the request.
 | 
			
		||||
 | 
			
		||||
    In addition, all BBJException's will return their attached
 | 
			
		||||
    schema, and unhandled exceptions return a code 1 error schema.
 | 
			
		||||
    In the body of each api method and all the functions
 | 
			
		||||
    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)
 | 
			
		||||
    def wrapper(*args, **kwargs):
 | 
			
		||||
        headers = cherrypy.request.headers
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
        response = None
 | 
			
		||||
        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:
 | 
			
		||||
            value = e.schema
 | 
			
		||||
            response = e.schema
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -76,8 +80,8 @@ def create_usermap(connection, obj):
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    if isinstance(obj, dict):
 | 
			
		||||
        # this is a message object for a thread, unravel it
 | 
			
		||||
        obj = [value for key, value in obj.items()]
 | 
			
		||||
        # this is a message object for a thread, ditch the keys
 | 
			
		||||
        obj = obj.values()
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        user_id: db.user_resolve(
 | 
			
		||||
@ -114,18 +118,40 @@ APICONFIG = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
    def thread_index(self):
 | 
			
		||||
        threads = db.thread_index(cherrypy.thread_data.db)
 | 
			
		||||
        usermap = create_usermap(cherrypy.thread_data.db, threads)
 | 
			
		||||
        return schema.response({
 | 
			
		||||
            "data": threads,
 | 
			
		||||
            "usermap": usermap
 | 
			
		||||
        })
 | 
			
		||||
        return schema.response(threads, usermap)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @bbjapi
 | 
			
		||||
    @api_method
 | 
			
		||||
    @cherrypy.expose
 | 
			
		||||
    @cherrypy.tools.json_in()
 | 
			
		||||
    def thread_create(self):
 | 
			
		||||
@ -142,27 +168,22 @@ class API(object):
 | 
			
		||||
              cherrypy.thread_data.user
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return schema.response({
 | 
			
		||||
            "data": thread,
 | 
			
		||||
            "usermap": usermap
 | 
			
		||||
        })
 | 
			
		||||
        return schema.response(thread, usermap)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @bbjapi
 | 
			
		||||
    @api_method
 | 
			
		||||
    @cherrypy.expose
 | 
			
		||||
    @cherrypy.tools.json_in()
 | 
			
		||||
    def thread_reply(self):
 | 
			
		||||
        args = cherrypy.request.json
 | 
			
		||||
        validate(args, ["thread_id", "body"])
 | 
			
		||||
        return schema.response({
 | 
			
		||||
            "data": db.thread_reply(
 | 
			
		||||
                cherrypy.thread_data.db,
 | 
			
		||||
                cherrypy.thread_data.user["user_id"],
 | 
			
		||||
                args["thread_id"], args["body"])
 | 
			
		||||
        })
 | 
			
		||||
        return schema.response(db.thread_reply(
 | 
			
		||||
            cherrypy.thread_data.db,
 | 
			
		||||
            cherrypy.thread_data.user["user_id"],
 | 
			
		||||
            args["thread_id"], args["body"]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @bbjapi
 | 
			
		||||
    @api_method
 | 
			
		||||
    @cherrypy.expose
 | 
			
		||||
    @cherrypy.tools.json_in()
 | 
			
		||||
    def thread_load(self):
 | 
			
		||||
@ -177,38 +198,32 @@ class API(object):
 | 
			
		||||
            cherrypy.thread_data.db,
 | 
			
		||||
            thread["messages"])
 | 
			
		||||
 | 
			
		||||
        return schema.response({
 | 
			
		||||
            "data": thread,
 | 
			
		||||
            "usermap": usermap
 | 
			
		||||
        })
 | 
			
		||||
        return schema.response(thread, usermap)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @bbjapi
 | 
			
		||||
    @api_method
 | 
			
		||||
    @cherrypy.expose
 | 
			
		||||
    @cherrypy.tools.json_in()
 | 
			
		||||
    def user_register(self):
 | 
			
		||||
        args = cherrypy.request.json
 | 
			
		||||
        validate(args, ["user_name", "auth_hash"])
 | 
			
		||||
        return schema.response({
 | 
			
		||||
            "data": db.user_register(
 | 
			
		||||
                cherrypy.thread_data.db,
 | 
			
		||||
                args["user_name"], args["auth_hash"])
 | 
			
		||||
        })
 | 
			
		||||
        return schema.response(db.user_register(
 | 
			
		||||
            cherrypy.thread_data.db,
 | 
			
		||||
            args["user_name"],
 | 
			
		||||
            args["auth_hash"]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @bbjapi
 | 
			
		||||
    @api_method
 | 
			
		||||
    @cherrypy.expose
 | 
			
		||||
    @cherrypy.tools.json_in()
 | 
			
		||||
    def edit_query(self):
 | 
			
		||||
        args = cherrypy.request.json
 | 
			
		||||
        validate(args, ["thread_id", "post_id"])
 | 
			
		||||
        return schema.response({
 | 
			
		||||
            "data": message_edit_query(
 | 
			
		||||
                cherrypy.thread_data.db,
 | 
			
		||||
                cherrypy.thread_data.user["user_id"],
 | 
			
		||||
                args["thread_id"],
 | 
			
		||||
                args["post_id"])
 | 
			
		||||
        })
 | 
			
		||||
        return schema.response(message_edit_query(
 | 
			
		||||
            cherrypy.thread_data.db,
 | 
			
		||||
            cherrypy.thread_data.user["user_id"],
 | 
			
		||||
            args["thread_id"],
 | 
			
		||||
            args["post_id"]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								setup.sh
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.sh
									
									
									
									
									
								
							@ -2,7 +2,7 @@
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
if [[ $1 == --init ]]; then
 | 
			
		||||
	sqlite3 bbj.db < schema.sql
 | 
			
		||||
	sqlite3 data.sqlite < schema.sql
 | 
			
		||||
	echo cleared
 | 
			
		||||
	exit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,8 @@ import pickle
 | 
			
		||||
import json
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
anonymous = \
 | 
			
		||||
anon_object = None
 | 
			
		||||
anon_credentials = \
 | 
			
		||||
    ("anonymous",
 | 
			
		||||
     "5430eeed859cad61d925097ec4f53246"
 | 
			
		||||
     "1ccf1ab6b9802b09a313be1478a4d614")
 | 
			
		||||
@ -228,7 +229,7 @@ def user_resolve(connection, name_or_id, externalize=False, return_false=True):
 | 
			
		||||
        return False
 | 
			
		||||
    raise BBJParameterError(
 | 
			
		||||
        "Requested user element ({})"
 | 
			
		||||
        " does not exist".format(name_or_id))
 | 
			
		||||
        " is not registered".format(name_or_id))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def user_update(connection, user_object, parameters):
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,15 @@
 | 
			
		||||
def base():
 | 
			
		||||
    return {
 | 
			
		||||
        "error": False
 | 
			
		||||
        "error": False,
 | 
			
		||||
        "data": None,
 | 
			
		||||
        "usermap": dict()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def response(dictionary):
 | 
			
		||||
def response(data, usermap={}):
 | 
			
		||||
    result = base()
 | 
			
		||||
    result.update(dictionary)
 | 
			
		||||
    result["data"] = data
 | 
			
		||||
    result["usermap"].update(usermap)
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user