from __future__ import annotations import os import secrets from datetime import date, timedelta from pathlib import Path from flask import Flask, g, send_from_directory from . import db from .admin import admin_bp from .auth import auth_bp from .constants import ( CATEGORIES, DAYPARTS, ITEM_KIND_LABELS, ITEM_KIND_SINGULAR_LABELS, ROLE_LABELS, VISIBILITY_DESCRIPTIONS, VISIBILITY_LABELS, ) from .main import main_bp WEEKDAY_NAMES = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"] WEEKDAY_SHORT_NAMES = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"] def load_secret_key(data_dir: Path) -> str: env_secret = os.environ.get("NOURI_SECRET_KEY") if env_secret: return env_secret secret_path = data_dir / ".secret_key" if secret_path.exists(): return secret_path.read_text(encoding="utf-8").strip() secret_value = secrets.token_hex(24) try: with secret_path.open("x", encoding="utf-8") as handle: handle.write(secret_value) except FileExistsError: return secret_path.read_text(encoding="utf-8").strip() return secret_value def create_app() -> Flask: root_dir = Path(__file__).resolve().parent.parent data_dir = Path(os.environ.get("NOURI_DATA_DIR", root_dir / "data")).resolve() upload_dir = data_dir / "uploads" db_path = data_dir / "nouri.sqlite3" data_dir.mkdir(parents=True, exist_ok=True) upload_dir.mkdir(parents=True, exist_ok=True) app = Flask(__name__, instance_relative_config=False) app.config.update( SECRET_KEY=load_secret_key(data_dir), DATABASE_PATH=str(db_path), DATA_DIR=str(data_dir), UPLOAD_FOLDER=str(upload_dir), MAX_CONTENT_LENGTH=int(os.environ.get("NOURI_MAX_UPLOAD_MB", "5")) * 1024 * 1024, PERMANENT_SESSION_LIFETIME=timedelta(days=30), SESSION_COOKIE_HTTPONLY=True, SESSION_COOKIE_SAMESITE="Lax", ) db.init_app(app) db.init_db_if_needed(app) app.register_blueprint(auth_bp) app.register_blueprint(admin_bp) app.register_blueprint(main_bp) @app.context_processor def inject_globals() -> dict[str, object]: return { "item_kind_labels": ITEM_KIND_LABELS, "item_kind_singular_labels": ITEM_KIND_SINGULAR_LABELS, "category_suggestions": CATEGORIES, "daypart_suggestions": DAYPARTS, "visibility_labels": VISIBILITY_LABELS, "visibility_descriptions": VISIBILITY_DESCRIPTIONS, "role_labels": ROLE_LABELS, "today": date.today(), "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", } @app.get("/uploads/") def uploaded_file(filename: str): return send_from_directory(app.config["UPLOAD_FOLDER"], filename) return app