zoi_resolver/
mini_resolve.rs1use anyhow::{Result, anyhow};
2use colored::*;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5pub use zoi_core::types::MiniVulnerability;
6
7fn default_revision() -> String {
8 "1".to_string()
9}
10
11#[derive(Debug, Serialize, Deserialize, Clone)]
16pub struct MiniPackageIndex {
17 pub repo: String,
18 pub repo_type: String,
19 pub version: String,
20 #[serde(default = "default_revision")]
21 pub revision: String,
22 pub description: String,
23 #[serde(default, deserialize_with = "deserialize_sub_packages")]
24 pub sub_packages: Option<Vec<String>>,
25 pub vuln: Option<Vec<MiniVulnerability>>,
26}
27
28fn deserialize_sub_packages<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
29where
30 D: serde::Deserializer<'de>,
31{
32 let v: serde_json::Value = serde::Deserialize::deserialize(deserializer)?;
33 if v.is_array() {
34 Ok(serde_json::from_value(v).ok())
35 } else {
36 Ok(None)
37 }
38}
39
40#[derive(Debug, Serialize, Deserialize, Clone)]
41pub struct MiniRegistryIndex {
42 pub packages: HashMap<String, MiniPackageIndex>,
43}
44
45pub fn fetch_registry_index() -> Result<MiniRegistryIndex> {
50 let url = "https://gitlab.com/zillowe/zillwen/zusty/zoidberg/-/raw/main/packages.json";
51 let client = zoi_core::utils::get_http_client()?;
52 let response = client.get(url).send()?;
53 if !response.status().is_success() {
54 return Err(anyhow!(
55 "Failed to fetch packages.json from Zoidberg registry: {}",
56 response.status()
57 ));
58 }
59 let index: MiniRegistryIndex = response.json()?;
60 Ok(index)
61}
62
63pub fn fetch_registry_config() -> Result<zoi_core::types::RepoConfig> {
64 let url = "https://gitlab.com/zillowe/zillwen/zusty/zoidberg/-/raw/main/repo.yaml";
65 let client = zoi_core::utils::get_http_client()?;
66 let response = client.get(url).send()?;
67 if !response.status().is_success() {
68 return Err(anyhow!(
69 "Failed to fetch repo.yaml from Zoidberg registry: {}",
70 response.status()
71 ));
72 }
73 let content = response.text()?;
74 let config: zoi_core::types::RepoConfig = serde_yaml::from_str(&content)?;
75 Ok(config)
76}
77
78pub fn get_package_lua_url(repo: &str, name: &str) -> String {
79 format!(
80 "https://gitlab.com/zillowe/zillwen/zusty/zoidberg/-/raw/main/{}/{}/{}.pkg.lua",
81 repo, name, name
82 )
83}
84
85pub fn check_vulnerabilities(
90 pkg_name: &str,
91 pkg_index: &MiniPackageIndex,
92 version: &str,
93) -> Result<bool> {
94 let Some(vulns) = &pkg_index.vuln else {
95 return Ok(true);
96 };
97
98 let target_version = semver::Version::parse(version.trim_start_matches('v'))
99 .map_err(|e| anyhow!("Failed to parse version {}: {}", version, e))?;
100
101 let mut affected = Vec::new();
102
103 for vuln in vulns {
104 if let Ok(req) = semver::VersionReq::parse(&vuln.affected_range)
105 && req.matches(&target_version)
106 {
107 affected.push(vuln);
108 }
109 }
110
111 if affected.is_empty() {
112 return Ok(true);
113 }
114
115 println!("\n{}", "SECURITY WARNING".red().bold());
116 for vuln in affected {
117 println!(
118 "Package {} v{} is known to be vulnerable:",
119 pkg_name.cyan().bold(),
120 version.red()
121 );
122 println!(
123 "[{}] {} (Severity: {})",
124 vuln.id.dimmed(),
125 vuln.summary,
126 vuln.severity.to_uppercase()
127 );
128 if let Some(fixed) = &vuln.fixed_in {
129 println!("Fixed in version: {}", fixed.green());
130 }
131 println!();
132 }
133
134 Ok(zoi_core::utils::ask_for_confirmation(
135 "Do you want to continue with the installation anyway?",
136 false,
137 ))
138}