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