Add DAST, graph modules, toast notifications, and dashboard enhancements
Add DAST scanning and code knowledge graph features across the stack: - compliance-dast and compliance-graph workspace crates - Agent API handlers and routes for DAST targets/scans and graph builds - Core models and traits for DAST and graph domains - Dashboard pages for DAST targets/findings/overview and graph explorer/impact - Toast notification system with auto-dismiss for async action feedback - Button click animations and disabled states for better UX Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use super::issue::TrackerType;
|
||||
|
||||
@@ -15,21 +15,64 @@ pub enum ScanTrigger {
|
||||
pub struct TrackedRepository {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<bson::oid::ObjectId>,
|
||||
#[serde(default)]
|
||||
pub name: String,
|
||||
#[serde(default)]
|
||||
pub git_url: String,
|
||||
#[serde(default = "default_branch")]
|
||||
pub default_branch: String,
|
||||
pub local_path: Option<String>,
|
||||
pub scan_schedule: Option<String>,
|
||||
#[serde(default)]
|
||||
pub webhook_enabled: bool,
|
||||
pub tracker_type: Option<TrackerType>,
|
||||
pub tracker_owner: Option<String>,
|
||||
pub tracker_repo: Option<String>,
|
||||
pub last_scanned_commit: Option<String>,
|
||||
#[serde(default, deserialize_with = "deserialize_findings_count")]
|
||||
pub findings_count: u32,
|
||||
#[serde(default = "chrono::Utc::now", deserialize_with = "deserialize_datetime")]
|
||||
pub created_at: DateTime<Utc>,
|
||||
#[serde(default = "chrono::Utc::now", deserialize_with = "deserialize_datetime")]
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
fn default_branch() -> String {
|
||||
"main".to_string()
|
||||
}
|
||||
|
||||
/// Handles findings_count stored as either a plain integer or a BSON Int64
|
||||
/// which the driver may present as a map `{"low": N, "high": N, "unsigned": bool}`.
|
||||
/// Handles datetime stored as either a BSON DateTime or an RFC 3339 string.
|
||||
fn deserialize_datetime<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bson = bson::Bson::deserialize(deserializer)?;
|
||||
match bson {
|
||||
bson::Bson::DateTime(dt) => Ok(dt.into()),
|
||||
bson::Bson::String(s) => s
|
||||
.parse::<DateTime<Utc>>()
|
||||
.map_err(serde::de::Error::custom),
|
||||
other => Err(serde::de::Error::custom(format!(
|
||||
"expected DateTime or string, got: {other:?}"
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_findings_count<'de, D>(deserializer: D) -> Result<u32, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bson = bson::Bson::deserialize(deserializer)?;
|
||||
match &bson {
|
||||
bson::Bson::Int32(n) => Ok(*n as u32),
|
||||
bson::Bson::Int64(n) => Ok(*n as u32),
|
||||
bson::Bson::Double(n) => Ok(*n as u32),
|
||||
_ => Ok(0),
|
||||
}
|
||||
}
|
||||
|
||||
impl TrackedRepository {
|
||||
pub fn new(name: String, git_url: String) -> Self {
|
||||
let now = Utc::now();
|
||||
|
||||
Reference in New Issue
Block a user