fix: pentest session ID propagation, target name resolution, BSON field paths

- Set session.id from insert_one result so orchestrator has the ID
- Enrich sessions with target_name by joining DAST targets in server fns
- Fix _id.$oid BSON field path for target dropdown and session list
- Fix send_message URL to /chat (was /messages)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-03-11 21:48:54 +01:00
parent af98e3e070
commit 30301a12b5
3 changed files with 76 additions and 7 deletions

View File

@@ -76,7 +76,7 @@ pub async fn create_session(
let mut session = PentestSession::new(req.target_id.clone(), strategy);
session.repo_id = target.repo_id.clone();
agent
let insert_result = agent
.db
.pentest_sessions()
.insert_one(&session)
@@ -88,6 +88,9 @@ pub async fn create_session(
)
})?;
// Set the generated ID back on the session so the orchestrator has it
session.id = insert_result.inserted_id.as_object_id();
let initial_message = req.message.unwrap_or_else(|| {
format!(
"Begin a {} penetration test against {} ({}). \

View File

@@ -34,14 +34,50 @@ pub struct AttackChainResponse {
pub async fn fetch_pentest_sessions() -> Result<PentestSessionsResponse, ServerFnError> {
let state: super::server_state::ServerState =
dioxus_fullstack::FullstackContext::extract().await?;
// Fetch sessions
let url = format!("{}/api/v1/pentest/sessions", state.agent_api_url);
let resp = reqwest::get(&url)
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let body: PentestSessionsResponse = resp
let mut body: PentestSessionsResponse = resp
.json()
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
// Fetch DAST targets to resolve target names
let targets_url = format!("{}/api/v1/dast/targets", state.agent_api_url);
if let Ok(tresp) = reqwest::get(&targets_url).await {
if let Ok(tbody) = tresp.json::<serde_json::Value>().await {
let targets = tbody.get("data").and_then(|v| v.as_array());
if let Some(targets) = targets {
// Build target_id -> name lookup
let target_map: std::collections::HashMap<String, String> = targets
.iter()
.filter_map(|t| {
let id = t.get("_id")?.get("$oid")?.as_str()?.to_string();
let name = t.get("name")?.as_str()?.to_string();
Some((id, name))
})
.collect();
// Enrich sessions with target_name
for session in body.data.iter_mut() {
if let Some(tid) = session.get("target_id").and_then(|v| v.as_str()) {
if let Some(name) = target_map.get(tid) {
session.as_object_mut().map(|obj| {
obj.insert(
"target_name".to_string(),
serde_json::Value::String(name.clone()),
)
});
}
}
}
}
}
}
Ok(body)
}
@@ -53,10 +89,33 @@ pub async fn fetch_pentest_session(id: String) -> Result<PentestSessionResponse,
let resp = reqwest::get(&url)
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
let body: PentestSessionResponse = resp
let mut body: PentestSessionResponse = resp
.json()
.await
.map_err(|e| ServerFnError::new(e.to_string()))?;
// Resolve target name from targets list
if let Some(tid) = body.data.get("target_id").and_then(|v| v.as_str()) {
let targets_url = format!("{}/api/v1/dast/targets", state.agent_api_url);
if let Ok(tresp) = reqwest::get(&targets_url).await {
if let Ok(tbody) = tresp.json::<serde_json::Value>().await {
if let Some(targets) = tbody.get("data").and_then(|v| v.as_array()) {
for t in targets {
let t_id = t.get("_id").and_then(|v| v.get("$oid")).and_then(|v| v.as_str()).unwrap_or("");
if t_id == tid {
if let Some(name) = t.get("name").and_then(|v| v.as_str()) {
body.data.as_object_mut().map(|obj| {
obj.insert("target_name".to_string(), serde_json::Value::String(name.to_string()))
});
}
break;
}
}
}
}
}
}
Ok(body)
}
@@ -150,7 +209,7 @@ pub async fn send_pentest_message(
let state: super::server_state::ServerState =
dioxus_fullstack::FullstackContext::extract().await?;
let url = format!(
"{}/api/v1/pentest/sessions/{session_id}/messages",
"{}/api/v1/pentest/sessions/{session_id}/chat",
state.agent_api_url
);
let client = reqwest::Client::new();

View File

@@ -34,7 +34,8 @@ pub fn PentestDashboardPage() -> Element {
Ok(resp) => {
let session_id = resp
.data
.get("id")
.get("_id")
.and_then(|v| v.get("$oid"))
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
@@ -241,7 +242,10 @@ pub fn PentestDashboardPage() -> Element {
div { style: "display: grid; gap: 12px; padding: 16px;",
for session in sess_list {
{
let id = session.get("id").and_then(|v| v.as_str()).unwrap_or("-").to_string();
let id = session.get("_id")
.and_then(|v| v.get("$oid"))
.and_then(|v| v.as_str())
.unwrap_or("-").to_string();
let target_name = session.get("target_name").and_then(|v| v.as_str()).unwrap_or("Unknown Target").to_string();
let status = session.get("status").and_then(|v| v.as_str()).unwrap_or("unknown").to_string();
let strategy = session.get("strategy").and_then(|v| v.as_str()).unwrap_or("-").to_string();
@@ -329,7 +333,10 @@ pub fn PentestDashboardPage() -> Element {
rsx! {
for target in &data.data {
{
let tid = target.get("id").and_then(|v| v.as_str()).unwrap_or("").to_string();
let tid = target.get("_id")
.and_then(|v| v.get("$oid"))
.and_then(|v| v.as_str())
.unwrap_or("").to_string();
let tname = target.get("name").and_then(|v| v.as_str()).unwrap_or("Unknown").to_string();
let turl = target.get("base_url").and_then(|v| v.as_str()).unwrap_or("").to_string();
rsx! {