Add PunktFri Flask landing page
- Landing page with hero, problemet, målgruppe, idé, disclaimer sections - Signup form → SQLite + file log (navn, email, domæner, egne_ns, kommentar) - /tak confirmation page - /admin with HTTP Basic Auth - /health endpoint - Mobile-first minimal CSS, Danish throughout - Honest 'under undersøgelse' framing — no premature organisational claims
This commit is contained in:
137
app.py
Normal file
137
app.py
Normal file
@@ -0,0 +1,137 @@
|
||||
import os
|
||||
import logging
|
||||
import sqlite3
|
||||
from functools import wraps
|
||||
|
||||
from flask import Flask, render_template, request, redirect, url_for, g, Response
|
||||
|
||||
DATABASE = os.environ.get("DATABASE", "punktfri.db")
|
||||
LOG_FILE = os.environ.get("LOG_FILE", "signups.log")
|
||||
ADMIN_USER = os.environ.get("ADMIN_USER", "admin")
|
||||
ADMIN_PASS = os.environ.get("ADMIN_PASS", "punktfri2024")
|
||||
PORT = int(os.environ.get("PORT", 5000))
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
signup_logger = logging.getLogger("signups")
|
||||
signup_logger.setLevel(logging.INFO)
|
||||
_fh = logging.FileHandler(LOG_FILE)
|
||||
_fh.setFormatter(logging.Formatter("%(asctime)s %(message)s"))
|
||||
signup_logger.addHandler(_fh)
|
||||
|
||||
|
||||
def get_db():
|
||||
db = getattr(g, "_database", None)
|
||||
if db is None:
|
||||
db = g._database = sqlite3.connect(DATABASE)
|
||||
db.row_factory = sqlite3.Row
|
||||
return db
|
||||
|
||||
|
||||
@app.teardown_appcontext
|
||||
def close_db(exception):
|
||||
db = getattr(g, "_database", None)
|
||||
if db is not None:
|
||||
db.close()
|
||||
|
||||
|
||||
def init_db():
|
||||
with app.app_context():
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS signups (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
navn TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
domaener INTEGER NOT NULL,
|
||||
egne_ns TEXT NOT NULL,
|
||||
kommentar TEXT,
|
||||
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
"""
|
||||
)
|
||||
db.commit()
|
||||
|
||||
|
||||
def require_admin(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
auth = request.authorization
|
||||
if not auth or auth.username != ADMIN_USER or auth.password != ADMIN_PASS:
|
||||
return Response(
|
||||
"Login krævet.",
|
||||
401,
|
||||
{"WWW-Authenticate": 'Basic realm="PunktFri Admin"'},
|
||||
)
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return decorated
|
||||
|
||||
|
||||
@app.route("/", methods=["GET", "POST"])
|
||||
def index():
|
||||
error = None
|
||||
if request.method == "POST":
|
||||
navn = request.form.get("navn", "").strip()
|
||||
email = request.form.get("email", "").strip().lower()
|
||||
domaener_raw = request.form.get("domaener", "").strip()
|
||||
egne_ns = request.form.get("egne_ns", "").strip()
|
||||
kommentar = request.form.get("kommentar", "").strip()
|
||||
|
||||
if not navn or not email or not domaener_raw or egne_ns not in ("ja", "nej"):
|
||||
error = "Udfyld venligst alle påkrævede felter."
|
||||
else:
|
||||
try:
|
||||
domaener = int(domaener_raw)
|
||||
if domaener < 1:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
error = "Angiv et gyldigt antal domæner (mindst 1)."
|
||||
else:
|
||||
db = get_db()
|
||||
existing = db.execute(
|
||||
"SELECT id FROM signups WHERE email = ?", (email,)
|
||||
).fetchone()
|
||||
if existing:
|
||||
error = "Denne e-mail er allerede tilmeldt — tak for din interesse!"
|
||||
else:
|
||||
db.execute(
|
||||
"INSERT INTO signups (navn, email, domaener, egne_ns, kommentar) VALUES (?, ?, ?, ?, ?)",
|
||||
(navn, email, domaener, egne_ns, kommentar or None),
|
||||
)
|
||||
db.commit()
|
||||
signup_logger.info(
|
||||
f"SIGNUP navn={navn!r} email={email!r} domaener={domaener} "
|
||||
f"egne_ns={egne_ns} kommentar={kommentar!r}"
|
||||
)
|
||||
return redirect(url_for("tak"))
|
||||
|
||||
return render_template("index.html", error=error)
|
||||
|
||||
|
||||
@app.route("/tak")
|
||||
def tak():
|
||||
return render_template("tak.html")
|
||||
|
||||
|
||||
@app.route("/admin")
|
||||
@require_admin
|
||||
def admin():
|
||||
db = get_db()
|
||||
signups = db.execute(
|
||||
"SELECT * FROM signups ORDER BY timestamp DESC"
|
||||
).fetchall()
|
||||
count = db.execute("SELECT COUNT(*) FROM signups").fetchone()[0]
|
||||
return render_template("admin.html", signups=signups, count=count)
|
||||
|
||||
|
||||
@app.route("/health")
|
||||
def health():
|
||||
return {"status": "ok"}, 200
|
||||
|
||||
|
||||
init_db()
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=PORT, debug=False)
|
||||
Reference in New Issue
Block a user