fix(topology): secure and unify demo serving
This commit is contained in:
@@ -255,7 +255,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const API_BASE = 'http://localhost:5000';
|
const API_BASE = '';
|
||||||
let currentData = null;
|
let currentData = null;
|
||||||
|
|
||||||
// Group node members for composite SVG elements
|
// Group node members for composite SVG elements
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from topology_api.app import create_app
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
HTML_PATH = ROOT / "data" / "wiki" / "guanghan_topology_demo.html"
|
||||||
|
CONFIG_PATH = ROOT / "topology_api" / "config.py"
|
||||||
|
|
||||||
|
|
||||||
|
class TopologyApiServingTests(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls) -> None:
|
||||||
|
app = create_app()
|
||||||
|
app.config.update(TESTING=True)
|
||||||
|
cls.client = app.test_client()
|
||||||
|
|
||||||
|
def test_app_serves_demo_page_and_health(self) -> None:
|
||||||
|
health = self.client.get("/health")
|
||||||
|
self.assertEqual(health.status_code, 200)
|
||||||
|
self.assertEqual(health.get_json(), {"status": "ok"})
|
||||||
|
|
||||||
|
page = self.client.get("/guanghan_topology_demo.html")
|
||||||
|
self.assertEqual(page.status_code, 200)
|
||||||
|
self.assertIn("广寒基地拓扑结构", page.get_data(as_text=True))
|
||||||
|
page.close()
|
||||||
|
|
||||||
|
def test_page_uses_same_origin_api(self) -> None:
|
||||||
|
html = HTML_PATH.read_text(encoding="utf-8")
|
||||||
|
self.assertNotIn("http://localhost:5000", html)
|
||||||
|
self.assertIn("const API_BASE = ''", html)
|
||||||
|
|
||||||
|
def test_config_has_no_default_password(self) -> None:
|
||||||
|
source = CONFIG_PATH.read_text(encoding="utf-8")
|
||||||
|
self.assertNotRegex(
|
||||||
|
source,
|
||||||
|
r'os\.environ\.get\(\s*["\']PGPASSWORD["\']\s*,',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
+10
-1
@@ -1,10 +1,15 @@
|
|||||||
# topology_api/app.py
|
# topology_api/app.py
|
||||||
from flask import Flask
|
from pathlib import Path
|
||||||
|
|
||||||
|
from flask import Flask, send_from_directory
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
from topology_api.config import API_HOST, API_PORT, API_DEBUG
|
from topology_api.config import API_HOST, API_PORT, API_DEBUG
|
||||||
from topology_api.routes.snapshot import snapshot_bp
|
from topology_api.routes.snapshot import snapshot_bp
|
||||||
|
|
||||||
|
|
||||||
|
WIKI_DIR = Path(__file__).resolve().parents[1] / "data" / "wiki"
|
||||||
|
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
@@ -14,6 +19,10 @@ def create_app():
|
|||||||
def health():
|
def health():
|
||||||
return {"status": "ok"}
|
return {"status": "ok"}
|
||||||
|
|
||||||
|
@app.route("/guanghan_topology_demo.html")
|
||||||
|
def topology_demo():
|
||||||
|
return send_from_directory(WIKI_DIR, "guanghan_topology_demo.html")
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+12
-5
@@ -1,11 +1,18 @@
|
|||||||
# topology_api/config.py
|
# topology_api/config.py
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
|
||||||
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
load_dotenv(PROJECT_ROOT / ".env")
|
||||||
|
|
||||||
# PostgreSQL connection (from .env)
|
# PostgreSQL connection (from .env)
|
||||||
PGHOST = os.environ.get("PGHOST", "192.168.195.241")
|
PGHOST = os.environ["PGHOST"]
|
||||||
PGPORT = os.environ.get("PGPORT", "35432")
|
PGPORT = os.environ["PGPORT"]
|
||||||
PGUSER = os.environ.get("PGUSER", "user_armor")
|
PGUSER = os.environ["PGUSER"]
|
||||||
PGPASSWORD = os.environ.get("PGPASSWORD", "user_armor_1790990971")
|
PGPASSWORD = os.environ["PGPASSWORD"]
|
||||||
TOPO_DATABASE = os.environ.get("TOPO_DATABASE", "ksp_wiki_topology")
|
TOPO_DATABASE = os.environ.get("TOPO_DATABASE", "ksp_wiki_topology")
|
||||||
|
|
||||||
_BASE_DSN = f"postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}"
|
_BASE_DSN = f"postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}"
|
||||||
@@ -26,5 +33,5 @@ WRITER_DATABASE_URL = os.environ.get(
|
|||||||
)
|
)
|
||||||
|
|
||||||
API_HOST = os.environ.get("TOPOLOGY_API_HOST", "0.0.0.0")
|
API_HOST = os.environ.get("TOPOLOGY_API_HOST", "0.0.0.0")
|
||||||
API_PORT = int(os.environ.get("TOPOLOGY_API_PORT", "5000"))
|
API_PORT = int(os.environ.get("TOPOLOGY_API_PORT", "8080"))
|
||||||
API_DEBUG = os.environ.get("TOPOLOGY_API_DEBUG", "false").lower() == "true"
|
API_DEBUG = os.environ.get("TOPOLOGY_API_DEBUG", "false").lower() == "true"
|
||||||
|
|||||||
Reference in New Issue
Block a user