#!/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")