aboutsummaryrefslogtreecommitdiff
path: root/api
diff options
context:
space:
mode:
authorlonkaars <l.leblansch@gmail.com>2021-04-15 15:14:44 +0200
committerlonkaars <l.leblansch@gmail.com>2021-04-15 15:14:44 +0200
commitcc53f217f6122151bcae131a42da8f8887f8560d (patch)
tree2d09b9fd3758cecc00626c8aac31510dee7a37af /api
parentc5f71bc38772dedb033258416e0cd722f7b9e7af (diff)
new valid and util module, more function decorators
Diffstat (limited to 'api')
-rw-r--r--api/auth/login.py3
-rw-r--r--api/game/accept.py1
-rw-r--r--api/game/info.py11
-rw-r--r--api/hierarchy.py23
-rw-r--r--api/readme.md5
-rw-r--r--api/user/avatar.py4
-rw-r--r--api/user/info.py47
-rw-r--r--api/util.py6
-rw-r--r--api/valid.py21
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")