1pub mod audit;
8pub mod auth;
9pub mod handlers;
10pub mod rbac;
11pub mod routes;
12pub mod models;
14pub mod prometheus_client;
15pub mod time_travel_handlers;
16
17pub use models::{RequestLog, RouteInfo, ServerStatus, SystemInfo};
18pub use routes::create_admin_router;
19
20use std::net::SocketAddr;
21
22pub async fn start_admin_server(
38 addr: SocketAddr,
39 http_server_addr: Option<SocketAddr>,
40 ws_server_addr: Option<SocketAddr>,
41 grpc_server_addr: Option<SocketAddr>,
42 graphql_server_addr: Option<SocketAddr>,
43 api_enabled: bool,
44 prometheus_url: String,
45 chaos_api_state: Option<std::sync::Arc<mockforge_chaos::api::ChaosApiState>>,
46 latency_injector: Option<
47 std::sync::Arc<tokio::sync::RwLock<mockforge_core::latency::LatencyInjector>>,
48 >,
49 mockai: Option<
50 std::sync::Arc<tokio::sync::RwLock<mockforge_core::intelligent_behavior::MockAI>>,
51 >,
52 continuum_config: Option<mockforge_core::ContinuumConfig>,
53 virtual_clock: Option<std::sync::Arc<mockforge_core::VirtualClock>>,
54) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
55 let app = create_admin_router(
56 http_server_addr,
57 ws_server_addr,
58 grpc_server_addr,
59 graphql_server_addr,
60 api_enabled,
61 addr.port(),
62 prometheus_url,
63 chaos_api_state,
64 latency_injector,
65 mockai,
66 continuum_config,
67 virtual_clock,
68 );
69
70 tracing::info!("Starting MockForge Admin UI on {}", addr);
71
72 let listener = tokio::net::TcpListener::bind(addr).await.map_err(|e| {
73 format!(
74 "Failed to bind Admin UI server to port {}: {}\n\
75 Hint: The port may already be in use. Try using a different port with --admin-port or check if another process is using this port with: lsof -i :{} or netstat -tulpn | grep {}",
76 addr.port(), e, addr.port(), addr.port()
77 )
78 })?;
79
80 axum::serve(listener, app).await?;
81
82 Ok(())
83}
84
85pub fn get_admin_html() -> &'static str {
87 include_str!("../ui/dist/index.html")
88}
89
90pub fn get_admin_css() -> &'static str {
92 include_str!("../ui/dist/assets/index.css")
93}
94
95pub fn get_admin_js() -> &'static str {
97 include_str!("../ui/dist/assets/index.js")
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_get_admin_html() {
106 let html = get_admin_html();
107 assert!(!html.is_empty());
108 assert!(html.contains("<!DOCTYPE html>") || html.contains("<html"));
109 }
110
111 #[test]
112 fn test_get_admin_css() {
113 let css = get_admin_css();
114 assert!(!css.is_empty());
115 }
116
117 #[test]
118 fn test_get_admin_js() {
119 let js = get_admin_js();
120 assert!(!js.is_empty());
121 }
122}