release nouri 0.6.0 polish backup and pwa
This commit is contained in:
+55
-6
@@ -5,7 +5,7 @@ import secrets
|
||||
from datetime import date, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from flask import Flask, g, send_from_directory
|
||||
from flask import Flask, flash, g, redirect, request, send_from_directory, url_for
|
||||
|
||||
from . import db
|
||||
from .admin import admin_bp
|
||||
@@ -24,6 +24,7 @@ from .constants import (
|
||||
VISIBILITY_LABELS,
|
||||
WEEKDAY_OPTIONS,
|
||||
)
|
||||
from .images import ensure_upload_structure, image_sizes, image_srcset, image_url
|
||||
from .main import main_bp
|
||||
|
||||
|
||||
@@ -56,7 +57,7 @@ def create_app() -> Flask:
|
||||
db_path = data_dir / "nouri.sqlite3"
|
||||
|
||||
data_dir.mkdir(parents=True, exist_ok=True)
|
||||
upload_dir.mkdir(parents=True, exist_ok=True)
|
||||
ensure_upload_structure(upload_dir)
|
||||
|
||||
app = Flask(__name__, instance_relative_config=False)
|
||||
app.config.update(
|
||||
@@ -68,7 +69,7 @@ def create_app() -> Flask:
|
||||
PERMANENT_SESSION_LIFETIME=timedelta(days=30),
|
||||
SESSION_COOKIE_HTTPONLY=True,
|
||||
SESSION_COOKIE_SAMESITE="Lax",
|
||||
APP_VERSION="0.5.1",
|
||||
APP_VERSION="0.6.0",
|
||||
VAPID_PUBLIC_KEY=os.environ.get("NOURI_VAPID_PUBLIC_KEY", ""),
|
||||
VAPID_PRIVATE_KEY=os.environ.get("NOURI_VAPID_PRIVATE_KEY", ""),
|
||||
VAPID_SUBJECT=os.environ.get("NOURI_VAPID_SUBJECT", "mailto:mail@hnz.io"),
|
||||
@@ -83,6 +84,11 @@ def create_app() -> Flask:
|
||||
|
||||
@app.context_processor
|
||||
def inject_globals() -> dict[str, object]:
|
||||
def asset_url(filename: str) -> str:
|
||||
file_path = root_dir / "nouri" / "static" / filename
|
||||
version = int(file_path.stat().st_mtime) if file_path.exists() else app.config["APP_VERSION"]
|
||||
return url_for("static", filename=filename, v=version)
|
||||
|
||||
return {
|
||||
"item_kind_labels": ITEM_KIND_LABELS,
|
||||
"item_kind_singular_labels": ITEM_KIND_SINGULAR_LABELS,
|
||||
@@ -103,18 +109,61 @@ def create_app() -> Flask:
|
||||
"weekday_name": lambda value: WEEKDAY_NAMES[value.weekday()],
|
||||
"weekday_short_name": lambda value: WEEKDAY_SHORT_NAMES[value.weekday()],
|
||||
"is_admin": lambda: bool(getattr(g, "user", None)) and g.user["role"] == "admin",
|
||||
"asset_url": asset_url,
|
||||
"image_url": lambda filename, variant="md": image_url(
|
||||
filename,
|
||||
url_for,
|
||||
variant,
|
||||
upload_folder=app.config["UPLOAD_FOLDER"],
|
||||
),
|
||||
"image_srcset": lambda filename: image_srcset(
|
||||
filename,
|
||||
url_for,
|
||||
upload_folder=app.config["UPLOAD_FOLDER"],
|
||||
),
|
||||
"image_sizes": image_sizes,
|
||||
}
|
||||
|
||||
@app.get("/uploads/<path:filename>")
|
||||
def uploaded_file(filename: str):
|
||||
return send_from_directory(app.config["UPLOAD_FOLDER"], filename)
|
||||
response = send_from_directory(app.config["UPLOAD_FOLDER"], filename, max_age=60 * 60 * 24 * 30)
|
||||
response.headers["Cache-Control"] = "public, max-age=2592000, immutable"
|
||||
return response
|
||||
|
||||
@app.get("/app.webmanifest")
|
||||
def webmanifest():
|
||||
return send_from_directory(root_dir / "nouri" / "static" / "pwa", "app.webmanifest", mimetype="application/manifest+json")
|
||||
response = send_from_directory(
|
||||
root_dir / "nouri" / "static" / "pwa",
|
||||
"app.webmanifest",
|
||||
mimetype="application/manifest+json",
|
||||
max_age=60 * 30,
|
||||
)
|
||||
response.headers["Cache-Control"] = "public, max-age=1800"
|
||||
return response
|
||||
|
||||
@app.get("/service-worker.js")
|
||||
def service_worker():
|
||||
return send_from_directory(root_dir / "nouri" / "static" / "pwa", "service-worker.js", mimetype="application/javascript")
|
||||
response = send_from_directory(
|
||||
root_dir / "nouri" / "static" / "pwa",
|
||||
"service-worker.js",
|
||||
mimetype="application/javascript",
|
||||
max_age=0,
|
||||
)
|
||||
response.headers["Cache-Control"] = "no-store"
|
||||
return response
|
||||
|
||||
@app.after_request
|
||||
def apply_cache_policy(response):
|
||||
if response.direct_passthrough:
|
||||
return response
|
||||
content_type = response.headers.get("Content-Type", "")
|
||||
if content_type.startswith("text/html"):
|
||||
response.headers.setdefault("Cache-Control", "no-store, max-age=0")
|
||||
return response
|
||||
|
||||
@app.errorhandler(413)
|
||||
def upload_too_large(_error):
|
||||
flash("Das hochgeladene Bild ist etwas zu groß. Eine kleinere Datei passt hier besser.", "error")
|
||||
return redirect(request.referrer or url_for("main.dashboard"))
|
||||
|
||||
return app
|
||||
|
||||
Reference in New Issue
Block a user