nomadnet-website/pages/hswro.py

141 lines
3.9 KiB
Python
Executable File

#!/usr/bin/env python3
from os import environ
from typing import Optional, Tuple
from datetime import datetime
from redis import Redis
from hashlib import sha256
from functools import reduce
s = datetime.now()
NO_REMOTE_IDENTITY_MSG = """User identity hash not available.
In MeshChat: use the fingerprint button in the top right to send the identification information.
In NomadNet: Save node, click on it, go to <Info> and select "Identify when connecting"."""
FORBIDDEN_INPUT = [
"[",
"`",
"\n"
]
MENU_ITEMS = [
("Home", "/page/index.mu]"),
("Status", "/page/status.mu"),
("Shoutbox", "/page/chat.mu"),
("Library", "/page/library.mu")
]
ADMIN_IDENTITIES = [
"e6c72573bb91d48338dbcc57d0223b81",
"70c9608c9a0f4ae895f7fab406554e1c"
]
BGCOLOR = "`F333`BDDD"
MENUBGCOLOR = "`FEEE`B333"
def is_admin() -> bool:
remote_identity = environ.get("remote_identity", None)
if remote_identity is None:
return False
return remote_identity in ADMIN_IDENTITIES
def sanitize_input(text: str) -> str:
return reduce(lambda a, b: a.replace(b, ""), FORBIDDEN_INPUT, text)
def check_password(password: str) -> bool:
expected = '34a77e61000b2ba1f56201332ef64d93f9cdc60e63ab48bc255102586ef7e592'
gotten = sha256(f"hswrosalt{password}".encode('utf-8'), usedforsecurity=True).hexdigest()
return expected == gotten
def check_name(username: str) -> bool:
if len(username) >= 16:
return False
return all(map(lambda c: c.isalnum(), username))
def get_login_info() -> Tuple[Optional[str], Optional[str]]:
"""Returns [login_name, error]"""
remote_identity = environ.get("remote_identity", None)
if remote_identity is None:
return (None, NO_REMOTE_IDENTITY_MSG)
r = Redis(host='localhost', port=6379, db=0)
login = r.get(f'login_info_{remote_identity}')
if login is None:
return (None, None)
return (login.decode('utf-8'), None)
def login(username: str) -> Optional[str]:
"""Returns err"""
remote_identity = environ.get("remote_identity", None)
if remote_identity is None:
return NO_REMOTE_IDENTITY_MSG
if not check_name(username):
return "Username should only contain alphanumeric characters and have at most 16 characters."
r = Redis(host='localhost', port=6379, db=0)
r.set(f'login_info_{remote_identity}', username)
return None
def logout():
remote_identity = environ.get("remote_identity", None)
if remote_identity is None:
return
r = Redis(host='localhost', port=6379, db=0)
r.delete(f'login_info_{remote_identity}')
def login_button() -> str:
l = get_login_info()
if l[0] is None:
return "[`[Identify`:/page/login.mu`]]"
else:
return f"Welcome, {l[0]} | [`[Forget`:/page/logout.mu`]]"
def render_menu_item(active_title: Optional[str]) -> str:
def f(current: Tuple[str, str]) -> str:
current_title = current[0]
href = current[1]
retval = " "
if current_title == active_title:
retval += "`!"
retval += f"`[{current_title}`:{href}`]"
if current_title == active_title:
retval += "`!"
return retval + " "
return f
def render_menu(title: Optional[str] = None) -> str:
LEFT_MARGIN = 2
retval = "\n`l" + " "*LEFT_MARGIN
retval += "".join(map(render_menu_item(title), MENU_ITEMS))
retval += "\n"
return retval
def header(title: Optional[str] = None):
ftitle = ""
if title is not None:
ftitle = ": `i" + title
print(f"""`F000`BFB1
`c
`r {login_button()}
`l `!Hackerspace`!Wrocław{ftitle}
`a
`a
``
{MENUBGCOLOR}
`c
{render_menu(title)}
{BGCOLOR}""")
def reset_colors() -> str:
print(BGCOLOR)
def footer():
print(f"\n{BGCOLOR}`r Rendered in: {(datetime.now()-s).total_seconds()}s")
print(f"{datetime.now()}")
if __name__ == "__main__":
pass