From ed5e1a1101f2179fbc098accae914c5e769b292a Mon Sep 17 00:00:00 2001 From: nearxos Date: Fri, 20 Feb 2026 09:23:51 +0200 Subject: [PATCH] Implement debug API for portal files and enhance file listing functionality: add a no-auth endpoint for troubleshooting, improve error handling, and streamline the portal files listing logic. Update HTML template to handle session expiration gracefully and provide a read-only fallback for unauthenticated users. --- .../emmc-provisioning/dashboard/app.py | 61 +++++++++++++++---- .../dashboard/templates/portal_files.html | 20 +++++- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/chromium-setup/emmc-provisioning/dashboard/app.py b/chromium-setup/emmc-provisioning/dashboard/app.py index e86b989..44ab230 100644 --- a/chromium-setup/emmc-provisioning/dashboard/app.py +++ b/chromium-setup/emmc-provisioning/dashboard/app.py @@ -424,6 +424,27 @@ def serve_portal_file(filename): return send_file(path, as_attachment=False, download_name=filename.split("/")[-1]) +@app.route("/api/portal-files-debug") +def api_portal_files_debug(): + """No-auth debug: what PORTAL_FILES_DIR the process sees (for troubleshooting).""" + try: + names = [] + if PORTAL_FILES_DIR.is_dir(): + for p in sorted(PORTAL_FILES_DIR.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower())): + if ".." in p.name or p.name.startswith("."): + continue + names.append({"name": p.name, "type": "dir" if p.is_dir() else "file"}) + return jsonify({ + "portal_files_dir": str(PORTAL_FILES_DIR), + "exists": PORTAL_FILES_DIR.exists(), + "is_dir": PORTAL_FILES_DIR.is_dir(), + "items": names, + "CM4_PROVISIONING_DIR": os.environ.get("CM4_PROVISIONING_DIR"), + }) + except Exception as e: + return jsonify({"error": str(e)}), 500 + + @app.route("/api/status") def api_status(): return jsonify(read_status()) @@ -610,29 +631,26 @@ def _save_portal_descriptions(descriptions): return False -@app.route("/api/portal-files") -@require_admin -def api_portal_files_list(): - """List one level: root or contents of path=... (folders and files).""" - subpath = request.args.get("path", "").strip().strip("/") +def _portal_files_list_impl(subpath): + """Shared impl for listing portal files. Returns (items, descriptions, base_url, current_path).""" base_url = request.host_url.rstrip("/") + "/files/" - empty = {"items": [], "base_url": base_url, "descriptions": {}, "current_path": subpath, "portal_files_dir": str(PORTAL_FILES_DIR)} + empty_items = [] if ".." in subpath or "\\" in subpath: - return jsonify(empty) + return empty_items, {}, base_url, subpath if not PORTAL_FILES_DIR.is_dir(): try: PORTAL_FILES_DIR.mkdir(parents=True, exist_ok=True) except OSError: pass if not PORTAL_FILES_DIR.is_dir(): - return jsonify(empty) + return empty_items, {}, base_url, subpath list_dir = (PORTAL_FILES_DIR / subpath).resolve() if subpath else PORTAL_FILES_DIR try: list_dir.relative_to(PORTAL_FILES_DIR.resolve()) except ValueError: - return jsonify({**empty, "current_path": subpath}) + return empty_items, {}, base_url, subpath if not list_dir.is_dir(): - return jsonify({**empty, "current_path": subpath}) + return empty_items, {}, base_url, subpath items = [] for p in sorted(list_dir.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower())): if ".." in p.name or p.name.startswith("."): @@ -646,7 +664,28 @@ def api_portal_files_list(): except OSError: pass descriptions = _load_portal_descriptions() - return jsonify({"items": items, "base_url": base_url, "descriptions": descriptions, "current_path": subpath, "portal_files_dir": str(PORTAL_FILES_DIR)}) + return items, descriptions, base_url, subpath + + +@app.route("/api/portal-files") +def api_portal_files_list(): + """List one level: root or contents of path=... (folders and files). ?debug=1 allows unauthenticated read-only list.""" + subpath = request.args.get("path", "").strip().strip("/") + debug = request.args.get("debug") == "1" + if not debug and not session.get("admin_logged_in"): + if request.is_json or request.path.startswith("/api/"): + return jsonify({"ok": False, "error": "Login required"}), 401 + return redirect(url_for("login", next=request.url)) + items, descriptions, base_url, subpath = _portal_files_list_impl(subpath) + resp = jsonify({ + "items": items, + "base_url": base_url, + "descriptions": descriptions, + "current_path": subpath, + "portal_files_dir": str(PORTAL_FILES_DIR), + }) + resp.headers["Cache-Control"] = "no-store, no-cache, must-revalidate" + return resp @app.route("/api/portal-files/descriptions", methods=["GET", "PATCH"]) diff --git a/chromium-setup/emmc-provisioning/dashboard/templates/portal_files.html b/chromium-setup/emmc-provisioning/dashboard/templates/portal_files.html index 87368b7..3d33227 100644 --- a/chromium-setup/emmc-provisioning/dashboard/templates/portal_files.html +++ b/chromium-setup/emmc-provisioning/dashboard/templates/portal_files.html @@ -85,6 +85,7 @@