From cd4cbcfb483f7427f1e9a50507ca211b821f23ea Mon Sep 17 00:00:00 2001 From: CTO H3R7Tech Date: Sat, 23 May 2026 22:57:06 +0200 Subject: [PATCH] Fix #2+#3: Routes API 404 et conflit blueprint name Bug #2: portal_server.py importait api_v1_bp depuis saas_api_v1 au lieu de api_v1/__init__.py. Tous les sous-blueprints api_v1/routes/* (health, courses, predictions, valuebets, backtest, export, metrics, ml_feedback) n'etaient jamais enregistres -> 404. Fix: utiliser register_api_v1(app) depuis api_v1/__init__.py. Bug #3: Conflit de nom de blueprint entre saas_api_v1 et api_v1 (tous deux nommes api_v1). Renomme le blueprint de saas_api_v1 en saas_api_v1_bp. Supprime les record_once handlers de saas_api_v1 qui dupliquaient l'enregistrement de sous-blueprints (billing, org, user, history) - desormais geres par register_api_v1(app). Co-Authored-By: Paperclip --- portal_server.py | 10 +++--- saas_api_v1.py | 79 ++++++++---------------------------------------- 2 files changed, 17 insertions(+), 72 deletions(-) diff --git a/portal_server.py b/portal_server.py index 97f49ad..5ce2408 100755 --- a/portal_server.py +++ b/portal_server.py @@ -18,14 +18,12 @@ SAAS_DIR = "/home/h3r7/turf_saas" # ─── SaaS Auth & API v1 blueprints ──────────────────────────────────────────── try: from saas_auth import auth_bp - from saas_api_v1 import api_v1_bp - from api_v1.routes.ml_feedback import ml_feedback_bp - from api_v1.routes.metrics import metrics_bp + from saas_api_v1 import saas_api_v1_bp + from api_v1 import register_api_v1 app.register_blueprint(auth_bp) - app.register_blueprint(api_v1_bp) - app.register_blueprint(ml_feedback_bp) - app.register_blueprint(metrics_bp) + app.register_blueprint(saas_api_v1_bp) + register_api_v1(app) print("[portal] SaaS auth & API v1 blueprints registered ✅") except Exception as e: print(f"[portal] Warning: could not register SaaS blueprints: {e}") diff --git a/saas_api_v1.py b/saas_api_v1.py index 1944cf7..da4abd2 100644 --- a/saas_api_v1.py +++ b/saas_api_v1.py @@ -13,7 +13,7 @@ from saas_auth import require_auth DB_PATH = os.environ.get("TURF_SAAS_DB", "/home/h3r7/turf_saas/turf_saas.db") -api_v1_bp = Blueprint("api_v1", __name__, url_prefix="/api/v1") +saas_api_v1_bp = Blueprint("saas_api_v1", __name__, url_prefix="/api/v1") def get_db(): @@ -30,7 +30,7 @@ def plan_allows(user_plan: str, required: str) -> bool: # ─── Stats ──────────────────────────────────────────────────────────────────── -@api_v1_bp.route("/stats/summary", methods=["GET"]) +@saas_api_v1_bp.route("/stats/summary", methods=["GET"]) @require_auth def stats_summary(): """GET /api/v1/stats/summary — résumé dashboard.""" @@ -94,7 +94,7 @@ def stats_summary(): # ─── Predictions ────────────────────────────────────────────────────────────── -@api_v1_bp.route("/predictions/today", methods=["GET"]) +@saas_api_v1_bp.route("/predictions/today", methods=["GET"]) @require_auth def predictions_today(): """GET /api/v1/predictions/today — prédictions du jour selon le plan.""" @@ -149,7 +149,7 @@ def predictions_today(): return jsonify({"error": str(e), "predictions": []}), 200 -@api_v1_bp.route("/predictions/race/", methods=["GET"]) +@saas_api_v1_bp.route("/predictions/race/", methods=["GET"]) @require_auth def predictions_race(race_label): """GET /api/v1/predictions/race/