aboutsummaryrefslogtreecommitdiff
path: root/api/user
diff options
context:
space:
mode:
Diffstat (limited to 'api/user')
-rw-r--r--api/user/avatar.py37
-rw-r--r--api/user/games.py116
-rw-r--r--api/user/info.py145
-rw-r--r--api/user/password.py13
-rw-r--r--api/user/preferences.py51
-rw-r--r--api/user/status.py20
6 files changed, 221 insertions, 161 deletions
diff --git a/api/user/avatar.py b/api/user/avatar.py
index b4edeed..1b5500a 100644
--- a/api/user/avatar.py
+++ b/api/user/avatar.py
@@ -10,29 +10,34 @@ default_avatar = open("database/avatars/default.png", "rb").read()
avatar = Blueprint('avatar', __name__)
-@avatar.route('/avatar', methods = ["GET"])
+
+@avatar.route('/avatar', methods=["GET"])
def get_avatar():
- token = request.cookies.get("token") or ""
- login = token_login(token) or ""
+ token = request.cookies.get("token") or ""
+ login = token_login(token) or ""
+
+ user_id = request.args.get("id") or login
+ if not user_id: return "", 400
+ if not valid_user_id(user_id): return "", 403
- user_id = request.args.get("id") or login
- if not user_id: return "", 400
- if not valid_user_id(user_id): return "", 403
+ avatar_path = f"database/avatars/{user_id}.png"
+ avatar = ""
+ if exists(avatar_path):
+ avatar = open(avatar_path, "rb").read()
+ return Response(avatar or default_avatar, 200, mimetype="image/png")
- avatar_path = f"database/avatars/{user_id}.png"
- avatar = ""
- if exists(avatar_path):
- avatar = open(avatar_path, "rb").read()
- return Response(avatar or default_avatar, 200, mimetype="image/png")
-@avatar.route('/avatar', methods = ["POST"]) #TODO: pillow image size validation (client side resize)
+@avatar.route(
+ '/avatar', methods=["POST"]
+) #TODO: pillow image size validation (client side resize)
@auth_required("user")
def update_avatar(login):
- if not request.data: return "", 400
+ if not request.data: return "", 400
- open(f"database/avatars/{login}.png", "wb").write(decode(request.data, "base64"))
+ open(f"database/avatars/{login}.png",
+ "wb").write(decode(request.data, "base64"))
- return "", 200
+ return "", 200
-dynamic_route = ["/user", avatar]
+dynamic_route = ["/user", avatar]
diff --git a/api/user/games.py b/api/user/games.py
index 3936566..83d721a 100644
--- a/api/user/games.py
+++ b/api/user/games.py
@@ -8,69 +8,89 @@ from ruleset import resolve_ruleset
from game.info import format_game
import json
+
# get total game outcome amount for user
-def sum_games(user_id): #! SANITIZE USER_ID FIRST
- wld_querys = [' '.join([
- "select count(game_id)",
- "from games",
- "where",
- f"player_{x[0]}_id = \"{user_id}\" and",
- f"outcome = \"{x[1]}\"",
- ]) for x in [(1, "w"), (1, "l"), (2, "w"), (2, "l")]]
- wld_querys.insert(0, ' '.join([
- "select count(game_id)",
- "from games",
- "where",
- f"(player_1_id = \"{user_id}\" or player_2_id = \"{user_id}\") and",
- "outcome = \"d\"",
- ]))
-
- big_query = "select " + ", ".join([f"({query})" for query in wld_querys])
-
- results = cursor.execute(big_query).fetchone()
-
- # win and lose are calculated from user_id's perspective (player_1_id, player_2_id in db)
- return {
- "draw": results[0],
- "win": results[1] + results[4],
- "lose": results[2] + results[3],
- "games": reduce(lambda a, b: a + b, results)
- }
+def sum_games(user_id): #! SANITIZE USER_ID FIRST
+ wld_querys = [
+ ' '.join(
+ [
+ "select count(game_id)",
+ "from games",
+ "where",
+ f"player_{x[0]}_id = \"{user_id}\" and",
+ f"outcome = \"{x[1]}\"",
+ ]
+ ) for x in [(1, "w"), (1, "l"), (2, "w"), (2, "l")]
+ ]
+ wld_querys.insert(
+ 0, ' '.join(
+ [
+ "select count(game_id)",
+ "from games",
+ "where",
+ f"(player_1_id = \"{user_id}\" or player_2_id = \"{user_id}\") and",
+ "outcome = \"d\"",
+ ]
+ )
+ )
+
+ big_query = "select " + ", ".join([f"({query})" for query in wld_querys])
+
+ results = cursor.execute(big_query).fetchone()
+
+ # win and lose are calculated from user_id's perspective (player_1_id, player_2_id in db)
+ return {
+ "draw": results[0],
+ "win": results[1] + results[4],
+ "lose": results[2] + results[3],
+ "games": reduce(lambda a, b: a + b, results)
+ }
+
# get `count` games that `user_id` participated in, sorted by newest game
def fetch_games(user_id, count):
- game_ids = cursor.execute("select game_id from games where player_1_id = ? or player_2_id = ? order by created desc", [user_id, user_id]).fetchmany(count)
- export = []
+ game_ids = cursor.execute(
+ "select game_id from games where player_1_id = ? or player_2_id = ? order by created desc",
+ [user_id, user_id]
+ ).fetchmany(count)
+ export = []
+
+ for game_id in game_ids:
+ export.append(format_game(game_id[0], user_id))
- for game_id in game_ids:
- export.append(format_game(game_id[0], user_id))
+ return export
- return export
games = Blueprint('games', __name__)
-@games.route('/games', methods = ['GET', 'POST'])
+
+@games.route('/games', methods=['GET', 'POST'])
def index():
- data_string = request.data or "{}"
- data = json.loads(data_string)
+ data_string = request.data or "{}"
+ data = json.loads(data_string)
+
+ user_id = data.get("id") or ""
+ token = request.cookies.get("token") or ""
- user_id = data.get("id") or ""
- token = request.cookies.get("token") or ""
+ if not user_id and \
+ not token:
+ return "", 400
- if not user_id and \
- not token:
- return "", 400
+ if token and not user_id:
+ user_id = token_login(token)
- if token and not user_id:
- user_id = token_login(token)
+ if not cursor.execute(
+ "select user_id from users where user_id = ?", [user_id]
+ ).fetchone():
+ return "", 403
- if not cursor.execute("select user_id from users where user_id = ?", [user_id]).fetchone(): return "", 403
+ export = {}
+ merge(
+ export, {"totals": sum_games(user_id)},
+ {"games": fetch_games(user_id, 20)}
+ )
- export = {}
- merge(export,
- {"totals": sum_games(user_id)},
- {"games": fetch_games(user_id, 20)})
+ return export, 200
- return export, 200
dynamic_route = ["/user", games]
diff --git a/api/user/info.py b/api/user/info.py
index be48ef1..de0d2e8 100644
--- a/api/user/info.py
+++ b/api/user/info.py
@@ -4,84 +4,103 @@ from auth.login_token import token_login
from rating import get_rating
import json
+
# check if user_id exists in database
def valid_user_id(user_id):
- query = cursor.execute("select user_id from users where user_id = ?", [user_id]).fetchone()
- return bool(query)
+ query = cursor.execute(
+ "select user_id from users where user_id = ?", [user_id]
+ ).fetchone()
+ return bool(query)
+
# get relation to user_2_id from user_1_id's perspective
def get_relation_to(user_1_id, user_2_id):
- relation = cursor.execute("select * from social where " + \
- "(user_1_id = ? and user_2_id = ?) or " + \
- "(user_1_id = ? and user_2_id = ?)", [user_1_id, user_2_id, user_2_id, user_1_id]).fetchone()
- if not relation: return "none"
- if relation[2] == "friendship": return "friends"
- if relation[2] == "outgoing" and relation[0] == user_1_id: return "outgoing"
- if relation[2] == "outgoing" and relation[1] == user_1_id: return "incoming"
- if relation[2] == "block" and relation[0] == user_1_id: return "blocked"
- return "none"
+ relation = cursor.execute("select * from social where " + \
+ "(user_1_id = ? and user_2_id = ?) or " + \
+ "(user_1_id = ? and user_2_id = ?)", [user_1_id, user_2_id, user_2_id, user_1_id]).fetchone()
+ if not relation: return "none"
+ if relation[2] == "friendship": return "friends"
+ if relation[2] == "outgoing" and relation[0] == user_1_id:
+ return "outgoing"
+ if relation[2] == "outgoing" and relation[1] == user_1_id:
+ return "incoming"
+ if relation[2] == "block" and relation[0] == user_1_id: return "blocked"
+ return "none"
+
# get users friend count
def count_friends(user_id):
- query = cursor.execute("select type from social where (user_1_id = ? or user_2_id = ?) and type = \"friendship\"", [user_id, user_id]).fetchall()
- return len(query) #FIXME: use SQL count() instead of python's len()
+ query = cursor.execute(
+ "select type from social where (user_1_id = ? or user_2_id = ?) and type = \"friendship\"",
+ [user_id, user_id]
+ ).fetchall()
+ return len(query) #FIXME: use SQL count() instead of python's len()
+
# get user/info of `user_id` as `viewer` (id)
-def format_user(user_id, viewer = ''):
- user = cursor.execute("select " + ", ".join([
- "username",
- "user_id",
- "country",
- "registered",
- "status",
- ]) + " from users where user_id = ?", [user_id]).fetchone()
- formatted_user = {
- "username": user[0],
- "id": user[1],
- "country": user[2],
- "registered": user[3],
- "status": user[4],
- "friends": count_friends(user_id),
- "rating": get_rating(user_id), #TODO: calculate rating based on game analysis
- }
- if viewer:
- #FIXME: validate viewer id?
- formatted_user["relation"] = get_relation_to(viewer, user_id)
- return formatted_user
+def format_user(user_id, viewer=''):
+ user = cursor.execute(
+ "select " + ", ".join(
+ [
+ "username",
+ "user_id",
+ "country",
+ "registered",
+ "status",
+ ]
+ ) + " from users where user_id = ?", [user_id]
+ ).fetchone()
+ formatted_user = {
+ "username": user[0],
+ "id": user[1],
+ "country": user[2],
+ "registered": user[3],
+ "status": user[4],
+ "friends": count_friends(user_id),
+ "rating":
+ get_rating(user_id), #TODO: calculate rating based on game analysis
+ }
+ if viewer:
+ #FIXME: validate viewer id?
+ formatted_user["relation"] = get_relation_to(viewer, user_id)
+ return formatted_user
+
info = Blueprint('info', __name__)
+
# view own user/info if no user_id or username is provided and is logged in,
# else view user/info of user with user_id = `user_id` or username = `username`
-@info.route('/info', methods = ['GET', 'POST'])
+@info.route('/info', methods=['GET', 'POST'])
def index():
- data_string = request.data or "{}"
- data = json.loads(data_string)
-
- username = data.get("username") or ""
- user_id = data.get("id") or ""
- token = request.cookies.get("token") or ""
- viewer = ""
-
- if not username and \
- not user_id and \
- not token:
- return "", 400
-
- if username:
- temp_user_id = cursor.execute("select user_id from users where username = ?", [username]).fetchone()
- if len(temp_user_id) > 0: user_id = temp_user_id
-
- if token:
- self_id = token_login(token)
- if not (username or user_id):
- user_id = self_id
- if user_id:
- viewer = self_id
-
- if user_id and not valid_user_id(user_id): return "", 403
- user = format_user(user_id, viewer)
-
- return user, 200
+ data_string = request.data or "{}"
+ data = json.loads(data_string)
+
+ username = data.get("username") or ""
+ user_id = data.get("id") or ""
+ token = request.cookies.get("token") or ""
+ viewer = ""
+
+ if all(not v for v in [username, user_id, token]):
+ return "", 400
+
+ if username:
+ temp_user_id = cursor.execute(
+ "select user_id from users where username = ?", [username]
+ ).fetchone()
+ if len(temp_user_id) > 0: user_id = temp_user_id
+
+ if token:
+ self_id = token_login(token)
+ if not (username or user_id):
+ user_id = self_id
+ if user_id:
+ viewer = self_id
+
+ if user_id and not valid_user_id(user_id): return "", 403
+ user = format_user(user_id, viewer)
+
+ return user, 200
+
dynamic_route = ["/user", info]
diff --git a/api/user/password.py b/api/user/password.py
index 0c1cb70..ff52ba4 100644
--- a/api/user/password.py
+++ b/api/user/password.py
@@ -3,16 +3,17 @@ from db import cursor
password = Blueprint('password', __name__)
+
# this endpoint is unfinished
@password.route('/password')
def index():
- data = request.get_json()
+ data = request.get_json()
- if not data["password"] or \
- not data["newPassword"]:
- return "", 400
+ if not data["password"] or \
+ not data["newPassword"]:
+ return "", 400
- return {}, 200
+ return {}, 200
-dynamic_route = ["/user", password]
+dynamic_route = ["/user", password]
diff --git a/api/user/preferences.py b/api/user/preferences.py
index d4e27c9..2feaade 100644
--- a/api/user/preferences.py
+++ b/api/user/preferences.py
@@ -4,38 +4,49 @@ from ruleset import resolve_ruleset
from hierarchy import auth_required
import json
+
# fill missing dict keys in preferences object
def format_preferences(prefs):
- return {
- "darkMode": prefs.get("darkMode") or False,
- "ruleset": resolve_ruleset(json.dumps(prefs.get("ruleset") or {}) or "default"),
- "userColors": {
- "diskA": prefs.get("userColors", {}).get("diskA") or "",
- "diskB": prefs.get("userColors", {}).get("diskB") or "",
- "background": prefs.get("userColors", {}).get("background") or ""
- }
- }
+ return {
+ "darkMode":
+ prefs.get("darkMode") or False,
+ "ruleset":
+ resolve_ruleset(json.dumps(prefs.get("ruleset") or {}) or "default"),
+ "userColors": {
+ "diskA": prefs.get("userColors", {}).get("diskA") or "",
+ "diskB": prefs.get("userColors", {}).get("diskB") or "",
+ "background": prefs.get("userColors", {}).get("background") or ""
+ }
+ }
+
preferences = Blueprint('preferences', __name__)
-@preferences.route('/preferences', methods = ["GET"])
+
+@preferences.route('/preferences', methods=["GET"])
@auth_required("user")
def get_preferences(login):
- user_prefs = cursor.execute("select preferences from users where user_id = ?", [login]).fetchone()
- return { "preferences": format_preferences(json.loads(user_prefs[0])) }, 200
+ user_prefs = cursor.execute(
+ "select preferences from users where user_id = ?", [login]
+ ).fetchone()
+ return {"preferences": format_preferences(json.loads(user_prefs[0]))}, 200
-@preferences.route('/preferences', methods = ["POST"])
+
+@preferences.route('/preferences', methods=["POST"])
@auth_required("user")
def index(login):
- data = request.get_json()
- new_preferences = data.get("newPreferences") or ""
+ data = request.get_json()
+ new_preferences = data.get("newPreferences") or ""
- formatted_json = format_preferences(new_preferences)
+ formatted_json = format_preferences(new_preferences)
- cursor.execute("update users set preferences = ? where user_id = ?", [json.dumps(formatted_json), login])
- connection.commit()
+ cursor.execute(
+ "update users set preferences = ? where user_id = ?",
+ [json.dumps(formatted_json), login]
+ )
+ connection.commit()
- return "", 200
+ return "", 200
-dynamic_route = ["/user", preferences]
+dynamic_route = ["/user", preferences]
diff --git a/api/user/status.py b/api/user/status.py
index 3adb013..e762d12 100644
--- a/api/user/status.py
+++ b/api/user/status.py
@@ -5,17 +5,21 @@ import json
status = Blueprint('user_status', __name__)
-@status.route('/status', methods = ['POST'])
+
+@status.route('/status', methods=['POST'])
@auth_required("user")
def index(user_id):
- data = request.get_json()
- status = data.get("status") or ""
- if not status: return "", 400
+ data = request.get_json()
+ status = data.get("status") or ""
+ if not status: return "", 400
- cursor.execute("update users set status = ? where user_id = ?", [status[0:200], user_id])
- connection.commit()
+ cursor.execute(
+ "update users set status = ? where user_id = ?",
+ [status[0:200], user_id]
+ )
+ connection.commit()
- return "", 200
+ return "", 200
-dynamic_route = ["/user", status]
+dynamic_route = ["/user", status]