feat(webui): consolidate client-info into main dashboard with primary and settings subtabs layout
CI Test Suite / Run Component Tests & Pipeline Verification (push) Successful in 2m5s
CI Test Suite / Run Component Tests & Pipeline Verification (push) Successful in 2m5s
This commit is contained in:
+2
-11
@@ -2569,21 +2569,12 @@ def serve_webui(request: Request = None):
|
||||
@app.get("/client-info", response_class=HTMLResponse)
|
||||
@app.get("/webui/client-info", response_class=HTMLResponse)
|
||||
def serve_client_info(request: Request = None):
|
||||
"""Renders the dedicated LOGAR Client & Server Role Directory subpage."""
|
||||
auth_user = None
|
||||
"""Redirects to the integrated Server Roles directory tab within the main Web UI."""
|
||||
if request is not None:
|
||||
auth_user = get_current_user_optional(request)
|
||||
if not auth_user:
|
||||
return RedirectResponse(url="/login", status_code=303)
|
||||
else:
|
||||
auth_user = DEFAULT_ADMIN_USER
|
||||
|
||||
html_content = WebUIRenderer.render_client_info_html(
|
||||
auth_user=auth_user,
|
||||
request=request,
|
||||
server_state=SERVER_STATE
|
||||
)
|
||||
return HTMLResponse(content=html_content)
|
||||
return RedirectResponse(url="/webui#server-roles", status_code=303)
|
||||
|
||||
|
||||
@app.get("/api/client-info")
|
||||
|
||||
+775
-59
File diff suppressed because it is too large
Load Diff
@@ -190,8 +190,10 @@ class TestHubComprehensive(unittest.TestCase):
|
||||
)
|
||||
self.assertIn("LOGAR Fleet Hub", html)
|
||||
self.assertIn("tabPane-fleet", html)
|
||||
self.assertIn("tabPane-server-roles", html)
|
||||
self.assertIn("tabPane-telemetry", html)
|
||||
self.assertIn("tabPane-events", html)
|
||||
self.assertIn("tabPane-hermes", html)
|
||||
self.assertIn("tabPane-anomalies", html)
|
||||
self.assertIn("tabPane-pki", html)
|
||||
self.assertIn("tabPane-db", html)
|
||||
self.assertIn("tabPane-updates", html)
|
||||
|
||||
+10
-5
@@ -36,6 +36,8 @@ class TestServerComponent(unittest.TestCase):
|
||||
os.remove(self.test_config)
|
||||
except Exception:
|
||||
pass
|
||||
if "config" in Server.SERVER_STATE and isinstance(Server.SERVER_STATE["config"], dict):
|
||||
Server.SERVER_STATE["config"]["db_path"] = Server.DEFAULT_DB_FILE
|
||||
|
||||
def test_first_run_config_and_keypair_generation(self):
|
||||
config = Server.load_or_init_config(self.test_config)
|
||||
@@ -822,13 +824,16 @@ class TestServerComponent(unittest.TestCase):
|
||||
html_content = resp.body.decode("utf-8")
|
||||
|
||||
# Verify clean tab buttons without number suffixes
|
||||
self.assertIn('>💻 Fleet Forwarders</button>', html_content)
|
||||
self.assertIn('>🤖 Hermes AI & Tokens</button>', html_content)
|
||||
self.assertIn('>📊 Verified Telemetry</button>', html_content)
|
||||
self.assertIn('>📜 Sub-CA & Licensing</button>', html_content)
|
||||
self.assertIn('>💻 Forwarders</button>', html_content)
|
||||
self.assertIn('>🏢 Server Roles</button>', html_content)
|
||||
self.assertIn('>📊 Telemetry</button>', html_content)
|
||||
self.assertIn('>📜 Events</button>', html_content)
|
||||
self.assertIn('>⚙️ Settings', html_content)
|
||||
self.assertIn('>📜 Sub-CA & Licensing</button>', html_content)
|
||||
self.assertIn('>💾 DB Engine</button>', html_content)
|
||||
self.assertIn('>🤖 Hermes AI & Tokens</button>', html_content)
|
||||
self.assertNotIn('🟢 UNLOCKED', html_content)
|
||||
self.assertNotIn('Fleet Forwarders (', html_content)
|
||||
self.assertNotIn('Forwarders (', html_content)
|
||||
|
||||
# Verify Licensed Capabilities card is present
|
||||
self.assertIn('Licensed Capabilities & Feature Modules', html_content)
|
||||
|
||||
@@ -31,6 +31,11 @@ class TestServerRolesAndBestPractices(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.client = TestClient(app)
|
||||
self.db_path = SERVER_STATE.get("config", {}).get("db_path") or DEFAULT_DB_FILE
|
||||
if not os.path.exists(self.db_path):
|
||||
self.db_path = DEFAULT_DB_FILE
|
||||
SERVER_STATE.setdefault("config", {})["db_path"] = self.db_path
|
||||
from src.hub.Server import init_db
|
||||
init_db(self.db_path)
|
||||
self.session_token = SessionManager.generate_session_token("admin", db_path=self.db_path)
|
||||
self.auth_headers = {"Authorization": f"Bearer {self.session_token}"}
|
||||
|
||||
@@ -143,21 +148,64 @@ class TestServerRolesAndBestPractices(unittest.TestCase):
|
||||
self.assertIn("BP-SEC-003", loaded_ids)
|
||||
|
||||
def test_client_info_html_rendering(self):
|
||||
"""Verifies GET /client-info redirects to /login when unauthenticated, and renders HTML when authenticated."""
|
||||
"""Verifies GET /client-info redirects to /login when unauthenticated, and redirects to /webui#server-roles when authenticated."""
|
||||
# Unauthenticated redirects to /login
|
||||
res_unauth = self.client.get("/client-info", follow_redirects=False)
|
||||
self.assertEqual(res_unauth.status_code, 303)
|
||||
self.assertEqual(res_unauth.headers.get("location"), "/login")
|
||||
|
||||
# Authenticated renders the full directory page
|
||||
res1 = self.client.get("/client-info", cookies={SessionManager.SESSION_COOKIE_NAME: self.session_token})
|
||||
self.assertEqual(res1.status_code, 200)
|
||||
self.assertIn("LOGAR Server & Client Role Directory", res1.text)
|
||||
self.assertIn("Node Telemetry & Server Roles Inventory", res1.text)
|
||||
# Authenticated redirects to /webui#server-roles
|
||||
auth_client = TestClient(app)
|
||||
auth_client.cookies.set(SessionManager.SESSION_COOKIE_NAME, self.session_token)
|
||||
|
||||
res2 = self.client.get("/webui/client-info", cookies={SessionManager.SESSION_COOKIE_NAME: self.session_token})
|
||||
self.assertEqual(res2.status_code, 200)
|
||||
self.assertIn("LOGAR Server & Client Role Directory", res2.text)
|
||||
res1 = auth_client.get("/client-info", follow_redirects=False)
|
||||
self.assertEqual(res1.status_code, 303)
|
||||
self.assertEqual(res1.headers.get("location"), "/webui#server-roles")
|
||||
|
||||
res2 = auth_client.get("/webui/client-info", follow_redirects=False)
|
||||
self.assertEqual(res2.status_code, 303)
|
||||
self.assertEqual(res2.headers.get("location"), "/webui#server-roles")
|
||||
|
||||
# Following redirect leads to main dashboard with Server Roles tab pane
|
||||
res_follow = auth_client.get("/client-info", follow_redirects=True)
|
||||
self.assertEqual(res_follow.status_code, 200)
|
||||
self.assertIn("id=\"tabPane-server-roles\"", res_follow.text)
|
||||
self.assertIn("Node Telemetry & Server Roles Inventory", res_follow.text)
|
||||
|
||||
def test_dashboard_tabs_structure(self):
|
||||
"""Verifies primary tabs (Forwarders, Server Roles, Telemetry, Events, Settings) and secondary settings subtabs (Sub-CA, DB, Updates, Hermes)."""
|
||||
res = self.client.get("/webui", cookies={SessionManager.SESSION_COOKIE_NAME: self.session_token})
|
||||
self.assertEqual(res.status_code, 200)
|
||||
html = res.text
|
||||
|
||||
# Primary navigation tabs
|
||||
self.assertIn("id=\"mainTabsNav\"", html)
|
||||
self.assertIn("id=\"tabBtn-fleet\"", html)
|
||||
self.assertIn("id=\"tabBtn-server-roles\"", html)
|
||||
self.assertIn("id=\"tabBtn-telemetry\"", html)
|
||||
self.assertIn("id=\"tabBtn-events\"", html)
|
||||
self.assertIn("id=\"tabBtn-settings\"", html)
|
||||
|
||||
# Settings sub-navigation tabs (row below)
|
||||
self.assertIn("id=\"settingsSubtabs\"", html)
|
||||
self.assertIn("id=\"tabBtn-pki\"", html)
|
||||
self.assertIn("id=\"tabBtn-db\"", html)
|
||||
self.assertIn("id=\"tabBtn-updates\"", html)
|
||||
self.assertIn("id=\"tabBtn-hermes\"", html)
|
||||
|
||||
# Tab panes
|
||||
self.assertIn("id=\"tabPane-fleet\"", html)
|
||||
self.assertIn("id=\"tabPane-server-roles\"", html)
|
||||
self.assertIn("id=\"tabPane-telemetry\"", html)
|
||||
self.assertIn("id=\"tabPane-events\"", html)
|
||||
self.assertIn("id=\"tabPane-pki\"", html)
|
||||
self.assertIn("id=\"tabPane-db\"", html)
|
||||
self.assertIn("id=\"tabPane-updates\"", html)
|
||||
self.assertIn("id=\"tabPane-hermes\"", html)
|
||||
|
||||
# Telemetry JSON inspector modal
|
||||
self.assertIn("id=\"telemetryModal\"", html)
|
||||
self.assertIn("id=\"modalJsonContent\"", html)
|
||||
|
||||
def test_api_client_info_endpoint(self):
|
||||
"""Verifies GET /api/client-info provides structured JSON inventory."""
|
||||
@@ -197,11 +245,14 @@ class TestServerRolesAndBestPractices(unittest.TestCase):
|
||||
self.assertIn("fail_count", eval_data)
|
||||
|
||||
def test_admin_version_info_modal(self):
|
||||
"""Verifies admin dropdown menu contains Version & System Info option and renders telemetry modal in both /webui and /client-info."""
|
||||
"""Verifies admin dropdown menu contains Version & System Info option and renders telemetry modal in /webui."""
|
||||
from src.version import LOGAR_VERSION
|
||||
|
||||
auth_client = TestClient(app)
|
||||
auth_client.cookies.set(SessionManager.SESSION_COOKIE_NAME, self.session_token)
|
||||
|
||||
# Check /webui
|
||||
res_webui = self.client.get("/webui", cookies={SessionManager.SESSION_COOKIE_NAME: self.session_token})
|
||||
res_webui = auth_client.get("/webui")
|
||||
self.assertEqual(res_webui.status_code, 200)
|
||||
self.assertIn("id=\"userDropdown\"", res_webui.text)
|
||||
self.assertIn("Version & System Info", res_webui.text)
|
||||
@@ -218,23 +269,13 @@ class TestServerRolesAndBestPractices(unittest.TestCase):
|
||||
self.assertIn("Storage Backend Engine:", res_webui.text)
|
||||
self.assertIn("License Status & Seats:", res_webui.text)
|
||||
|
||||
# Check /client-info
|
||||
res_client_info = self.client.get("/client-info", cookies={SessionManager.SESSION_COOKIE_NAME: self.session_token})
|
||||
# Check /client-info redirects to /webui#server-roles and shows the version info modal
|
||||
res_client_info = auth_client.get("/client-info", follow_redirects=True)
|
||||
self.assertEqual(res_client_info.status_code, 200)
|
||||
self.assertIn("id=\"userDropdown\"", res_client_info.text)
|
||||
self.assertIn("Version & System Info", res_client_info.text)
|
||||
self.assertIn("openVersionInfoModal()", res_client_info.text)
|
||||
self.assertIn("id=\"versionInfoModal\"", res_client_info.text)
|
||||
self.assertIn(f"v{LOGAR_VERSION}", res_client_info.text)
|
||||
self.assertIn("Server Hub Release", res_client_info.text)
|
||||
self.assertIn("Hosted Client Binaries", res_client_info.text)
|
||||
self.assertIn("Repository Update Mode:", res_client_info.text)
|
||||
self.assertIn("Distribution Source:", res_client_info.text)
|
||||
self.assertIn("Python Environment:", res_client_info.text)
|
||||
self.assertIn("Host Platform & OS:", res_client_info.text)
|
||||
self.assertIn("TLS 1.3 mTLS Encrypted", res_client_info.text)
|
||||
self.assertIn("Storage Backend Engine:", res_client_info.text)
|
||||
self.assertIn("License Status & Seats:", res_client_info.text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user