feat: complete dashboard-vite parity and fix portal health/csp regressions

This commit is contained in:
egg
2026-02-09 09:22:23 +08:00
parent cf194bc3a3
commit 1e6d6dbd31
57 changed files with 13347 additions and 312 deletions

View File

@@ -104,11 +104,12 @@ def _build_security_headers(production: bool) -> dict[str, str]:
"img-src 'self' data: blob:; "
"font-src 'self' data:; "
"connect-src 'self'; "
"frame-ancestors 'none'; "
# Portal embeds same-origin report pages via iframe.
"frame-ancestors 'self'; "
"base-uri 'self'; "
"form-action 'self'"
),
"X-Frame-Options": "DENY",
"X-Frame-Options": "SAMEORIGIN",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin-when-cross-origin",
}
@@ -233,11 +234,14 @@ def create_app(config_name: str | None = None) -> Flask:
# Initialize database teardown and pool
init_db(app)
running_pytest = bool(os.getenv("PYTEST_CURRENT_TEST"))
is_testing_runtime = bool(app.config.get("TESTING")) or app.testing or running_pytest
with app.app_context():
get_engine()
start_keepalive() # Keep database connections alive
start_cache_updater() # Start Redis cache updater
init_realtime_equipment_cache(app) # Start realtime equipment status cache
if not is_testing_runtime:
get_engine()
start_keepalive() # Keep database connections alive
start_cache_updater() # Start Redis cache updater
init_realtime_equipment_cache(app) # Start realtime equipment status cache
_register_shutdown_hooks(app)
# Register API routes
@@ -343,13 +347,10 @@ def create_app(config_name: str | None = None) -> Flask:
return admin
def frontend_asset(filename: str) -> str | None:
"""Resolve built frontend asset from static/dist if available."""
"""Resolve frontend asset path served from static/dist."""
if not filename:
return None
dist_path = os.path.join(app.static_folder or "", "dist", filename)
if os.path.exists(dist_path):
return url_for("static", filename=f"dist/{filename}")
return None
return url_for("static", filename=f"dist/{filename}")
return {
"is_admin": admin,
@@ -368,6 +369,11 @@ def create_app(config_name: str | None = None) -> Flask:
"""Portal home with tabs."""
return render_template('portal.html')
@app.route('/favicon.ico')
def favicon():
"""Serve favicon without 404 noise."""
return redirect(url_for('static', filename='favicon.svg'), code=302)
@app.route('/tables')
def tables_page():
"""Table viewer page."""
@@ -398,6 +404,11 @@ def create_app(config_name: str | None = None) -> Flask:
"""Resource history analysis page."""
return render_template('resource_history.html')
@app.route('/tmtt-defect')
def tmtt_defect_page():
"""TMTT printing & lead form defect analysis page."""
return render_template('tmtt_defect.html')
# ========================================================
# Table Query APIs (for table_data_viewer)
# ========================================================