Some checks failed
CI / Format (push) Successful in 2s
CI / Clippy (push) Failing after 1m23s
CI / Security Audit (push) Has been skipped
CI / Tests (push) Has been skipped
CI / Clippy (pull_request) Failing after 1m18s
CI / Security Audit (pull_request) Has been skipped
CI / Tests (pull_request) Has been skipped
CI / Format (pull_request) Successful in 3s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
101 lines
2.9 KiB
Rust
101 lines
2.9 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Deserializer, Serialize};
|
|
|
|
use super::issue::TrackerType;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum ScanTrigger {
|
|
Scheduled,
|
|
Webhook,
|
|
Manual,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
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();
|
|
Self {
|
|
id: None,
|
|
name,
|
|
git_url,
|
|
default_branch: "main".to_string(),
|
|
local_path: None,
|
|
scan_schedule: None,
|
|
webhook_enabled: false,
|
|
tracker_type: None,
|
|
tracker_owner: None,
|
|
tracker_repo: None,
|
|
last_scanned_commit: None,
|
|
findings_count: 0,
|
|
created_at: now,
|
|
updated_at: now,
|
|
}
|
|
}
|
|
}
|