This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
mod admin;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -15,11 +17,12 @@ use dtrack_tools::{shared_client, DtrackServer};
|
|||||||
use rmcp::transport::streamable_http_server::{
|
use rmcp::transport::streamable_http_server::{
|
||||||
session::local::LocalSessionManager, StreamableHttpService,
|
session::local::LocalSessionManager, StreamableHttpService,
|
||||||
};
|
};
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
/// Bearer-Token-Gate fuer den /mcp-Endpoint.
|
/// Bearer-Token-Gate fuer den /mcp-Endpoint.
|
||||||
///
|
///
|
||||||
/// Stage 2: eine flache Token-Liste aus `DTRACK_HTTP_TOKENS` (kommagetrennt).
|
/// Stage 2: eine flache Token-Liste aus `DTRACK_HTTP_TOKENS` (kommagetrennt).
|
||||||
/// Multi-Client mit Rechten pro Token folgt in Stage 3 (Permission-Engine).
|
/// Rechte pro Token (Permission-Engine) folgen spaeter.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AuthState {
|
struct AuthState {
|
||||||
tokens: Arc<HashSet<String>>,
|
tokens: Arc<HashSet<String>>,
|
||||||
@@ -48,11 +51,7 @@ impl AuthState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn auth_mw(
|
async fn auth_mw(State(auth): State<AuthState>, req: Request, next: Next) -> Result<Response, StatusCode> {
|
||||||
State(auth): State<AuthState>,
|
|
||||||
req: Request,
|
|
||||||
next: Next,
|
|
||||||
) -> Result<Response, StatusCode> {
|
|
||||||
if auth.allow_all {
|
if auth.allow_all {
|
||||||
return Ok(next.run(req).await);
|
return Ok(next.run(req).await);
|
||||||
}
|
}
|
||||||
@@ -79,9 +78,17 @@ async fn main() -> Result<()> {
|
|||||||
let cfg = DtrackConfig::resolve()?;
|
let cfg = DtrackConfig::resolve()?;
|
||||||
let client = DtrackClient::from_config(&cfg)?;
|
let client = DtrackClient::from_config(&cfg)?;
|
||||||
|
|
||||||
// Laufzeit-austauschbarer Client-Handle (Admin-UI kann ihn spaeter neu bauen).
|
let config_path = std::env::var("DTRACK_CONFIG").ok().map(std::path::PathBuf::from);
|
||||||
|
|
||||||
|
// Laufzeit-austauschbarer Client-Handle (Admin-UI baut ihn live neu).
|
||||||
let shared = shared_client(client);
|
let shared = shared_client(client);
|
||||||
|
|
||||||
|
let app_state = admin::AppState {
|
||||||
|
config: Arc::new(RwLock::new(cfg)),
|
||||||
|
client: shared.clone(),
|
||||||
|
config_path,
|
||||||
|
};
|
||||||
|
|
||||||
// Pro Session ein frischer DtrackServer; der Handle wird nur geklont (Arc).
|
// Pro Session ein frischer DtrackServer; der Handle wird nur geklont (Arc).
|
||||||
let mcp_service = StreamableHttpService::new(
|
let mcp_service = StreamableHttpService::new(
|
||||||
move || Ok(DtrackServer::new(shared.clone())),
|
move || Ok(DtrackServer::new(shared.clone())),
|
||||||
@@ -94,15 +101,18 @@ async fn main() -> Result<()> {
|
|||||||
.nest_service("/mcp", mcp_service)
|
.nest_service("/mcp", mcp_service)
|
||||||
.layer(middleware::from_fn_with_state(auth, auth_mw));
|
.layer(middleware::from_fn_with_state(auth, auth_mw));
|
||||||
|
|
||||||
|
let admin_router = admin::router(app_state, admin::AdminAuth::from_env());
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/health", get(|| async { "OK" }))
|
.route("/health", get(|| async { "OK" }))
|
||||||
.merge(mcp);
|
.merge(mcp)
|
||||||
|
.merge(admin_router);
|
||||||
|
|
||||||
let addr = std::env::var("DTRACK_HTTP_ADDR").unwrap_or_else(|_| "0.0.0.0:8080".to_string());
|
let addr = std::env::var("DTRACK_HTTP_ADDR").unwrap_or_else(|_| "0.0.0.0:8080".to_string());
|
||||||
let listener = tokio::net::TcpListener::bind(&addr)
|
let listener = tokio::net::TcpListener::bind(&addr)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("Bind auf {addr} fehlgeschlagen"))?;
|
.with_context(|| format!("Bind auf {addr} fehlgeschlagen"))?;
|
||||||
tracing::info!("dtrack-http laeuft auf http://{addr}/mcp");
|
tracing::info!("dtrack-http laeuft auf http://{addr}/mcp (Admin: /admin)");
|
||||||
|
|
||||||
axum::serve(listener, app)
|
axum::serve(listener, app)
|
||||||
.with_graceful_shutdown(async {
|
.with_graceful_shutdown(async {
|
||||||
|
|||||||
Reference in New Issue
Block a user