vika_cli/config/
validator.rs

1use crate::config::model::Config;
2use crate::error::{ConfigError, Result};
3use std::path::{Path, PathBuf};
4
5pub fn validate_config(config: &Config) -> Result<()> {
6    // Validate root_dir
7    let root_dir = PathBuf::from(&config.root_dir);
8    if root_dir.is_absolute() && !root_dir.exists() {
9        return Err(ConfigError::Invalid {
10            message: format!("Root directory does not exist: {}", config.root_dir),
11        }
12        .into());
13    }
14
15    // Validate schemas output path
16    let schemas_output = PathBuf::from(&config.schemas.output);
17    if schemas_output.is_absolute() {
18        validate_safe_path(&schemas_output)?;
19    }
20
21    // Validate apis output path
22    let apis_output = PathBuf::from(&config.apis.output);
23    if apis_output.is_absolute() {
24        validate_safe_path(&apis_output)?;
25    }
26
27    // Validate style
28    if config.apis.style != "fetch" {
29        return Err(ConfigError::Invalid {
30            message: format!(
31                "Unsupported API style: {}. Only 'fetch' is supported.",
32                config.apis.style
33            ),
34        }
35        .into());
36    }
37
38    Ok(())
39}
40
41fn validate_safe_path(path: &Path) -> Result<()> {
42    // Prevent writing to system directories
43    let path_str = path.to_string_lossy();
44
45    if path_str.contains("/etc/")
46        || path_str.contains("/usr/")
47        || path_str.contains("/bin/")
48        || path_str.contains("/sbin/")
49        || path_str.contains("/var/")
50        || path_str.contains("/opt/")
51        || path_str == "/"
52        || path_str == "/root"
53    {
54        return Err(ConfigError::InvalidOutputDirectory {
55            path: path_str.to_string(),
56        }
57        .into());
58    }
59
60    Ok(())
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66    use crate::config::model::Config;
67
68    #[test]
69    fn test_validate_config_valid() {
70        let config = Config::default();
71        assert!(validate_config(&config).is_ok());
72    }
73
74    #[test]
75    fn test_validate_config_invalid_style() {
76        let mut config = Config::default();
77        config.apis.style = "invalid".to_string();
78
79        let result = validate_config(&config);
80        assert!(result.is_err());
81        let error = result.unwrap_err();
82        assert!(error.to_string().contains("Unsupported API style"));
83    }
84}