feat: add annotations about functionalities of some endpoints
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# API is expected to return:
|
# API is expected to return a tuple of:
|
||||||
# - HTTP status code,
|
# - HTTP status code,
|
||||||
# - human-readable status message,
|
# - human-readable status message,
|
||||||
# - json with appropriate data
|
# - json with appropriate data
|
||||||
@@ -11,6 +11,14 @@ import lewy_db as ldb
|
|||||||
import lewy_globals
|
import lewy_globals
|
||||||
|
|
||||||
def require_authentication(func):
|
def require_authentication(func):
|
||||||
|
"""
|
||||||
|
Ten dekorator służy do wymuszenia parametru "token"
|
||||||
|
podczas obsługi zapytania. Powinien on zostać doklejony
|
||||||
|
do żądania, np. /api/v1/halt?token=XXX...
|
||||||
|
Wartość tokenu jest pobierana z pola api_key w config.toml.
|
||||||
|
Jeżeli skrypt jej tam nie znajdzie, jest generowana losowo
|
||||||
|
na starcie i drukowana w terminalu.
|
||||||
|
"""
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
token = kwargs["r"].args.get('token')
|
token = kwargs["r"].args.get('token')
|
||||||
@@ -26,19 +34,44 @@ def require_authentication(func):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
def increment_bad_requests():
|
def increment_bad_requests():
|
||||||
|
"""
|
||||||
|
Zwiększa globalny, tymczasowy licznik nieprawidłowych zapytań.
|
||||||
|
"""
|
||||||
lewy_globals.apiFailedRequests += 1
|
lewy_globals.apiFailedRequests += 1
|
||||||
|
|
||||||
def not_implemented(data):
|
def not_implemented(data):
|
||||||
|
"""
|
||||||
|
Zwraca kod 501 wraz z endpointem, który wywołał błąd.
|
||||||
|
|
||||||
|
:param data: Ścieżka zapytania
|
||||||
|
:type data: list
|
||||||
|
"""
|
||||||
# TODO: change list to string -> data, not data[0]
|
# TODO: change list to string -> data, not data[0]
|
||||||
return 501, f"not recognised/implemented: {data[0]}", []
|
return 501, f"not recognised/implemented: {data[0]}", []
|
||||||
|
|
||||||
|
# GET /api/v1
|
||||||
def stub_hello():
|
def stub_hello():
|
||||||
|
"""
|
||||||
|
Prosta funkcja witająca użytkowników w /api/v1
|
||||||
|
"""
|
||||||
return 200, 'hello from v1! stats are at /api/v1/stats', []
|
return 200, 'hello from v1! stats are at /api/v1/stats', []
|
||||||
|
|
||||||
def epoch_to_date(epoch):
|
def epoch_to_date(epoch):
|
||||||
|
"""
|
||||||
|
Zamienia Unix'owy epoch na lokalny czas,
|
||||||
|
w formacie przypominającym format ISO.
|
||||||
|
|
||||||
|
:param epoch: Epoch - sekundy po 1. stycznia 1970
|
||||||
|
:type epoch: int
|
||||||
|
"""
|
||||||
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(epoch))
|
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(epoch))
|
||||||
|
|
||||||
|
# GET /api/v1/
|
||||||
|
# GET /api/v1/stats
|
||||||
def stats():
|
def stats():
|
||||||
|
"""
|
||||||
|
Zwraca ogólne statystyki serwera.
|
||||||
|
"""
|
||||||
data_to_send = {
|
data_to_send = {
|
||||||
"start_time": lewy_globals.starttime,
|
"start_time": lewy_globals.starttime,
|
||||||
"uptime": lewy_globals.getUptime(),
|
"uptime": lewy_globals.getUptime(),
|
||||||
@@ -50,11 +83,20 @@ def stats():
|
|||||||
}
|
}
|
||||||
return 200, "ok", data_to_send
|
return 200, "ok", data_to_send
|
||||||
|
|
||||||
def get_matches():
|
# GET /api/v1/matches
|
||||||
|
def get_matches(r):
|
||||||
|
"""
|
||||||
|
TODO: Zwraca mecze.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# GET /api/v1/debugger_halt?token=XXX...
|
||||||
@require_authentication
|
@require_authentication
|
||||||
def debugger_halt(r):
|
def debugger_halt(r):
|
||||||
|
"""
|
||||||
|
Zatrzymuje wykonywanie skryptu, aby pozwolić
|
||||||
|
administratorowi na wykonywanie dowolnego polecenia z konsoli.
|
||||||
|
"""
|
||||||
if lewy_globals.config['general']['is_proxied']:
|
if lewy_globals.config['general']['is_proxied']:
|
||||||
print(f"{c.WARNING}[{epoch_to_date(time.time())}]{c.ENDC} {r.headers['X-Forwarded-For']} triggered a debugger halt!")
|
print(f"{c.WARNING}[{epoch_to_date(time.time())}]{c.ENDC} {r.headers['X-Forwarded-For']} triggered a debugger halt!")
|
||||||
else:
|
else:
|
||||||
@@ -63,6 +105,16 @@ def debugger_halt(r):
|
|||||||
return 200, "ok", []
|
return 200, "ok", []
|
||||||
|
|
||||||
def lookup(data, request):
|
def lookup(data, request):
|
||||||
|
"""
|
||||||
|
Obsługuje zapytania zwrócone do /api/v1/...
|
||||||
|
|
||||||
|
:param data: Lista ze ścieżką zapytania
|
||||||
|
:type data: list
|
||||||
|
:param request: Zapytanie
|
||||||
|
:type request: flask.request
|
||||||
|
|
||||||
|
:returns: Wartość zwróconą przez którąś z przywołanych funkcji.
|
||||||
|
"""
|
||||||
if data == []:
|
if data == []:
|
||||||
return stub_hello()
|
return stub_hello()
|
||||||
match data[0].lower():
|
match data[0].lower():
|
||||||
@@ -74,6 +126,8 @@ def lookup(data, request):
|
|||||||
return stub_hello()
|
return stub_hello()
|
||||||
case 'halt':
|
case 'halt':
|
||||||
return debugger_halt(r = request)
|
return debugger_halt(r = request)
|
||||||
|
case 'matches':
|
||||||
|
get_matches(r = request)
|
||||||
case _:
|
case _:
|
||||||
increment_bad_requests()
|
increment_bad_requests()
|
||||||
return not_implemented(data)
|
return not_implemented(data)
|
||||||
@@ -29,7 +29,7 @@ def safeTraverse(obj: dict, path: list, default=None):
|
|||||||
finally:
|
finally:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def getCommit():
|
def getCommit() -> str | None:
|
||||||
try:
|
try:
|
||||||
return Repo(search_parent_directories=True).head.object.hexsha
|
return Repo(search_parent_directories=True).head.object.hexsha
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -65,7 +65,7 @@ def ensureRandomlyGeneratedPassword():
|
|||||||
print(f"{colors.WARNING}WARNING{colors.ENDC}: Default config populated with one-time, insecure pseudorandom API key: {colors.OKCYAN}{randomly_generated_passcode}{colors.ENDC}.\n"
|
print(f"{colors.WARNING}WARNING{colors.ENDC}: Default config populated with one-time, insecure pseudorandom API key: {colors.OKCYAN}{randomly_generated_passcode}{colors.ENDC}.\n"
|
||||||
f" The API key is not the Flask debugger PIN. You need to provide a config file for persistence!{colors.ENDL}")
|
f" The API key is not the Flask debugger PIN. You need to provide a config file for persistence!{colors.ENDL}")
|
||||||
|
|
||||||
def getConfig(configfile):
|
def getConfig(configfile: str) -> dict:
|
||||||
global randomly_generated_passcode
|
global randomly_generated_passcode
|
||||||
|
|
||||||
if not os.path.exists(configfile):
|
if not os.path.exists(configfile):
|
||||||
@@ -82,15 +82,26 @@ def getConfig(configfile):
|
|||||||
else:
|
else:
|
||||||
return toml.load(configfile)
|
return toml.load(configfile)
|
||||||
|
|
||||||
def setupDb(app, config):
|
def setupDb(app, config) -> lewy_db.baza:
|
||||||
global db
|
global db
|
||||||
db = lewy_db.baza(app, config)
|
db = lewy_db.baza(app, config)
|
||||||
return db
|
return db
|
||||||
|
|
||||||
def getDb():
|
def getDb() -> lewy_db.baza:
|
||||||
|
"""
|
||||||
|
Akcesor dla wrappera bazy danych wspólnego dla całego projektu
|
||||||
|
(klasy baza z lewy_db)
|
||||||
|
"""
|
||||||
return db
|
return db
|
||||||
|
|
||||||
def setConfig(configfile):
|
def setConfig(configfile):
|
||||||
|
"""
|
||||||
|
Zapewnia, że konfiguracja nie jest pusta,
|
||||||
|
nawet, gdy sam plik jest pusty.
|
||||||
|
|
||||||
|
:param configfile: Ścieżka do pliku
|
||||||
|
:type configfile: str
|
||||||
|
"""
|
||||||
global config
|
global config
|
||||||
config = getConfig(configfile)
|
config = getConfig(configfile)
|
||||||
|
|
||||||
@@ -100,6 +111,11 @@ def setConfig(configfile):
|
|||||||
|
|
||||||
|
|
||||||
def getHeaders():
|
def getHeaders():
|
||||||
|
"""
|
||||||
|
Zwraca hardkodowane nagłówki do scrapowania, bądź te,
|
||||||
|
z config.toml (o ile użytkownik jakieś podał).
|
||||||
|
"""
|
||||||
|
|
||||||
# NOTE: use ESR user-agent
|
# NOTE: use ESR user-agent
|
||||||
# user_agent = 'Mozilla/5.0 (Windows NT 10.0; rv:130.0) Gecko/20100101 Firefox/130.0'
|
# user_agent = 'Mozilla/5.0 (Windows NT 10.0; rv:130.0) Gecko/20100101 Firefox/130.0'
|
||||||
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0'
|
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0'
|
||||||
@@ -110,10 +126,18 @@ def getHeaders():
|
|||||||
return user_agent
|
return user_agent
|
||||||
|
|
||||||
def getUptime():
|
def getUptime():
|
||||||
|
"""
|
||||||
|
Zwraca informację o czasie działania serwera.
|
||||||
|
"""
|
||||||
return int(time.time()) - starttime
|
return int(time.time()) - starttime
|
||||||
|
|
||||||
def extractIpAndPortFromPublicUrl() -> tuple:
|
def extractIpAndPortFromPublicUrl() -> tuple:
|
||||||
|
|
||||||
|
"""
|
||||||
|
Pobiera dane z konfiguracji i zwraca
|
||||||
|
krotkę: adres IP i port.
|
||||||
|
"""
|
||||||
|
|
||||||
ip, port = "127.0.0.1", "5000"
|
ip, port = "127.0.0.1", "5000"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user