+ Damit kein Schabernack getrieben wird müssen wir sicherstellen, dass du die Person bist die jon ausgeführt hat. + Gib unten das Token ein, welches jon beim Starten ausgegeben hat. +
+ +diff --git a/.gitignore b/.gitignore index 8f16228..9a684f2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ __pycache__ *.swp jon/config.json elm-stuff/ +venv/ +.venv/ diff --git a/jon/__init__.py b/jon/__init__.py index 7766f92..78b2a04 100644 --- a/jon/__init__.py +++ b/jon/__init__.py @@ -1,9 +1,11 @@ import inspect import json +import sys from flask import Flask, render_template from . import ( + auth, db, entry, inventory, @@ -21,6 +23,12 @@ def create_app(): db.init_app(app) + # This function denies every request until `auth.ACCESS_TOKEN` + # is passed using `?token=` to authenticate the session. + @app.before_request + def before_req_fun(): + return auth.before_request() + @app.context_processor def utility_processor(): return dict(inspect.getmembers(template_utils, inspect.isfunction)) @@ -28,8 +36,12 @@ def create_app(): app.register_blueprint(location.bp) app.register_blueprint(inventory.bp) app.register_blueprint(entry.bp) + app.register_blueprint(auth.bp) + @app.route("/") def index(): return render_template("index.html") + print(f"Jon started. Token: {auth.ACCESS_TOKEN}", file=sys.stderr) + return app diff --git a/jon/auth.py b/jon/auth.py new file mode 100644 index 0000000..ec97056 --- /dev/null +++ b/jon/auth.py @@ -0,0 +1,41 @@ +import random +import string + +from flask import Blueprint, request, redirect, render_template, session + +bp = Blueprint("auth", __name__, url_prefix="/auth") + + +ACCESS_TOKEN = "".join(random.choice(string.ascii_lowercase) for i in range(64)) + + +ALLOWED_PATHS = [ + "/favicon.ico", + "/static/jon.css" +] + + +def before_request(): + """ + If the correct token query parameter is passed along with any request, + we mark this session authenticated by setting `session["authenticated"]`. + Unless the session is authenticated, all requests result in a 403 FORBIDDEN. + """ + if "token" in request.args: + if request.args["token"] == ACCESS_TOKEN: + session["authenticated"] = () + # Reload the page without query parameters + return redirect(request.path) + + # Don't deny any paths in `ALLOWED_PATHS` + if request.path in ALLOWED_PATHS: + return + + if not "authenticated" in session: + return render_template("auth/denied.html"), 403 + + +@bp.get("/logout") +def logout(): + session.pop("authenticated", None) + return redirect("/") diff --git a/jon/static/jon.css b/jon/static/jon.css new file mode 100644 index 0000000..9897996 --- /dev/null +++ b/jon/static/jon.css @@ -0,0 +1,65 @@ +html { + font-family: Helvetica, sans-serif; +} +h1 { + margin: 0; +} +nav > ul { + padding-left: 0; +} +nav > ul > li { + display: inline-block; + list-style: none; +} +nav > ul > li + li:before { + content: ' · '; +} +.current-page > a { + position: relative; +} +.current-page > a:after { + content: '↓'; + font-size: 0.8em; + box-sizing: border-box; + position: absolute; + display: block; + right: 50%; + top: -1em; + width: 1em; + text-align: center; + margin-right: -0.5em; + animation: wiggle 0.8s ease-in-out 0s infinite; + /* animation-direction: alternate; */ +} +.--align-left { + text-align: left; +} +.--align-right { + text-align: right; +} +.--centered { + text-align: center; +} +@keyframes wiggle { + 0%, 100% { margin-top: 0; } + 50% { margin-top: -0.5em; } + /* 100% { transform: rotate(1turn); } */ +} +table { + border-spacing: .5em 0; +} +th { + font-size: .8em; +} +@media print { + body { + font-size: 8px; + } +} +.form-input > label { + font-size: .8em; +} +.form-input > input:not([type=radio]), +.form-input > select { + display: block; +} diff --git a/jon/templates/auth/denied.html b/jon/templates/auth/denied.html new file mode 100644 index 0000000..1122b1b --- /dev/null +++ b/jon/templates/auth/denied.html @@ -0,0 +1,36 @@ + + + +
+ +config
{% for key, value in config.items() %}{{ key }} = {{ value }} +{% endfor %}+
+ Damit kein Schabernack getrieben wird müssen wir sicherstellen, dass du die Person bist die jon ausgeführt hat. + Gib unten das Token ein, welches jon beim Starten ausgegeben hat. +
+ +