use serde::{Deserialize, Serialize};
use std::fmt;
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
Critical,
High,
Medium,
Low,
Info,
}
impl Severity {
pub fn rank(self) -> u8 {
match self {
Severity::Critical => 4,
Severity::High => 3,
Severity::Medium => 2,
Severity::Low => 1,
Severity::Info => 0,
}
}
pub fn as_str(self) -> &'static str {
match self {
Severity::Critical => "critical",
Severity::High => "high",
Severity::Medium => "medium",
Severity::Low => "low",
Severity::Info => "info",
}
}
}
impl fmt::Display for Severity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default)]
#[serde(rename_all = "lowercase")]
pub enum Status {
#[default]
Open,
Resolved,
Accepted,
#[serde(rename = "false_positive")]
FalsePositive,
}
impl Status {
pub fn as_str(self) -> &'static str {
match self {
Status::Open => "open",
Status::Resolved => "resolved",
Status::Accepted => "accepted",
Status::FalsePositive => "false_positive",
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Finding {
pub id: String,
pub title: String,
pub severity: Severity,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cvss: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cvss_vector: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cwe: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub owasp: Option<String>,
#[serde(default)]
pub status: Status,
#[serde(default)]
pub affected_assets: Vec<String>,
#[serde(default)]
pub tags: Vec<String>,
pub body_markdown: String,
pub body_html: String,
pub source_path: PathBuf,
#[serde(default)]
pub images: Vec<ImageRef>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ImageRef {
pub alt: String,
pub markdown_src: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub resolved_path: Option<PathBuf>,
}