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
22#[allow(clippy::too_many_arguments)]
38pub async fn start_admin_server(
39 addr: SocketAddr,
40 http_server_addr: Option<SocketAddr>,
41 ws_server_addr: Option<SocketAddr>,
42 grpc_server_addr: Option<SocketAddr>,
43 graphql_server_addr: Option<SocketAddr>,
44 api_enabled: bool,
45 prometheus_url: String,
46 chaos_api_state: Option<std::sync::Arc<mockforge_chaos::api::ChaosApiState>>,
47 latency_injector: Option<
48 std::sync::Arc<tokio::sync::RwLock<mockforge_core::latency::LatencyInjector>>,
49 >,
50 mockai: Option<
51 std::sync::Arc<tokio::sync::RwLock<mockforge_core::intelligent_behavior::MockAI>>,
52 >,
53 continuum_config: Option<mockforge_core::ContinuumConfig>,
54 virtual_clock: Option<std::sync::Arc<mockforge_core::VirtualClock>>,
55) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
56 let app = create_admin_router(
57 http_server_addr,
58 ws_server_addr,
59 grpc_server_addr,
60 graphql_server_addr,
61 api_enabled,
62 addr.port(),
63 prometheus_url,
64 chaos_api_state,
65 latency_injector,
66 mockai,
67 continuum_config,
68 virtual_clock,
69 );
70
71 tracing::info!("Starting MockForge Admin UI on {}", addr);
72
73 let listener = tokio::net::TcpListener::bind(addr).await.map_err(|e| {
74 format!(
75 "Failed to bind Admin UI server to port {}: {}\n\
76 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 {}",
77 addr.port(), e, addr.port(), addr.port()
78 )
79 })?;
80
81 axum::serve(listener, app).await?;
82
83 Ok(())
84}
85
86include!(concat!(env!("OUT_DIR"), "/ui_content.rs"));
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_get_admin_html() {
95 let html = get_admin_html();
96 assert!(!html.is_empty());
97 assert!(html.contains("<!DOCTYPE html>") || html.contains("<html"));
98 }
99
100 #[test]
101 fn test_get_admin_css() {
102 let _css = get_admin_css();
103 }
105
106 #[test]
107 fn test_get_admin_js() {
108 let _js = get_admin_js();
109 }
111}