use crate::files_proc::model::input_file_type::InputFileType;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
#[cfg(feature = "cli")]
use super::super::pdf::font_config::FontsDir;
#[cfg(feature = "cli")]
use super::env_vars::EnvVarNames;
#[cfg(feature = "cli")]
use super::run_utils::get_version_info;
#[cfg(feature = "cli")]
use crate::lib_utils::cli_args::CliArgs;
#[cfg(feature = "cli")]
use crate::lib_utils::errors::Vex2PdfError;
#[cfg(feature = "cli")]
use clap::Parser;
#[cfg(feature = "cli")]
use log::{info, warn};
pub struct Config {
pub working_path: PathBuf,
pub output_dir: PathBuf,
pub show_novulns_msg: bool,
pub file_types_to_process: Option<HashMap<InputFileType, bool>>,
pub pure_bom_novulns: bool,
pub show_components: bool,
pub report_title: Option<String>,
pub pdf_meta_name: Option<String>,
pub max_jobs: Option<u8>,
}
impl Config {
#[cfg(feature = "cli")]
pub fn build_with_env_cli() -> Result<Self, Vex2PdfError> {
let args = CliArgs::parse();
if args.license {
return Err(Vex2PdfError::VoluntaryLicenseDisplayInterruption);
}
args.validate()?;
info!("{}", get_version_info());
info!("");
let working_path = args.input.unwrap_or(std::env::current_dir()?);
let output_dir = args.output_dir.unwrap_or(std::env::current_dir()?);
let show_novulns_msg = args
.show_novulns_msg
.unwrap_or(EnvVarNames::NoVulnsMsg.is_on_or_unset());
let mut process_json = EnvVarNames::ProcessJson.is_on_or_unset();
let process_xml = EnvVarNames::ProcessXml.is_on_or_unset();
let show_pure_bom_novulns = args
.pure_bom_novulns
.unwrap_or(EnvVarNames::PureBomNoVulns.is_on());
let show_comps = args
.show_components
.unwrap_or(EnvVarNames::ShowComponentList.is_on_or_unset());
let report_title_override = args
.report_title
.map(Some)
.unwrap_or(EnvVarNames::ReportTitle.get_value());
let pdf_meta_name_override = args
.meta_name
.map(Some)
.unwrap_or(EnvVarNames::PdfName.get_value());
#[cfg(feature = "concurrency")]
let max_jobs = args.max_jobs;
#[cfg(not(feature = "concurrency"))]
let max_jobs = None;
FontsDir::print_fonts_info();
EnvVarNames::print_report_titles_info();
if !(process_json || process_xml) {
warn!("**** WARNING: we cannot have both json and xml deactivated. defaulting to json processing");
process_json = true;
}
let mut file_types_to_process: HashMap<InputFileType, bool> = HashMap::new();
file_types_to_process.insert(InputFileType::JSON, process_json);
file_types_to_process.insert(InputFileType::XML, process_xml);
let config = Config {
working_path,
output_dir,
show_novulns_msg,
file_types_to_process: Some(file_types_to_process),
pure_bom_novulns: show_pure_bom_novulns,
show_components: show_comps,
report_title: report_title_override,
pdf_meta_name: pdf_meta_name_override,
max_jobs,
};
Ok(config)
}
pub fn get_default_pdf_meta_name() -> &'static str {
"VEX Vulnerability Report"
}
pub fn get_default_report_title() -> &'static str {
"Vulnerability Report Document"
}
pub fn working_path(mut self, path: impl AsRef<Path>) -> Self {
self.working_path = path.as_ref().to_path_buf();
self
}
pub fn output_dir(mut self, path: impl AsRef<Path>) -> Self {
self.output_dir = path.as_ref().to_path_buf();
self
}
pub fn show_novulns_msg(mut self, show: bool) -> Self {
self.show_novulns_msg = show;
self
}
pub fn file_types_to_process(mut self, types: Option<HashMap<InputFileType, bool>>) -> Self {
self.file_types_to_process = types;
self
}
pub fn pure_bom_novulns(mut self, pure_bom: bool) -> Self {
self.pure_bom_novulns = pure_bom;
self
}
pub fn show_components(mut self, show: bool) -> Self {
self.show_components = show;
self
}
pub fn report_title(mut self, title: impl Into<String>) -> Self {
self.report_title = Some(title.into());
self
}
pub fn pdf_meta_name(mut self, name: impl Into<String>) -> Self {
self.pdf_meta_name = Some(name.into());
self
}
pub fn max_jobs(mut self, jobs: Option<u8>) -> Self {
self.max_jobs = jobs;
self
}
}
impl Default for Config {
fn default() -> Self {
let mut file_types_to_process: HashMap<InputFileType, bool> = HashMap::new();
file_types_to_process.insert(InputFileType::JSON, true);
file_types_to_process.insert(InputFileType::XML, true);
let working_path = std::env::current_dir().expect("Failed to get current directory");
let output_dir = working_path.clone();
Self {
working_path,
output_dir,
show_novulns_msg: true,
file_types_to_process: Some(file_types_to_process),
pure_bom_novulns: false,
show_components: true,
report_title: Some(Self::get_default_report_title().to_string()),
pdf_meta_name: Some(Self::get_default_pdf_meta_name().to_string()),
max_jobs: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builder_working_path() {
let config = Config::default().working_path("/tmp/test");
assert_eq!(config.working_path, PathBuf::from("/tmp/test"));
}
#[test]
fn test_builder_output_dir() {
let config = Config::default().output_dir("/tmp/output");
assert_eq!(config.output_dir, PathBuf::from("/tmp/output"));
}
#[test]
fn test_builder_show_novulns_msg() {
let config = Config::default().show_novulns_msg(false);
assert_eq!(config.show_novulns_msg, false);
}
#[test]
fn test_builder_pure_bom_novulns() {
let config = Config::default().pure_bom_novulns(true);
assert_eq!(config.pure_bom_novulns, true);
}
#[test]
fn test_builder_show_components() {
let config = Config::default().show_components(false);
assert_eq!(config.show_components, false);
}
#[test]
fn test_builder_report_title() {
let config = Config::default().report_title("Custom Title");
assert_eq!(config.report_title, Some("Custom Title".to_string()));
}
#[test]
fn test_builder_pdf_meta_name() {
let config = Config::default().pdf_meta_name("Custom Meta");
assert_eq!(config.pdf_meta_name, Some("Custom Meta".to_string()));
}
#[test]
fn test_builder_max_jobs() {
let config = Config::default().max_jobs(Some(4));
assert_eq!(config.max_jobs, Some(4));
}
#[test]
fn test_builder_chaining() {
let config = Config::default()
.working_path("/tmp/input")
.output_dir("/tmp/output")
.max_jobs(Some(2))
.report_title("Chained Config")
.show_components(false);
assert_eq!(config.working_path, PathBuf::from("/tmp/input"));
assert_eq!(config.output_dir, PathBuf::from("/tmp/output"));
assert_eq!(config.max_jobs, Some(2));
assert_eq!(config.report_title, Some("Chained Config".to_string()));
assert_eq!(config.show_components, false);
}
#[test]
fn test_default_values() {
let config = Config::default();
assert_eq!(config.show_novulns_msg, true);
assert_eq!(config.show_components, true);
assert_eq!(config.pure_bom_novulns, false);
assert!(config.working_path.exists());
}
#[test]
fn test_get_default_titles() {
assert_eq!(
Config::get_default_report_title(),
"Vulnerability Report Document"
);
assert_eq!(
Config::get_default_pdf_meta_name(),
"VEX Vulnerability Report"
);
}
}