diff --git a/crates/ely_domain/src/lib.rs b/crates/ely_domain/src/lib.rs index 8aa14c6..16aaa4b 100644 --- a/crates/ely_domain/src/lib.rs +++ b/crates/ely_domain/src/lib.rs @@ -21,8 +21,8 @@ pub use error::DomainError; pub use history::HistoryEntry; pub use identifiers::{DownloadId, ProfileId, SpaceId, SplitId, TabId, WebViewId}; pub use plugin::{ - PluginContributionPoint, PluginId, PluginManifest, PluginPermission, PluginSignature, - PluginSignatureAlgorithm, + PluginContributionPoint, PluginId, PluginManifest, PluginPermission, PluginPermissionRisk, + PluginSignature, PluginSignatureAlgorithm, }; pub use profile::{Profile, ProfileKind}; pub use space::{ArchivePolicy, Space}; diff --git a/crates/ely_domain/src/plugin.rs b/crates/ely_domain/src/plugin.rs index cbbf648..6d0246f 100644 --- a/crates/ely_domain/src/plugin.rs +++ b/crates/ely_domain/src/plugin.rs @@ -50,6 +50,12 @@ pub enum PluginPermission { UiContextMenu, } +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum PluginPermissionRisk { + Standard, + High, +} + #[derive(Clone, Debug, Eq, PartialEq)] pub enum PluginContributionPoint { CommandBarCommand, @@ -166,6 +172,10 @@ impl PluginManifest { &self.permissions } + pub fn high_risk_permissions(&self) -> impl Iterator { + self.permissions.iter().filter(|permission| permission.requires_separate_confirmation()) + } + #[must_use] pub fn contributes(&self) -> &[PluginContributionPoint] { &self.contributes @@ -245,6 +255,40 @@ impl PluginPermission { Self::UiContextMenu => "ui:context_menu", } } + + #[must_use] + pub fn risk(&self) -> PluginPermissionRisk { + match self { + Self::TabsRead + | Self::SpacesRead + | Self::PageMetadata + | Self::SettingsRead + | Self::UiPanel + | Self::UiCommand + | Self::UiContextMenu => PluginPermissionRisk::Standard, + Self::TabsWrite + | Self::SpacesWrite + | Self::BookmarksRead + | Self::BookmarksWrite + | Self::HistoryRead + | Self::DownloadsRead + | Self::DownloadsWrite + | Self::PageScreenshot + | Self::PageScript + | Self::ClipboardRead + | Self::ClipboardWrite + | Self::FilesystemRead + | Self::FilesystemWrite + | Self::NetworkFetch + | Self::SettingsWrite + | Self::SyncPlugin => PluginPermissionRisk::High, + } + } + + #[must_use] + pub fn requires_separate_confirmation(&self) -> bool { + self.risk() == PluginPermissionRisk::High + } } impl PluginContributionPoint { diff --git a/crates/ely_domain/tests/plugins.rs b/crates/ely_domain/tests/plugins.rs index 1268ffb..5acd793 100644 --- a/crates/ely_domain/tests/plugins.rs +++ b/crates/ely_domain/tests/plugins.rs @@ -1,7 +1,7 @@ use std::{error::Error, io}; use ely_domain::{ - DomainError, PluginContributionPoint, PluginManifest, PluginPermission, + DomainError, PluginContributionPoint, PluginManifest, PluginPermission, PluginPermissionRisk, PluginSignatureAlgorithm, }; @@ -33,6 +33,20 @@ fn parses_signed_plugin_manifest() -> Result<(), Box> { Ok(()) } +#[test] +fn classifies_plugin_permission_risk_for_separate_confirmation() -> Result<(), Box> { + let manifest = PluginManifest::from_toml(valid_manifest().as_str())?; + let high_risk_permissions = manifest.high_risk_permissions().collect::>(); + + 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> { let manifest = valid_manifest().replace("page:metadata", "tabs:admin");