Files
purplebored.pl/src/pbpl/views/home.py
2025-10-23 20:38:04 +03:00

98 lines
2.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Home routes"""
import typing as t
import flask
from werkzeug.wrappers import Response
import pbpl.forms.prow as form_pow
import pbpl.forms.text as text_form
from pbpl.db import db
from pbpl.models import TextModel
from .bp import Bp
home: Bp = Bp("home", __name__)
__all__: t.Tuple[str] = ("home",)
@home.get("/", ishtml=True)
@home.csp("img-src $self; script-src $internal $wasm; style-src $internal; form-action $self; connect-src $self; manifest-src $self")
def index() -> str:
"""Home page"""
nonce: str = form_pow.proof_of_work_protect_session("home.index/text")
return flask.render_template(
"home/index.j2",
form=text_form.TextForm(),
texts=TextModel.query.all(),
pow_nonce=nonce,
)
@home.post("/")
@home.csp("img-src $self; script-src $internal; style-src $internal")
def text() -> Response:
"""Post some text"""
form: text_form.FlaskForm = text_form.TextForm()
if not form.validate_on_submit(): # type: ignore
flask.flash("Invalid form data/form", "error")
flask.abort(400)
if form.text.data is None:
flask.flash("Invalid form text", "error")
flask.abort(400)
if form.pow_solution.data is None or not form_pow.proof_of_work_verify_session(
"home.index/text",
form.pow_solution.data,
):
flask.flash("Invalid Proof-of-Work solution", "error")
flask.abort(403)
db.session.add(TextModel(text=form.text.data))
db.session.commit()
flask.flash("Your text has been saved")
return flask.redirect(flask.url_for("home.index"))
@home.get("/manifest.json")
@home.csp("manifest-src $self; img-src $self")
@home.cache("30d")
def manifest() -> t.Any:
"""Manifest file"""
return flask.jsonify( # type: ignore
{
"$schema": "https://json.schemastore.org/web-manifest-combined.json",
"short_name": "Example page",
"name": "Example page",
"description": "This is an example description",
"icons": [
{
"src": "/favicon.ico",
"sizes": "256x256",
"type": "image/vnd.microsoft.icon",
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#fbfbfb",
"background_color": "#121212",
}
)
@home.get("/favicon.ico")
@home.csp("img-src $self")
@home.cache("30d")
def favicon() -> Response:
"""Website icon"""
return flask.send_from_directory("static", "favicon.ico")