social/barkshark_social/routes/frontend.py
2024-04-18 22:36:06 -04:00

133 lines
3.6 KiB
Python

from argon2.exceptions import VerifyMismatchError
from basgi import HttpError, FileResponse, Request, Response, TemplateResponse, router
from blib import HttpDate
from datetime import timedelta
from ..misc import get_resource
@router.get("BarksharkSocial", "/")
async def handle_home(request: Request) -> Response:
if request.state.user is not None:
print(request.state.user.handle)
else:
print("no user")
return TemplateResponse("page/home.haml")
@router.get("BarksharkSocial", "/about")
async def handle_about(request: Request) -> Response:
return TemplateResponse("page/about.haml")
@router.get("BarksharkSocial", "/login")
async def handle_login_get(request: Request) -> Response:
if request.state.user is not None:
host = request.headers.get("Host", request.app.state.config.host)
return Response.new_redirect(f"https://{host}/", 303)
return TemplateResponse("page/login.haml")
@router.post("BarksharkSocial", "/login")
async def handle_login_post(request: Request) -> Response:
state = request.app.state
form = await request.form()
username, password = form.get("username"), form.get("password")
if username in [state.config.host, state.config.web_host, *state.config.alt_hosts, "relay"]:
raise HttpError(400, "User does not exist")
if username is None or password is None:
raise HttpError(400, "Missing username and/or password")
if not isinstance(username, str) or not isinstance(password, str):
raise HttpError(400, "Invalid field type")
with state.database.session(False) as s:
if (user := s.get_user(username.lower())) is None:
raise HttpError(400, "User does not exist")
try:
s.hasher.verify(user.password, password)
except VerifyMismatchError:
raise HttpError(400, "Password does not match")
cookie = s.put_cookie(user, request.headers.get("User-Agent"))
host = request.headers.get("Host", state.config.host)
response = Response.new_redirect(f"https://{host}/", 303)
response.set_cookie(
key = state.config.cookie_name,
value = cookie.code,
same_site = "strict",
expires = HttpDate.new_utc() + timedelta(days = 30),
path = "/",
domain = host,
secure = True
)
return response
@router.get("BarksharkSocial", "/logout")
async def handle_logout_get(request: Request) -> Response:
cname = request.app.state.config.cookie_name
response = Response.new_redirect("/")
try:
cookie = request.cookies[cname]
with request.app.state.database.session(True) as s:
s.del_cookie(cookie.value)
response.delete_cookie(cookie)
except KeyError:
pass
return response
@router.get("BarksharkSocial", "/register")
async def handle_register_get(request: Request) -> Response:
return TemplateResponse("page/login.haml")
@router.get("BarksharkSocial", "/@{username}", "/@{username}@{domain}")
async def handle_user_page(request: Request) -> Response:
with request.app.state.database.session(False) as s:
user = s.get_user(
request.params["username"],
request.params.get("domain", request.app.state.config.host)
)
if user is None or user.id < 1:
raise HttpError(404, "User not found")
context = {
"user": user,
"count": {
"following": s.get_following_count(user),
"followers": s.get_follower_count(user),
"posts": s.get_post_count(user)
}
}
return TemplateResponse("page/user.haml", context)
@router.get("BarksharkSocial", "/style/{filename}.css")
async def handle_style(request: Request) -> Response:
filename = request.params["filename"]
return TemplateResponse(f"style/{filename}.scss", mimetype = "text/css")
@router.get("BarksharkSocial", "/favicon.ico")
async def handle_favicon(request: Request) -> Response:
return FileResponse(get_resource("frontend/static/images/icon.svg"))