diff --git a/plugins/persisted-scope/src/lib.rs b/plugins/persisted-scope/src/lib.rs index 6df25860..269f1973 100644 --- a/plugins/persisted-scope/src/lib.rs +++ b/plugins/persisted-scope/src/lib.rs @@ -15,11 +15,12 @@ use aho_corasick::AhoCorasick; use serde::{Deserialize, Serialize}; use tauri::{ plugin::{Builder, TauriPlugin}, - FsScope, FsScopeEvent, Manager, Runtime, + FsScope, FsScopeEvent, GlobPattern, Manager, Runtime, }; -use tauri_plugin_fs::{FsExt, ScopeEvent as FsScopeEvent}; +use tauri_plugin_fs::{FsExt, Scope as FsPluginScope, ScopeEvent as FsPluginScopeEvent}; use std::{ + collections::HashSet, fs::{create_dir_all, File}, io::Write, path::Path, @@ -43,6 +44,70 @@ const PATTERNS: &[&str] = &[ ]; const REPLACE_WITH: &[&str] = &[r"[", r"]", r"?", r"*", r"\?", r"\\?\", r"\\?\"]; +trait ScopeExt { + fn allow_file_(&self, path: &Path); + fn allow_directory_(&self, path: &Path, recursive: bool); + + fn forbid_file_(&self, path: &Path); + fn forbid_directory_(&self, path: &Path, recursive: bool); + + fn allowed_patterns_(&self) -> HashSet; + fn forbidden_patterns_(&self) -> HashSet; +} + +impl ScopeExt for &FsPluginScope { + fn allow_file_(&self, path: &Path) { + let _ = self.allow_file(path); + } + + fn allow_directory_(&self, path: &Path, recursive: bool) { + let _ = self.allow_directory(path, recursive); + } + + fn forbid_file_(&self, path: &Path) { + let _ = self.forbid_file(path); + } + + fn forbid_directory_(&self, path: &Path, recursive: bool) { + let _ = self.forbid_directory(path, recursive); + } + + fn allowed_patterns_(&self) -> HashSet { + self.allowed_patterns() + } + + fn forbidden_patterns_(&self) -> HashSet { + self.forbidden_patterns() + } +} + +#[cfg(feature = "protocol-asset")] +impl ScopeExt for &FsScope { + fn allow_file_(&self, path: &Path) { + let _ = self.allow_file(path); + } + + fn allow_directory_(&self, path: &Path, recursive: bool) { + let _ = self.allow_directory(path, recursive); + } + + fn forbid_file_(&self, path: &Path) { + let _ = self.forbid_file(path); + } + + fn forbid_directory_(&self, path: &Path, recursive: bool) { + let _ = self.forbid_directory(path, recursive); + } + + fn allowed_patterns_(&self) -> HashSet { + self.allowed_patterns() + } + + fn forbidden_patterns_(&self) -> HashSet { + self.forbidden_patterns() + } +} + #[derive(Debug, thiserror::Error)] enum Error { #[error(transparent)] @@ -105,49 +170,49 @@ fn fix_directory(path_str: &str) -> &Path { path } -fn allow_path(scope: &FsScope, path: &str) { +fn allow_path(scope: impl ScopeExt, path: &str) { let target_type = detect_scope_type(path); match target_type { TargetType::File => { - let _ = scope.allow_file(path); + scope.allow_file_(Path::new(path)); } TargetType::Directory => { // We remove the '*' at the end of it, else it will be escaped by the pattern. - let _ = scope.allow_directory(fix_directory(path), false); + scope.allow_directory_(fix_directory(path), false); } TargetType::RecursiveDirectory => { // We remove the '**' at the end of it, else it will be escaped by the pattern. - let _ = scope.allow_directory(fix_directory(path), true); + scope.allow_directory_(fix_directory(path), true); } } } -fn forbid_path(scope: &FsScope, path: &str) { +fn forbid_path(scope: impl ScopeExt, path: &str) { let target_type = detect_scope_type(path); match target_type { TargetType::File => { - let _ = scope.forbid_file(path); + scope.forbid_file_(Path::new(path)); } TargetType::Directory => { - let _ = scope.forbid_directory(fix_directory(path), false); + scope.forbid_directory_(fix_directory(path), false); } TargetType::RecursiveDirectory => { - let _ = scope.forbid_directory(fix_directory(path), true); + scope.forbid_directory_(fix_directory(path), true); } } } -fn save_scopes(scope: &FsScope, app_dir: &Path, scope_state_path: &Path) { +fn save_scopes(scope: impl ScopeExt, app_dir: &Path, scope_state_path: &Path) { let scope = Scope { allowed_paths: scope - .allowed_patterns() + .allowed_patterns_() .into_iter() .map(|p| p.to_string()) .collect(), forbidden_patterns: scope - .forbidden_patterns() + .forbidden_patterns_() .into_iter() .map(|p| p.to_string()) .collect(), @@ -166,16 +231,17 @@ pub fn init() -> TauriPlugin { Builder::new("persisted-scope") .setup(|app, _api| { let fs_scope = app.try_fs_scope(); - let core_scopes = app.state::(); + let asset_protocol_scope = app.asset_protocol_scope(); let app = app.clone(); let app_dir = app.path().app_data_dir(); - if let Some(app_dir) = app_dir { + if let Ok(app_dir) = app_dir { let fs_scope_state_path = app_dir.join(SCOPE_STATE_FILENAME); #[cfg(feature = "protocol-asset")] let asset_scope_state_path = app_dir.join(ASSET_SCOPE_STATE_FILENAME); - let _ = fs_scope.forbid_file(&fs_scope_state_path); + if let Some(fs_scope) = fs_scope { + let _ = fs_scope.forbid_file(&fs_scope_state_path);} #[cfg(feature = "protocol-asset")] let _ = asset_protocol_scope.forbid_file(&asset_scope_state_path); @@ -183,7 +249,8 @@ pub fn init() -> TauriPlugin { // We will still save some semi-broken values because the scope events are quite spammy and we don't want to reduce runtime performance any further. let ac = AhoCorasick::new(PATTERNS).unwrap(/* This should be impossible to fail since we're using a small static input */); - if fs_scope_state_path.exists() { + if let Some(fs_scope) = fs_scope { + if fs_scope_state_path.exists() { let scope: Scope = tauri::api::file::read_binary(&fs_scope_state_path) .map_err(Error::from) .and_then(|scope| bincode::deserialize(&scope).map_err(Into::into)) @@ -191,16 +258,17 @@ pub fn init() -> TauriPlugin { for allowed in &scope.allowed_paths { let allowed = fix_pattern(&ac, allowed); - allow_path(&fs_scope, &allowed); + allow_path(fs_scope, &allowed); } for forbidden in &scope.forbidden_patterns { let forbidden = fix_pattern(&ac, forbidden); - forbid_path(&fs_scope, &forbidden); + forbid_path(fs_scope, &forbidden); } // Manually save the fixed scopes to disk once. // This is needed to fix broken .peristed-scope files in case the app doesn't update the scope itself. - save_scopes(&fs_scope, &app_dir, &fs_scope_state_path); + save_scopes(fs_scope, &app_dir, &fs_scope_state_path); + } } #[cfg(feature = "protocol-asset")] @@ -225,12 +293,15 @@ pub fn init() -> TauriPlugin { #[cfg(feature = "protocol-asset")] let app_dir_ = app_dir.clone(); - let fs_scope_ = fs_scope.clone(); - fs_scope.listen(move |event| { - if let FsScopeEvent::PathAllowed(_) = event { - save_scopes(&fs_scope_, &app_dir, &fs_scope_state_path); - } - }); + if let Some(fs_scope) = fs_scope { + let fs_scope_ = fs_scope.clone(); + fs_scope.listen(move |event| { + if let FsPluginScopeEvent::PathAllowed(_) = event { + save_scopes(&fs_scope_, &app_dir, &fs_scope_state_path); + } + }); + } + #[cfg(feature = "protocol-asset")] { let asset_protocol_scope_ = asset_protocol_scope.clone();