diff options
-rw-r--r-- | api/auth/login.py | 3 | ||||
-rw-r--r-- | api/game/accept.py | 1 | ||||
-rw-r--r-- | api/game/info.py | 11 | ||||
-rw-r--r-- | api/hierarchy.py | 23 | ||||
-rw-r--r-- | api/readme.md | 5 | ||||
-rw-r--r-- | api/user/avatar.py | 4 | ||||
-rw-r--r-- | api/user/info.py | 47 | ||||
-rw-r--r-- | api/util.py | 6 | ||||
-rw-r--r-- | api/valid.py | 21 |
9 files changed, 58 insertions, 63 deletions
diff --git a/api/auth/login.py b/api/auth/login.py index 94752d9..1d5a4b2 100644 --- a/api/auth/login.py +++ b/api/auth/login.py @@ -15,8 +15,7 @@ def index(): password = data.get("password") or "" # return malformed request if email or password is missing - if not email or \ - not password: + if not email or not password: return "", 400 # resolve user_id from username or email diff --git a/api/game/accept.py b/api/game/accept.py index 5a09df2..bf63c46 100644 --- a/api/game/accept.py +++ b/api/game/accept.py @@ -6,7 +6,6 @@ import json import random from game.socket import game, games from hierarchy import auth_required -from game.info import valid_game_id from socket_io import io from game.new import start_game diff --git a/api/game/info.py b/api/game/info.py index 71fed2e..73c31ff 100644 --- a/api/game/info.py +++ b/api/game/info.py @@ -4,6 +4,7 @@ from db import cursor from user.info import format_user from rating import outcome from ruleset import resolve_ruleset +import valid def format_game(game_id, user_id=None): @@ -56,14 +57,6 @@ def format_game(game_id, user_id=None): } -# check if game_id exists in database -def valid_game_id(game_id): - query = cursor.execute( - "select game_id from games where game_id = ?", [game_id] - ).fetchone() - return bool(query) - - game_info = Blueprint('game_info', __name__) @@ -79,7 +72,7 @@ def index(): token = request.cookies.get("token") or "" if token: user_id = token_login(token) - if not valid_game_id(game_id): return "", 403 + if not valid.game_id(game_id): return "", 403 return format_game(game_id, user_id), 200 diff --git a/api/hierarchy.py b/api/hierarchy.py index 20dcc45..2f85225 100644 --- a/api/hierarchy.py +++ b/api/hierarchy.py @@ -1,7 +1,8 @@ from flask import request from auth.login_token import token_login -from user.info import valid_user_id from db import cursor +from util import all_def, all_notdef +import valid ranks = ["none", "user", "moderator", "admin", "bot"] @@ -19,7 +20,7 @@ def util_two_person(func): data = request.get_json() if data: explicit_id = data.get("id") - if explicit_id and not valid_user_id(explicit_id): explicit_id = None + if explicit_id and not valid.user_id(explicit_id): explicit_id = None return func(token_id, explicit_id) @@ -32,8 +33,7 @@ def util_two_person(func): def two_person(func): @util_two_person def wrapper(token_id, explicit_id): - if not token_id or \ - not explicit_id: + if not all_def([token_id, explicit_id]): return "", 400 return func(token_id, explicit_id) @@ -42,6 +42,21 @@ def two_person(func): return wrapper +# uses json data id with token_login id as fallback +# doesn't check for authentication +# expects that func takes these arguments: (user_id, viewer?) +def one_person(func): + @util_two_person + def wrapper(token_id, explicit_id): + if all_notdef([token_id, explicit_id]): + return "", 400 + + return func(explicit_id or token_id, token_id) + + wrapper.__name__ = func.__name__ + return wrapper + + # @auth_required function decorator (use after @flask.Blueprint.route() decorator) # This decorator only runs endpoint() if token_id from # @util_two_person is not None and passes hierarchy constraints diff --git a/api/readme.md b/api/readme.md index 70d9221..fbaeba1 100644 --- a/api/readme.md +++ b/api/readme.md @@ -83,10 +83,7 @@ API return type classes are mostly defined in api/api.ts <td> ```ts -{ - username?: string, - id?: userID -} +{ id?: userID } ``` </td> diff --git a/api/user/avatar.py b/api/user/avatar.py index b034c3e..eebe52b 100644 --- a/api/user/avatar.py +++ b/api/user/avatar.py @@ -1,10 +1,10 @@ from flask import Blueprint, request, Response from db import cursor from auth.login_token import token_login -from user.info import valid_user_id from hierarchy import auth_required from os.path import exists from codecs import decode +import valid default_avatar = open("database/avatars/default.png", "rb").read() @@ -18,7 +18,7 @@ def get_avatar(): user_id = request.args.get("id") or login if not user_id: return "", 400 - if not valid_user_id(user_id): return "", 403 + if not valid.user_id(user_id): return "", 403 avatar_path = f"database/avatars/{user_id}.png" avatar = "" diff --git a/api/user/info.py b/api/user/info.py index ee20814..3711371 100644 --- a/api/user/info.py +++ b/api/user/info.py @@ -1,23 +1,15 @@ from flask import Blueprint, request from db import cursor -from auth.login_token import token_login from rating import get_rating +from hierarchy import one_person 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) - - # 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() + "(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: @@ -60,9 +52,7 @@ def format_user(user_id, viewer=''): "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) + if viewer: formatted_user["relation"] = get_relation_to(viewer, user_id) return formatted_user @@ -72,34 +62,9 @@ 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']) -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 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 +@one_person +def index(user_id, viewer): user = format_user(user_id, viewer) - return user, 200 diff --git a/api/util.py b/api/util.py new file mode 100644 index 0000000..777820a --- /dev/null +++ b/api/util.py @@ -0,0 +1,6 @@ +def all_def(props): + return all(bool(v) for v in props) + + +def all_notdef(props): + return all(not v for v in props) diff --git a/api/valid.py b/api/valid.py new file mode 100644 index 0000000..f407460 --- /dev/null +++ b/api/valid.py @@ -0,0 +1,21 @@ +from db import cursor + + +def validate(id, type): + types = { + "user": ["user_id", "users"], + "game": ["game_id", "games"], + } + fields = types[type] + query = cursor.execute( + f"select {fields[0]} from {fields[1]} where {fields[0]} = ?", [id] + ).fetchone() + return bool(query) + + +def user_id(user_id): + return validate(user_id, "user") + + +def game_id(game_id): + return validate(game_id, "game") |