refactor: rip out the legacy TrackedRepository / repositories path (#161)
CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 3s
CI / Deploy Agent (push) Successful in 8m20s
CI / Deploy Dashboard (push) Successful in 3m13s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2m7s
CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 3s
CI / Deploy Agent (push) Successful in 8m20s
CI / Deploy Dashboard (push) Successful in 3m13s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2m7s
This commit was merged in pull request #161.
This commit is contained in:
@@ -246,15 +246,116 @@ pub async fn delete_target(
|
||||
.delete_one(doc! { "_id": oid })
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
// Cascade the collections keyed by repo_id == target id (best-effort).
|
||||
let by_repo = doc! { "repo_id": &id };
|
||||
let _ = db.findings().delete_many(by_repo.clone()).await;
|
||||
let _ = db.scan_runs().delete_many(by_repo.clone()).await;
|
||||
let _ = db.sbom_entries().delete_many(by_repo.clone()).await;
|
||||
let _ = db.cve_alerts().delete_many(by_repo).await;
|
||||
// Cascade all data keyed by repo_id == target id (best-effort).
|
||||
let db = &db;
|
||||
let _ = db.findings().delete_many(doc! { "repo_id": &id }).await;
|
||||
let _ = db.sbom_entries().delete_many(doc! { "repo_id": &id }).await;
|
||||
let _ = db.scan_runs().delete_many(doc! { "repo_id": &id }).await;
|
||||
let _ = db.cve_alerts().delete_many(doc! { "repo_id": &id }).await;
|
||||
let _ = db
|
||||
.tracker_issues()
|
||||
.delete_many(doc! { "repo_id": &id })
|
||||
.await;
|
||||
let _ = db.graph_nodes().delete_many(doc! { "repo_id": &id }).await;
|
||||
let _ = db.graph_edges().delete_many(doc! { "repo_id": &id }).await;
|
||||
let _ = db.graph_builds().delete_many(doc! { "repo_id": &id }).await;
|
||||
let _ = db
|
||||
.impact_analyses()
|
||||
.delete_many(doc! { "repo_id": &id })
|
||||
.await;
|
||||
let _ = db
|
||||
.code_embeddings()
|
||||
.delete_many(doc! { "repo_id": &id })
|
||||
.await;
|
||||
let _ = db
|
||||
.embedding_builds()
|
||||
.delete_many(doc! { "repo_id": &id })
|
||||
.await;
|
||||
|
||||
// DAST targets linked to this target, and all their downstream data.
|
||||
if let Ok(mut cursor) = db.dast_targets().find(doc! { "repo_id": &id }).await {
|
||||
use futures_util::StreamExt;
|
||||
while let Some(Ok(dt)) = cursor.next().await {
|
||||
let dast_target_id = dt.id.map(|oid| oid.to_hex()).unwrap_or_default();
|
||||
if !dast_target_id.is_empty() {
|
||||
cascade_delete_dast_target(db, &dast_target_id).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pentest sessions linked directly to this target (not via a DAST target).
|
||||
if let Ok(mut cursor) = db.pentest_sessions().find(doc! { "repo_id": &id }).await {
|
||||
use futures_util::StreamExt;
|
||||
while let Some(Ok(session)) = cursor.next().await {
|
||||
let session_id = session.id.map(|oid| oid.to_hex()).unwrap_or_default();
|
||||
if !session_id.is_empty() {
|
||||
let _ = db
|
||||
.attack_chain_nodes()
|
||||
.delete_many(doc! { "session_id": &session_id })
|
||||
.await;
|
||||
let _ = db
|
||||
.pentest_messages()
|
||||
.delete_many(doc! { "session_id": &session_id })
|
||||
.await;
|
||||
let _ = db
|
||||
.dast_findings()
|
||||
.delete_many(doc! { "session_id": &session_id })
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = db
|
||||
.pentest_sessions()
|
||||
.delete_many(doc! { "repo_id": &id })
|
||||
.await;
|
||||
|
||||
Ok(Json(serde_json::json!({ "status": "deleted" })))
|
||||
}
|
||||
|
||||
/// Delete a DAST target and everything downstream of it (pentest sessions +
|
||||
/// their attack chains / messages / findings, DAST scan runs + findings).
|
||||
async fn cascade_delete_dast_target(db: &crate::database::Database, target_id: &str) {
|
||||
use futures_util::StreamExt;
|
||||
if let Ok(mut cursor) = db
|
||||
.pentest_sessions()
|
||||
.find(doc! { "target_id": target_id })
|
||||
.await
|
||||
{
|
||||
while let Some(Ok(session)) = cursor.next().await {
|
||||
let session_id = session.id.map(|oid| oid.to_hex()).unwrap_or_default();
|
||||
if !session_id.is_empty() {
|
||||
let _ = db
|
||||
.attack_chain_nodes()
|
||||
.delete_many(doc! { "session_id": &session_id })
|
||||
.await;
|
||||
let _ = db
|
||||
.pentest_messages()
|
||||
.delete_many(doc! { "session_id": &session_id })
|
||||
.await;
|
||||
let _ = db
|
||||
.dast_findings()
|
||||
.delete_many(doc! { "session_id": &session_id })
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = db
|
||||
.pentest_sessions()
|
||||
.delete_many(doc! { "target_id": target_id })
|
||||
.await;
|
||||
let _ = db
|
||||
.dast_findings()
|
||||
.delete_many(doc! { "target_id": target_id })
|
||||
.await;
|
||||
let _ = db
|
||||
.dast_scan_runs()
|
||||
.delete_many(doc! { "target_id": target_id })
|
||||
.await;
|
||||
if let Ok(oid) = mongodb::bson::oid::ObjectId::parse_str(target_id) {
|
||||
let _ = db.dast_targets().delete_one(doc! { "_id": oid }).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// POST /api/v1/targets/{id}/artifacts — attach an artifact (by reference).
|
||||
#[tracing::instrument(skip_all, fields(target_id = %id))]
|
||||
pub async fn add_artifact(
|
||||
|
||||
Reference in New Issue
Block a user