ZIm/crates/extension_host/src/capability_granter.rs
tidely 7bdc99abc1
Fix clippy::redundant_clone lint violations (#36558)
This removes around 900 unnecessary clones, ranging from cloning a few
ints all the way to large data structures and images.

A lot of these were fixed using `cargo clippy --fix --workspace
--all-targets`, however it often breaks other lints and needs to be run
again. This was then followed up with some manual fixing.

I understand this is a large diff, but all the changes are pretty
trivial. Rust is doing some heavy lifting here for us. Once I get it up
to speed with main, I'd appreciate this getting merged rather sooner
than later.

Release Notes:

- N/A
2025-08-20 12:20:13 +02:00

152 lines
4.6 KiB
Rust

use std::sync::Arc;
use anyhow::{Result, bail};
use extension::{ExtensionCapability, ExtensionManifest};
use url::Url;
pub struct CapabilityGranter {
granted_capabilities: Vec<ExtensionCapability>,
manifest: Arc<ExtensionManifest>,
}
impl CapabilityGranter {
pub fn new(
granted_capabilities: Vec<ExtensionCapability>,
manifest: Arc<ExtensionManifest>,
) -> Self {
Self {
granted_capabilities,
manifest,
}
}
pub fn grant_exec(
&self,
desired_command: &str,
desired_args: &[impl AsRef<str> + std::fmt::Debug],
) -> Result<()> {
self.manifest.allow_exec(desired_command, desired_args)?;
let is_allowed = self
.granted_capabilities
.iter()
.any(|capability| match capability {
ExtensionCapability::ProcessExec(capability) => {
capability.allows(desired_command, desired_args)
}
_ => false,
});
if !is_allowed {
bail!(
"capability for process:exec {desired_command} {desired_args:?} is not granted by the extension host",
);
}
Ok(())
}
pub fn grant_download_file(&self, desired_url: &Url) -> Result<()> {
let is_allowed = self
.granted_capabilities
.iter()
.any(|capability| match capability {
ExtensionCapability::DownloadFile(capability) => capability.allows(desired_url),
_ => false,
});
if !is_allowed {
bail!(
"capability for download_file {desired_url} is not granted by the extension host",
);
}
Ok(())
}
pub fn grant_npm_install_package(&self, package_name: &str) -> Result<()> {
let is_allowed = self
.granted_capabilities
.iter()
.any(|capability| match capability {
ExtensionCapability::NpmInstallPackage(capability) => {
capability.allows(package_name)
}
_ => false,
});
if !is_allowed {
bail!("capability for npm:install {package_name} is not granted by the extension host",);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use extension::{ProcessExecCapability, SchemaVersion};
use super::*;
fn extension_manifest() -> ExtensionManifest {
ExtensionManifest {
id: "test".into(),
name: "Test".to_string(),
version: "1.0.0".into(),
schema_version: SchemaVersion::ZERO,
description: None,
repository: None,
authors: vec![],
lib: Default::default(),
themes: vec![],
icon_themes: vec![],
languages: vec![],
grammars: BTreeMap::default(),
language_servers: BTreeMap::default(),
context_servers: BTreeMap::default(),
slash_commands: BTreeMap::default(),
snippets: None,
capabilities: vec![],
debug_adapters: Default::default(),
debug_locators: Default::default(),
}
}
#[test]
fn test_grant_exec() {
let manifest = Arc::new(ExtensionManifest {
capabilities: vec![ExtensionCapability::ProcessExec(ProcessExecCapability {
command: "ls".to_string(),
args: vec!["-la".to_string()],
})],
..extension_manifest()
});
// It returns an error when the extension host has no granted capabilities.
let granter = CapabilityGranter::new(Vec::new(), manifest.clone());
assert!(granter.grant_exec("ls", &["-la"]).is_err());
// It succeeds when the extension host has the exact capability.
let granter = CapabilityGranter::new(
vec![ExtensionCapability::ProcessExec(ProcessExecCapability {
command: "ls".to_string(),
args: vec!["-la".to_string()],
})],
manifest.clone(),
);
assert!(granter.grant_exec("ls", &["-la"]).is_ok());
// It succeeds when the extension host has a wildcard capability.
let granter = CapabilityGranter::new(
vec![ExtensionCapability::ProcessExec(ProcessExecCapability {
command: "*".to_string(),
args: vec!["**".to_string()],
})],
manifest,
);
assert!(granter.grant_exec("ls", &["-la"]).is_ok());
}
}