//! Remote agent management API routes. //! //! Endpoints: //! //! - `GET /api/remote-agents` — list remote agents //! - `POST /api/remote-agents` — create new remote agent //! - `GET /api/remote-agents/{id}` — get remote agent details //! - `PUT /api/remote-agents/{id}` — update remote agent //! - `DELETE /api/remote-agents/{id}` — delete remote agent //! - `POST /api/remote-agents/test-connection` — test connection to remote agent (without saving it) //! - `POST /api/remote-agents/{id}/handshake` — perform handshake with the remote agent to verify connectivity and retrieve agent info use axum::Router; use axum::extract::rejection::JsonRejection; use axum::extract::{Extension, Json, Path, State}; use axum::http::StatusCode; use axum::routing::{get, post}; use nomifun_api_types::{ ApiResponse, CreateRemoteAgentRequest, HandshakeResponse, RemoteAgentListItem, RemoteAgentResponse, TestRemoteAgentConnectionRequest, UpdateRemoteAgentRequest, }; use nomifun_auth::CurrentUser; use nomifun_common::AppError; use super::state::RemoteAgentRouterState; /// Build the remote agent router. /// /// All routes require authentication (applied by the caller). pub fn remote_agent_routes(state: RemoteAgentRouterState) -> Router { Router::new() .route("/api/remote-agents", get(list).post(create)) .route("/api/remote-agents/test-connection", post(test_connection)) .route("/api/remote-agents/{id}", get(get_one).put(update).delete(delete_one)) .route("/api/remote-agents/{id}/handshake", post(handshake)) .with_state(state) } async fn list( State(state): State, Extension(_user): Extension, ) -> Result>>, AppError> { let items = state.service.list().await?; Ok(Json(ApiResponse::ok(items))) } async fn get_one( State(state): State, Extension(_user): Extension, Path(id): Path, ) -> Result>, AppError> { let agent = state.service.get(&id).await?; Ok(Json(ApiResponse::ok(agent))) } async fn create( State(state): State, Extension(_user): Extension, body: Result, JsonRejection>, ) -> Result<(StatusCode, Json>), AppError> { let Json(req) = body.map_err(|e| AppError::BadRequest(e.to_string()))?; let agent = state.service.create(req).await?; Ok((StatusCode::CREATED, Json(ApiResponse::ok(agent)))) } async fn update( State(state): State, Extension(_user): Extension, Path(id): Path, body: Result, JsonRejection>, ) -> Result>, AppError> { let Json(req) = body.map_err(|e| AppError::BadRequest(e.to_string()))?; let agent = state.service.update(&id, req).await?; Ok(Json(ApiResponse::ok(agent))) } async fn delete_one( State(state): State, Extension(_user): Extension, Path(id): Path, ) -> Result>, AppError> { state.service.delete(&id).await?; Ok(Json(ApiResponse::success())) } async fn test_connection( State(state): State, Extension(_user): Extension, body: Result, JsonRejection>, ) -> Result>, AppError> { let Json(req) = body.map_err(|e| AppError::BadRequest(e.to_string()))?; state.service.test_connection(req).await?; Ok(Json(ApiResponse::success())) } async fn handshake( State(state): State, Extension(_user): Extension, Path(id): Path, ) -> Result>, AppError> { let resp = state.service.handshake(&id).await?; Ok(Json(ApiResponse::ok(resp))) }