use super::{
AnalyticsCommand, ApiServerCommand, Command, CtLogsCommand, DatabaseCommand, MassScanCommand,
MonitorCommand, MxTestCommand, ScanCommand,
};
use crate::{Args, Result, TlsError};
pub struct CommandRouter;
impl CommandRouter {
pub fn route(args: Args) -> Result<Box<dyn Command>> {
if args.api_server.enable {
return Ok(Box::new(ApiServerCommand::new(args)));
}
if args.monitoring.enable || args.monitoring.test_alert {
return Ok(Box::new(MonitorCommand::new(args)));
}
if args.ct_logs.enable {
return Ok(Box::new(CtLogsCommand::new(args)));
}
if args.compare.is_some()
|| args.changes.is_some()
|| args.trends.is_some()
|| args.dashboard.is_some()
{
return Ok(Box::new(AnalyticsCommand::new(args)));
}
if (args.database.init
|| args.database.cleanup_days.is_some()
|| args.database.history.is_some())
&& args.target.is_none()
&& args.input_file.is_none()
&& args.mx_domain.is_none()
{
return Ok(Box::new(DatabaseCommand::new(args)));
}
if args.mx_domain.is_some() {
return Ok(Box::new(MxTestCommand::new(args)));
}
if args.input_file.is_some() {
return Ok(Box::new(MassScanCommand::new(args)));
}
Ok(Box::new(ScanCommand::new(args)))
}
pub fn validate_routing(args: &Args) -> Result<()> {
let mode_count = [
args.api_server.enable,
args.monitoring.enable || args.monitoring.test_alert,
args.ct_logs.enable,
args.compare.is_some()
|| args.changes.is_some()
|| args.trends.is_some()
|| args.dashboard.is_some(),
]
.iter()
.filter(|&&x| x)
.count();
if mode_count > 1 {
return Err(TlsError::InvalidInput {
message: "Cannot combine multiple operational modes (--serve, --monitor, --ct-logs, analytics)".to_string(),
});
}
if args.mx_domain.is_some() && args.input_file.is_some() {
return Err(TlsError::InvalidInput {
message: "Cannot use --mx with --file. Choose one scanning mode.".to_string(),
});
}
if args.target.is_some() && args.input_file.is_some() {
return Err(TlsError::InvalidInput {
message: "Cannot specify both target and --file. Choose one scanning mode."
.to_string(),
});
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_route_api_server() {
let mut args = Args::default();
args.api_server.enable = true;
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "ApiServerCommand");
}
#[test]
fn test_route_monitor() {
let mut args = Args::default();
args.monitoring.enable = true;
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "MonitorCommand");
}
#[test]
fn test_route_ct_logs() {
let mut args = Args::default();
args.ct_logs.enable = true;
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "CtLogsCommand");
}
#[test]
fn test_route_analytics() {
let mut args = Args::default();
args.compare = Some("1:2".to_string());
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "AnalyticsCommand");
}
#[test]
fn test_route_database() {
let mut args = Args::default();
args.database.init = true;
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "DatabaseCommand");
}
#[test]
fn test_route_mx_test() {
let mut args = Args::default();
args.mx_domain = Some("example.com".to_string());
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "MxTestCommand");
}
#[test]
fn test_route_mass_scan() {
let mut args = Args::default();
args.input_file = Some(std::path::PathBuf::from("targets.txt"));
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "MassScanCommand");
}
#[test]
fn test_route_scan_default() {
let args = Args::default();
let cmd = CommandRouter::route(args).expect("test assertion should succeed");
assert_eq!(cmd.name(), "ScanCommand");
}
#[test]
fn test_validate_conflicting_modes() {
let mut args = Args::default();
args.api_server.enable = true;
args.monitoring.enable = true;
let result = CommandRouter::validate_routing(&args);
assert!(result.is_err());
}
#[test]
fn test_validate_mx_file_conflict() {
let mut args = Args::default();
args.mx_domain = Some("example.com".to_string());
args.input_file = Some(std::path::PathBuf::from("targets.txt"));
let result = CommandRouter::validate_routing(&args);
assert!(result.is_err());
}
}