207 lines
6.7 KiB
Rust
207 lines
6.7 KiB
Rust
use std::{error::Error, io};
|
|
|
|
use ely_domain::{
|
|
DomainError, PluginContributionPoint, PluginManifest, PluginPermission, PluginPermissionRisk,
|
|
PluginSignatureAlgorithm,
|
|
};
|
|
|
|
#[test]
|
|
fn parses_signed_plugin_manifest() -> Result<(), Box<dyn Error>> {
|
|
let manifest = PluginManifest::from_toml(valid_manifest().as_str())?;
|
|
|
|
assert_eq!(manifest.id().as_str(), "com.elydora.reader");
|
|
assert_eq!(manifest.name(), "Reader Exporter");
|
|
assert_eq!(manifest.homepage(), "https://elydora.com/plugins/reader");
|
|
assert_eq!(
|
|
manifest.permissions(),
|
|
&[PluginPermission::PageMetadata, PluginPermission::UiCommand]
|
|
);
|
|
assert_eq!(
|
|
manifest.contributes(),
|
|
&[PluginContributionPoint::CommandBarCommand, PluginContributionPoint::ReadingModeExporter]
|
|
);
|
|
assert_eq!(manifest.min_ely_build().to_string(), "0.1.0");
|
|
assert_eq!(
|
|
manifest.checksum(),
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
);
|
|
assert_eq!(manifest.signature().algorithm(), &PluginSignatureAlgorithm::Ed25519);
|
|
assert_eq!(manifest.signature().key_id(), "elydora-alpha-plugins");
|
|
assert_eq!(
|
|
manifest.signature().public_key(),
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
);
|
|
assert_eq!(
|
|
manifest.signature().value(),
|
|
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn classifies_plugin_permission_risk_for_separate_confirmation() -> Result<(), Box<dyn Error>> {
|
|
let manifest = PluginManifest::from_toml(valid_manifest().as_str())?;
|
|
let high_risk_permissions = manifest.high_risk_permissions().collect::<Vec<_>>();
|
|
|
|
assert!(high_risk_permissions.is_empty());
|
|
assert_eq!(PluginPermission::PageMetadata.risk(), PluginPermissionRisk::Standard);
|
|
assert_eq!(PluginPermission::UiCommand.risk(), PluginPermissionRisk::Standard);
|
|
assert_eq!(PluginPermission::HistoryRead.risk(), PluginPermissionRisk::High);
|
|
assert!(PluginPermission::PageScript.requires_separate_confirmation());
|
|
assert!(PluginPermission::FilesystemWrite.requires_separate_confirmation());
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_unknown_plugin_permission() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest().replace("page:metadata", "tabs:admin");
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(
|
|
error,
|
|
DomainError::InvalidPluginPermission { value } if value == "tabs:admin"
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_duplicate_plugin_permission() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest()
|
|
.replace("[\"page:metadata\", \"ui:command\"]", "[\"page:metadata\", \"page:metadata\"]");
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(
|
|
error,
|
|
DomainError::DuplicatePluginPermission { value } if value == "page:metadata"
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_unknown_plugin_contribution() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest().replace("reading-mode-exporter", "hidden-root-hook");
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(
|
|
error,
|
|
DomainError::InvalidPluginContribution { value } if value == "hidden-root-hook"
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_unsigned_plugin_manifest() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest().replace(
|
|
"value = \"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\"",
|
|
"value = \"\"",
|
|
);
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(error, DomainError::EmptyField { field } if field == "signature"));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_invalid_plugin_signature_key_id() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest()
|
|
.replace("key_id = \"elydora-alpha-plugins\"", "key_id = \"Elydora Alpha Plugins\"");
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(
|
|
error,
|
|
DomainError::InvalidPluginSignatureKeyId { value } if value == "Elydora Alpha Plugins"
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_invalid_plugin_signature_public_key() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest().replace(
|
|
"public_key = \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"",
|
|
"public_key = \"abcd\"",
|
|
);
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(
|
|
error,
|
|
DomainError::InvalidPluginSignaturePublicKey { value } if value == "abcd"
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_mismatched_plugin_checksum() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest().replace(
|
|
"checksum = \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"",
|
|
"checksum = \"1234\"",
|
|
);
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(
|
|
error,
|
|
DomainError::InvalidPluginChecksum { value } if value == "1234"
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_non_http_plugin_homepage() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest().replace(
|
|
"homepage = \"https://elydora.com/plugins/reader\"",
|
|
"homepage = \"file:///tmp/reader\"",
|
|
);
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(
|
|
error,
|
|
DomainError::InvalidPluginHomepage { value } if value == "file:///tmp/reader"
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_extra_manifest_fields() -> Result<(), Box<dyn Error>> {
|
|
let manifest = valid_manifest().replace("[signature]", "process_escape = true\n\n[signature]");
|
|
|
|
let error = parse_error(manifest.as_str())?;
|
|
|
|
assert!(matches!(error, DomainError::InvalidPluginManifest { .. }));
|
|
Ok(())
|
|
}
|
|
|
|
fn parse_error(manifest: &str) -> Result<DomainError, Box<dyn Error>> {
|
|
match PluginManifest::from_toml(manifest) {
|
|
Ok(_) => Err(io::Error::other("manifest parsed successfully").into()),
|
|
Err(error) => Ok(error),
|
|
}
|
|
}
|
|
|
|
fn valid_manifest() -> String {
|
|
r#"
|
|
id = "com.elydora.reader"
|
|
name = "Reader Exporter"
|
|
description = "Exports the active reader view."
|
|
author = "Elydora"
|
|
homepage = "https://elydora.com/plugins/reader"
|
|
permissions = ["page:metadata", "ui:command"]
|
|
contributes = ["command-bar-command", "reading-mode-exporter"]
|
|
min_ely_build = "0.1.0"
|
|
checksum = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
|
|
|
[signature]
|
|
algorithm = "ed25519"
|
|
key_id = "elydora-alpha-plugins"
|
|
public_key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
|
value = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
|
|
"#
|
|
.to_string()
|
|
}
|