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)
.takes_value(false)
.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")
.help("Package name"));
@ -766,6 +772,13 @@ fn install_main(_config_set: ConfigSet, matches: &ArgMatches) {
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));
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.")
}
let res = package_manager.install_package(package_name);
let res = package_manager.install_package(package_name, allow_external);
match res {
Ok(install_result) => {
@ -812,6 +825,22 @@ fn install_main(_config_set: ConfigSet, matches: &ArgMatches) {
InstallResult::AlreadyInstalled => {
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 => {
println!("{} successfully installed!", package_name);
println!();

View File

@ -24,7 +24,7 @@ use std::fs::{File, create_dir};
use std::io::{BufReader, BufRead};
use std::time::{SystemTime, UNIX_EPOCH};
use crate::package::UpdateResult::{NotOutdated, Updated};
use crate::package::InstallResult::{NotFoundInIndex, AlreadyInstalled};
use crate::package::InstallResult::{NotFoundInIndex, AlreadyInstalled, BlockedExternalPackage};
use std::fs;
use tempfile::TempDir;
use git2::Repository;
@ -138,13 +138,31 @@ impl DefaultPackageManager {
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 {
name: fields.get("package_name").unwrap().clone(),
title: fields.get("package_title").unwrap().clone(),
version: fields.get("package_version").unwrap().clone(),
repo: fields.get("package_repo").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)
@ -228,11 +246,15 @@ impl super::PackageManager for DefaultPackageManager {
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);
match package {
Some(package) => {
self.install_package_from_repo(name, &package.repo)
if package.is_core || allow_external {
self.install_package_from_repo(name, &package.repo)
}else{
Ok(BlockedExternalPackage(package.original_repo))
}
},
None => {
Ok(NotFoundInIndex)
@ -451,7 +473,7 @@ mod tests {
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]
@ -462,7 +484,7 @@ mod tests {
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]
@ -472,7 +494,7 @@ mod tests {
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/README.md").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);
});
assert_eq!(temp.package_manager.install_package("not-existing").unwrap(), NotFoundInRepo);
assert_eq!(temp.package_manager.install_package("not-existing", false).unwrap(), NotFoundInRepo);
}
#[test]
@ -495,7 +517,7 @@ mod tests {
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]
@ -505,7 +527,7 @@ mod tests {
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]
@ -515,7 +537,7 @@ mod tests {
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]
@ -525,7 +547,7 @@ mod tests {
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/README.md").exists());
assert!(temp.package_dir.path().join("dummy-package/package.yml").exists());
@ -571,6 +593,7 @@ mod tests {
package_version: "0.1.0"
package_author: "Federico Terzi"
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(),
repo: "https://github.com/federico-terzi/espanso-hub-core".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);
@ -599,6 +624,7 @@ mod tests {
package_version:"0.1.0"
package_author:Federico Terzi
package_repo: "https://github.com/federico-terzi/espanso-hub-core"
is_core: true
---
Readme text
"###);
@ -611,7 +637,9 @@ mod tests {
version: "0.1.0".to_string(),
repo: "https://github.com/federico-terzi/espanso-hub-core".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);

View File

@ -31,7 +31,7 @@ pub trait PackageManager {
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 remove_package(&self, name: &str) -> Result<RemoveResult, Box<dyn Error>>;
@ -50,9 +50,17 @@ pub struct Package {
pub version: String,
pub repo: 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)]
pub struct PackageIndex {
#[serde(rename = "lastUpdate")]
@ -75,7 +83,8 @@ pub enum InstallResult {
UnableToParsePackageInfo,
MissingPackageVersion,
AlreadyInstalled,
Installed
Installed,
BlockedExternalPackage(String)
}
#[derive(Clone, Debug, PartialEq)]

View File

@ -8,7 +8,8 @@
"version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"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",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"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",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"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",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"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",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package",
"author": "Federico Terzi"
"author": "Federico Terzi",
"is_core": true
},
{
@ -18,7 +18,8 @@
"version": "9.9.9",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package",
"author": "Federico Terzi"
"author": "Federico Terzi",
"is_core": true
},
@ -28,7 +29,8 @@
"version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package",
"author": "Federico Terzi"
"author": "Federico Terzi",
"is_core": true
},
@ -38,7 +40,8 @@
"version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Dummy package",
"author": "Federico Terzi"
"author": "Federico Terzi",
"is_core": true
},
@ -49,7 +52,8 @@
"version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Include Italian accents substitutions to espanso.",
"author": "Federico Terzi"
"author": "Federico Terzi",
"is_core": true
},
@ -59,7 +63,8 @@
"version": "0.1.0",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"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",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"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",
"repo": "https://github.com/federico-terzi/espanso-hub-core",
"desc": "Include Italian accents substitutions to espanso.",
"author": "Federico Terzi"
"author": "Federico Terzi",
"is_core": true
}