CmdForge/src/cmdforge/web/app.py

82 lines
2.5 KiB
Python

"""Web app factory for CmdForge UI."""
from __future__ import annotations
import os
import secrets
from flask import Flask, render_template, session
# Initialize Sentry before importing Flask app (if DSN is configured)
_sentry_dsn = os.environ.get("SENTRY_DSN")
if _sentry_dsn:
try:
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(
dsn=_sentry_dsn,
integrations=[FlaskIntegration()],
traces_sample_rate=float(os.environ.get("SENTRY_TRACES_RATE", "0.1")),
profiles_sample_rate=float(os.environ.get("SENTRY_PROFILES_RATE", "0.1")),
environment=os.environ.get("CMDFORGE_ENV", "development"),
send_default_pii=False, # Privacy: don't send user IPs, emails, etc.
)
except ImportError:
pass # sentry-sdk not installed
from cmdforge.registry import app as registry_app
from . import web_bp
from .auth import login, register, logout
from .filters import register_filters
from .forum import forum_bp
from .sessions import SQLiteSessionInterface, cleanup_expired_sessions
def create_web_app() -> Flask:
app = registry_app.create_app()
# Import routes BEFORE registering blueprint
from . import routes # noqa: F401
app.register_blueprint(web_bp)
app.register_blueprint(forum_bp)
# Session configuration
app.session_interface = SQLiteSessionInterface(cookie_name="cmdforge_session")
app.config["SESSION_COOKIE_NAME"] = "cmdforge_session"
app.config["SESSION_COOKIE_SECURE"] = os.environ.get("CMDFORGE_ENV") == "production"
app.config["SHOW_ADS"] = os.environ.get("CMDFORGE_SHOW_ADS", "").lower() == "true"
# CSRF token generator
app.config["CSRF_GENERATOR"] = lambda: secrets.token_urlsafe(32)
# Jinja globals
def _csrf_token():
token = session.get("csrf_token")
if not token:
token = app.config["CSRF_GENERATOR"]()
session["csrf_token"] = token
return token
app.jinja_env.globals["csrf_token"] = _csrf_token
register_filters(app)
cleanup_expired_sessions()
# Error handlers
@app.errorhandler(404)
def not_found_error(error):
return render_template("errors/404.html"), 404
@app.errorhandler(500)
def internal_error(error):
return render_template("errors/500.html"), 500
return app
if __name__ == "__main__":
create_web_app().run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))