zoi_resolver/
mini_resolve.rs1use std::collections::HashMap;
7
8use anyhow::{Result, anyhow};
9use colored::Colorize;
10use serde::{Deserialize, Serialize};
11pub use zoi_core::types::MiniVulnerability;
12
13fn default_revision() -> String {
15 "1".to_string()
16}
17
18#[derive(Debug, Serialize, Deserialize, Clone)]
24pub struct MiniPackageIndex {
25 pub repo: String,
27 pub repo_type: String,
29 pub version: String,
31 #[serde(default = "default_revision")]
33 pub revision: String,
34 pub description: String,
36 #[serde(default, deserialize_with = "deserialize_sub_packages")]
38 pub sub_packages: Option<Vec<String>>,
39 pub vuln: Option<Vec<MiniVulnerability>>
41}
42
43fn deserialize_sub_packages<'de, D>(
46 deserializer: D
47) -> Result<Option<Vec<String>>, D::Error>
48where
49 D: serde::Deserializer<'de>
50{
51 let v: serde_json::Value = serde::Deserialize::deserialize(deserializer)?;
52 if v.is_array() {
53 Ok(serde_json::from_value(v).ok())
54 } else {
55 Ok(None)
56 }
57}
58
59#[derive(Debug, Serialize, Deserialize, Clone)]
61pub struct MiniRegistryIndex {
62 pub packages: HashMap<String, MiniPackageIndex>
64}
65
66pub fn fetch_registry_index() -> Result<MiniRegistryIndex> {
75 let url = "https://gitlab.com/zillowe/zillwen/zusty/zoidberg/-/raw/main/packages.json";
76 let client = zoi_core::utils::get_http_client()?;
77 let response = client.get(url).send()?;
78 if !response.status().is_success() {
79 return Err(anyhow!(
80 "Failed to fetch packages.json from Zoidberg registry: {}",
81 response.status()
82 ));
83 }
84 let index: MiniRegistryIndex = response.json()?;
85 Ok(index)
86}
87
88pub fn fetch_registry_config() -> Result<zoi_core::types::RepoConfig> {
94 let url = "https://gitlab.com/zillowe/zillwen/zusty/zoidberg/-/raw/main/repo.yaml";
95 let client = zoi_core::utils::get_http_client()?;
96 let response = client.get(url).send()?;
97 if !response.status().is_success() {
98 return Err(anyhow!(
99 "Failed to fetch repo.yaml from Zoidberg registry: {}",
100 response.status()
101 ));
102 }
103 let content = response.text()?;
104 let config: zoi_core::types::RepoConfig = serde_yaml::from_str(&content)?;
105 Ok(config)
106}
107
108pub fn get_package_lua_url(repo: &str, name: &str) -> String {
111 format!(
112 "https://gitlab.com/zillowe/zillwen/zusty/zoidberg/-/raw/main/{repo}/{name}/{name}.pkg.lua"
113 )
114}
115
116pub fn check_vulnerabilities(
126 pkg_name: &str,
127 pkg_index: &MiniPackageIndex,
128 version: &str
129) -> Result<bool> {
130 let Some(vulns) = &pkg_index.vuln else {
131 return Ok(true);
132 };
133
134 let target_version =
135 semver::Version::parse(version.trim_start_matches('v'))
136 .map_err(|e| anyhow!("Failed to parse version {version}: {e}"))?;
137
138 let mut affected = Vec::new();
139
140 for vuln in vulns {
141 if let Ok(req) = semver::VersionReq::parse(&vuln.affected_range)
142 && req.matches(&target_version)
143 {
144 affected.push(vuln);
145 }
146 }
147
148 if affected.is_empty() {
149 return Ok(true);
150 }
151
152 println!("\n{}", "SECURITY WARNING".red().bold());
153 for vuln in affected {
154 println!(
155 "Package {} v{} is known to be vulnerable:",
156 pkg_name.cyan().bold(),
157 version.red()
158 );
159 println!(
160 "[{}] {} (Severity: {})",
161 vuln.id.dimmed(),
162 vuln.summary,
163 vuln.severity.to_uppercase()
164 );
165 if let Some(fixed) = &vuln.fixed_in {
166 println!("Fixed in version: {}", fixed.green());
167 }
168 println!();
169 }
170
171 Ok(zoi_core::utils::ask_for_confirmation(
172 "Do you want to continue with the installation anyway?",
173 false
174 ))
175}