Enhance API response in portal files listing: streamline JSON structure by consolidating repeated code, improve error handling for directory checks, and add portal files directory information to the response. Update HTML template to display the server directory path dynamically.

This commit is contained in:
nearxos
2026-02-20 08:49:02 +02:00
parent 1fdd1dd376
commit 42bacad329
2 changed files with 15 additions and 7 deletions

View File

@@ -615,17 +615,24 @@ def _save_portal_descriptions(descriptions):
def api_portal_files_list(): def api_portal_files_list():
"""List one level: root or contents of path=... (folders and files).""" """List one level: root or contents of path=... (folders and files)."""
subpath = request.args.get("path", "").strip().strip("/") subpath = request.args.get("path", "").strip().strip("/")
base_url = request.host_url.rstrip("/") + "/files/"
empty = {"items": [], "base_url": base_url, "descriptions": {}, "current_path": subpath, "portal_files_dir": str(PORTAL_FILES_DIR)}
if ".." in subpath or "\\" in subpath: if ".." in subpath or "\\" in subpath:
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": ""}) return jsonify(empty)
if not PORTAL_FILES_DIR.is_dir(): if not PORTAL_FILES_DIR.is_dir():
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": ""}) try:
PORTAL_FILES_DIR.mkdir(parents=True, exist_ok=True)
except OSError:
pass
if not PORTAL_FILES_DIR.is_dir():
return jsonify(empty)
list_dir = (PORTAL_FILES_DIR / subpath).resolve() if subpath else PORTAL_FILES_DIR list_dir = (PORTAL_FILES_DIR / subpath).resolve() if subpath else PORTAL_FILES_DIR
try: try:
list_dir.relative_to(PORTAL_FILES_DIR.resolve()) list_dir.relative_to(PORTAL_FILES_DIR.resolve())
except ValueError: except ValueError:
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": subpath}) return jsonify({**empty, "current_path": subpath})
if not list_dir.is_dir(): if not list_dir.is_dir():
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": subpath}) return jsonify({**empty, "current_path": subpath})
items = [] items = []
for p in sorted(list_dir.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower())): 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("."): if ".." in p.name or p.name.startswith("."):
@@ -639,8 +646,7 @@ def api_portal_files_list():
except OSError: except OSError:
pass pass
descriptions = _load_portal_descriptions() descriptions = _load_portal_descriptions()
base = request.host_url.rstrip("/") + "/files/" return jsonify({"items": items, "base_url": base_url, "descriptions": descriptions, "current_path": subpath, "portal_files_dir": str(PORTAL_FILES_DIR)})
return jsonify({"items": items, "base_url": base, "descriptions": descriptions, "current_path": subpath})
@app.route("/api/portal-files/descriptions", methods=["GET", "PATCH"]) @app.route("/api/portal-files/descriptions", methods=["GET", "PATCH"])

View File

@@ -72,7 +72,8 @@
<button type="button" class="btn btn-outline btn-sm" id="uploadBtn">Upload file</button> <button type="button" class="btn btn-outline btn-sm" id="uploadBtn">Upload file</button>
<input type="file" id="uploadInput" style="display:none;" /> <input type="file" id="uploadInput" style="display:none;" />
</div> </div>
<p class="mono" style="font-size:0.8rem; margin-bottom:0.75rem;">Served at <strong id="baseUrl">/files/</strong> — use in cloud-init e.g. <code>curl -fsSL "http://SERVER/files/first-boot/splash.png" -o /tmp/splash.png</code></p> <p class="mono" style="font-size:0.8rem; margin-bottom:0.5rem;">Served at <strong id="baseUrl">/files/</strong> — use in cloud-init e.g. <code>curl -fsSL "http://SERVER/files/first-boot/splash.png" -o /tmp/splash.png</code></p>
<p class="mono" style="font-size:0.75rem; color:var(--text-muted); margin-bottom:0.75rem;">Directory on server: <strong id="portalDir"></strong></p>
<table> <table>
<thead><tr><th>Name</th><th>Type</th><th>Size</th><th>Description</th><th>Actions</th></tr></thead> <thead><tr><th>Name</th><th>Type</th><th>Size</th><th>Description</th><th>Actions</th></tr></thead>
<tbody id="portalBody"></tbody> <tbody id="portalBody"></tbody>
@@ -121,6 +122,7 @@
descriptions = data.descriptions || {}; descriptions = data.descriptions || {};
currentPath = data.current_path || ''; currentPath = data.current_path || '';
document.getElementById('baseUrl').textContent = baseUrl + (currentPath ? currentPath + '/' : ''); document.getElementById('baseUrl').textContent = baseUrl + (currentPath ? currentPath + '/' : '');
document.getElementById('portalDir').textContent = data.portal_files_dir || '—';
buildBreadcrumb(); buildBreadcrumb();
var tbody = document.getElementById('portalBody'); var tbody = document.getElementById('portalBody');