Refactor package install command to only accept verified packages by default

This commit is contained in:
Federico Terzi 2020-03-20 19:54:03 +01:00
parent 06476fd344
commit 80f12194db
7 changed files with 108 additions and 31 deletions

View File

@ -79,6 +79,12 @@ fn main() {
.required(false) .required(false)
.takes_value(false) .takes_value(false)
.help("Install packages avoiding the GIT package provider. Try this flag if the default mode is not working.")) .help("Install packages avoiding the GIT package provider. Try this flag if the default mode is not working."))
.arg(Arg::with_name("external")
.short("e")
.long("external")
.required(false)
.takes_value(false)
.help("Allow installing packages from non-verified repositories."))
.arg(Arg::with_name("package_name") .arg(Arg::with_name("package_name")
.help("Package name")); .help("Package name"));
@ -766,6 +772,13 @@ fn install_main(_config_set: ConfigSet, matches: &ArgMatches) {
Box::new(GitPackageResolver::new()) Box::new(GitPackageResolver::new())
}; };
let allow_external: bool = if matches.is_present("external") {
println!("Allowing external repositories");
true
}else{
false
};
let mut package_manager = DefaultPackageManager::new_default(Some(package_resolver)); let mut package_manager = DefaultPackageManager::new_default(Some(package_resolver));
if package_manager.is_index_outdated() { if package_manager.is_index_outdated() {
@ -792,7 +805,7 @@ fn install_main(_config_set: ConfigSet, matches: &ArgMatches) {
println!("Using cached package index, run 'espanso package refresh' to update it.") println!("Using cached package index, run 'espanso package refresh' to update it.")
} }
let res = package_manager.install_package(package_name); let res = package_manager.install_package(package_name, allow_external);
match res { match res {
Ok(install_result) => { Ok(install_result) => {
@ -812,6 +825,22 @@ fn install_main(_config_set: ConfigSet, matches: &ArgMatches) {
InstallResult::AlreadyInstalled => { InstallResult::AlreadyInstalled => {
eprintln!("{} already installed!", package_name); eprintln!("{} already installed!", package_name);
}, },
InstallResult::BlockedExternalPackage(repo_url) => {
eprintln!("Warning: the requested package is hosted on an external repository:");
eprintln!();
eprintln!("{}", repo_url);
eprintln!();
eprintln!("and its contents may not have been verified by espanso.");
eprintln!();
eprintln!("For your security, espanso blocks packages that are not verified.");
eprintln!("If you want to install the package anyway, you can force espanso");
eprintln!("to install it with the following command, but please do it only");
eprintln!("if you trust the source or you verified the contents of the package");
eprintln!("by checking out the repository listed above.");
eprintln!();
eprintln!("espanso install {} --external", package_name);
eprintln!();
}
InstallResult::Installed => { InstallResult::Installed => {
println!("{} successfully installed!", package_name); println!("{} successfully installed!", package_name);
println!(); println!();

View File

@ -24,7 +24,7 @@ use std::fs::{File, create_dir};
use std::io::{BufReader, BufRead}; use std::io::{BufReader, BufRead};
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use crate::package::UpdateResult::{NotOutdated, Updated}; use crate::package::UpdateResult::{NotOutdated, Updated};
use crate::package::InstallResult::{NotFoundInIndex, AlreadyInstalled}; use crate::package::InstallResult::{NotFoundInIndex, AlreadyInstalled, BlockedExternalPackage};
use std::fs; use std::fs;
use tempfile::TempDir; use tempfile::TempDir;
use git2::Repository; use git2::Repository;
@ -138,13 +138,31 @@ impl DefaultPackageManager {
return None return None
} }
let original_repo = if fields.contains_key("package_original_repo") {
fields.get("package_original_repo").unwrap().clone()
}else{
fields.get("package_repo").unwrap().clone()
};
let is_core = if fields.contains_key("is_core") {
match fields.get("is_core").unwrap().clone().as_ref() {
"true" => true,
"false" => false,
_ => false,
}
}else{
false
};
let package = Package { let package = Package {
name: fields.get("package_name").unwrap().clone(), name: fields.get("package_name").unwrap().clone(),
title: fields.get("package_title").unwrap().clone(), title: fields.get("package_title").unwrap().clone(),
version: fields.get("package_version").unwrap().clone(), version: fields.get("package_version").unwrap().clone(),
repo: fields.get("package_repo").unwrap().clone(), repo: fields.get("package_repo").unwrap().clone(),
desc: fields.get("package_desc").unwrap().clone(), desc: fields.get("package_desc").unwrap().clone(),
author: fields.get("package_author").unwrap().clone() author: fields.get("package_author").unwrap().clone(),
is_core,
original_repo
}; };
Some(package) Some(package)
@ -228,11 +246,15 @@ impl super::PackageManager for DefaultPackageManager {
None None
} }
fn install_package(&self, name: &str) -> Result<InstallResult, Box<dyn Error>> { fn install_package(&self, name: &str, allow_external: bool) -> Result<InstallResult, Box<dyn Error>> {
let package = self.get_package(name); let package = self.get_package(name);
match package { match package {
Some(package) => { Some(package) => {
if package.is_core || allow_external {
self.install_package_from_repo(name, &package.repo) self.install_package_from_repo(name, &package.repo)
}else{
Ok(BlockedExternalPackage(package.original_repo))
}
}, },
None => { None => {
Ok(NotFoundInIndex) Ok(NotFoundInIndex)
@ -451,7 +473,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("doesnotexist").unwrap(), NotFoundInIndex); assert_eq!(temp.package_manager.install_package("doesnotexist", false).unwrap(), NotFoundInIndex);
} }
#[test] #[test]
@ -462,7 +484,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("italian-accents").unwrap(), AlreadyInstalled); assert_eq!(temp.package_manager.install_package("italian-accents", false).unwrap(), AlreadyInstalled);
} }
#[test] #[test]
@ -472,7 +494,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("dummy-package").unwrap(), Installed); assert_eq!(temp.package_manager.install_package("dummy-package", false).unwrap(), Installed);
assert!(temp.package_dir.path().join("dummy-package").exists()); assert!(temp.package_dir.path().join("dummy-package").exists());
assert!(temp.package_dir.path().join("dummy-package/README.md").exists()); assert!(temp.package_dir.path().join("dummy-package/README.md").exists());
assert!(temp.package_dir.path().join("dummy-package/package.yml").exists()); assert!(temp.package_dir.path().join("dummy-package/package.yml").exists());
@ -485,7 +507,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("not-existing").unwrap(), NotFoundInRepo); assert_eq!(temp.package_manager.install_package("not-existing", false).unwrap(), NotFoundInRepo);
} }
#[test] #[test]
@ -495,7 +517,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("dummy-package2").unwrap(), MissingPackageVersion); assert_eq!(temp.package_manager.install_package("dummy-package2", false).unwrap(), MissingPackageVersion);
} }
#[test] #[test]
@ -505,7 +527,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("dummy-package3").unwrap(), UnableToParsePackageInfo); assert_eq!(temp.package_manager.install_package("dummy-package3", false).unwrap(), UnableToParsePackageInfo);
} }
#[test] #[test]
@ -515,7 +537,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("dummy-package4").unwrap(), UnableToParsePackageInfo); assert_eq!(temp.package_manager.install_package("dummy-package4", false).unwrap(), UnableToParsePackageInfo);
} }
#[test] #[test]
@ -525,7 +547,7 @@ mod tests {
std::fs::write(index_file, INSTALL_PACKAGE_INDEX); std::fs::write(index_file, INSTALL_PACKAGE_INDEX);
}); });
assert_eq!(temp.package_manager.install_package("dummy-package").unwrap(), Installed); assert_eq!(temp.package_manager.install_package("dummy-package", false).unwrap(), Installed);
assert!(temp.package_dir.path().join("dummy-package").exists()); assert!(temp.package_dir.path().join("dummy-package").exists());
assert!(temp.package_dir.path().join("dummy-package/README.md").exists()); assert!(temp.package_dir.path().join("dummy-package/README.md").exists());
assert!(temp.package_dir.path().join("dummy-package/package.yml").exists()); assert!(temp.package_dir.path().join("dummy-package/package.yml").exists());
@ -571,6 +593,7 @@ mod tests {
package_version: "0.1.0" package_version: "0.1.0"
package_author: "Federico Terzi" package_author: "Federico Terzi"
package_repo: "https://github.com/federico-terzi/espanso-hub-core" package_repo: "https://github.com/federico-terzi/espanso-hub-core"
is_core: true
--- ---
"###); "###);
@ -582,7 +605,9 @@ mod tests {
version: "0.1.0".to_string(), version: "0.1.0".to_string(),
repo: "https://github.com/federico-terzi/espanso-hub-core".to_string(), repo: "https://github.com/federico-terzi/espanso-hub-core".to_string(),
desc: "Include Italian accents substitutions to espanso.".to_string(), desc: "Include Italian accents substitutions to espanso.".to_string(),
author: "Federico Terzi".to_string() author: "Federico Terzi".to_string(),
original_repo: "https://github.com/federico-terzi/espanso-hub-core".to_string(),
is_core: true,
}; };
assert_eq!(package, target_package); assert_eq!(package, target_package);
@ -599,6 +624,7 @@ mod tests {
package_version:"0.1.0" package_version:"0.1.0"
package_author:Federico Terzi package_author:Federico Terzi
package_repo: "https://github.com/federico-terzi/espanso-hub-core" package_repo: "https://github.com/federico-terzi/espanso-hub-core"
is_core: true
--- ---
Readme text Readme text
"###); "###);
@ -611,7 +637,9 @@ mod tests {
version: "0.1.0".to_string(), version: "0.1.0".to_string(),
repo: "https://github.com/federico-terzi/espanso-hub-core".to_string(), repo: "https://github.com/federico-terzi/espanso-hub-core".to_string(),
desc: "Include Italian accents substitutions to espanso.".to_string(), desc: "Include Italian accents substitutions to espanso.".to_string(),
author: "Federico Terzi".to_string() author: "Federico Terzi".to_string(),
original_repo: "https://github.com/federico-terzi/espanso-hub-core".to_string(),
is_core: true,
}; };
assert_eq!(package, target_package); assert_eq!(package, target_package);

View File

@ -31,7 +31,7 @@ pub trait PackageManager {
fn get_package(&self, name: &str) -> Option<Package>; fn get_package(&self, name: &str) -> Option<Package>;
fn install_package(&self, name: &str) -> Result<InstallResult, Box<dyn Error>>; fn install_package(&self, name: &str, allow_external: bool) -> Result<InstallResult, Box<dyn Error>>;
fn install_package_from_repo(&self, name: &str, repo_url: &str) -> Result<InstallResult, Box<dyn Error>>; fn install_package_from_repo(&self, name: &str, repo_url: &str) -> Result<InstallResult, Box<dyn Error>>;
fn remove_package(&self, name: &str) -> Result<RemoveResult, Box<dyn Error>>; fn remove_package(&self, name: &str) -> Result<RemoveResult, Box<dyn Error>>;
@ -50,9 +50,17 @@ pub struct Package {
pub version: String, pub version: String,
pub repo: String, pub repo: String,
pub desc: String, pub desc: String,
pub author: String pub author: String,
#[serde(default = "default_is_core")]
pub is_core: bool,
#[serde(default = "default_original_repo")]
pub original_repo: String,
} }
fn default_is_core() -> bool {false}
fn default_original_repo() -> String {"".to_owned()}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct PackageIndex { pub struct PackageIndex {
#[serde(rename = "lastUpdate")] #[serde(rename = "lastUpdate")]
@ -75,7 +83,8 @@ pub enum InstallResult {
UnableToParsePackageInfo, UnableToParsePackageInfo,
MissingPackageVersion, MissingPackageVersion,
AlreadyInstalled, AlreadyInstalled,
Installed Installed,
BlockedExternalPackage(String)
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]

View File

@ -8,7 +8,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "A package to include some basic emojis in espanso.", "desc": "A package to include some basic emojis in espanso.",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
@ -19,7 +20,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Include Italian accents substitutions to espanso.", "desc": "Include Italian accents substitutions to espanso.",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
} }

View File

@ -8,7 +8,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "A package to include some basic emojis in espanso.", "desc": "A package to include some basic emojis in espanso.",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
@ -19,7 +20,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Include Italian accents substitutions to espanso.", "desc": "Include Italian accents substitutions to espanso.",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
} }

View File

@ -8,8 +8,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package", "desc": "Dummy package",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
{ {
@ -18,7 +18,8 @@
"version": "9.9.9", "version": "9.9.9",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package", "desc": "Dummy package",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
@ -28,7 +29,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package", "desc": "Dummy package",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
@ -38,7 +40,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package", "desc": "Dummy package",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
@ -49,7 +52,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Include Italian accents substitutions to espanso.", "desc": "Include Italian accents substitutions to espanso.",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
@ -59,7 +63,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Package that does not exist in the repo", "desc": "Package that does not exist in the repo",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
} }
]} ]}

View File

@ -8,7 +8,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "A package to include some basic emojis in espanso.", "desc": "A package to include some basic emojis in espanso.",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
}, },
@ -19,7 +20,8 @@
"version": "0.1.0", "version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core", "repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Include Italian accents substitutions to espanso.", "desc": "Include Italian accents substitutions to espanso.",
"author": "Federico Terzi" "author": "Federico Terzi",
"is_core": true
} }