|
@@ -5,6 +5,7 @@
|
|
|
use std::{
|
|
|
fmt,
|
|
|
path::{Path, PathBuf},
|
|
|
+ sync::{Arc, Mutex},
|
|
|
};
|
|
|
|
|
|
use glob::Pattern;
|
|
@@ -18,7 +19,7 @@ use crate::api::path::parse as parse_path;
|
|
|
/// Scope for filesystem access.
|
|
|
#[derive(Clone)]
|
|
|
pub struct Scope {
|
|
|
- allow_patterns: Vec<Pattern>,
|
|
|
+ allow_patterns: Arc<Mutex<Vec<Pattern>>>,
|
|
|
}
|
|
|
|
|
|
impl fmt::Debug for Scope {
|
|
@@ -28,6 +29,8 @@ impl fmt::Debug for Scope {
|
|
|
"allow_patterns",
|
|
|
&self
|
|
|
.allow_patterns
|
|
|
+ .lock()
|
|
|
+ .unwrap()
|
|
|
.iter()
|
|
|
.map(|p| p.as_str())
|
|
|
.collect::<Vec<&str>>(),
|
|
@@ -36,6 +39,16 @@ impl fmt::Debug for Scope {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+fn push_pattern<P: AsRef<Path>>(list: &mut Vec<Pattern>, pattern: P) {
|
|
|
+ let pattern: PathBuf = pattern.as_ref().components().collect();
|
|
|
+ list.push(Pattern::new(&pattern.to_string_lossy()).expect("invalid glob pattern"));
|
|
|
+ #[cfg(windows)]
|
|
|
+ {
|
|
|
+ list
|
|
|
+ .push(Pattern::new(&format!("\\\\?\\{}", pattern.display())).expect("invalid glob pattern"));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
impl Scope {
|
|
|
/// Creates a new scope from a `FsAllowlistScope` configuration.
|
|
|
pub fn for_fs_api(
|
|
@@ -47,17 +60,33 @@ impl Scope {
|
|
|
let mut allow_patterns = Vec::new();
|
|
|
for path in &scope.0 {
|
|
|
if let Ok(path) = parse_path(config, package_info, env, path) {
|
|
|
- let path: PathBuf = path.components().collect();
|
|
|
- allow_patterns.push(Pattern::new(&path.to_string_lossy()).expect("invalid glob pattern"));
|
|
|
- #[cfg(windows)]
|
|
|
- {
|
|
|
- allow_patterns.push(
|
|
|
- Pattern::new(&format!("\\\\?\\{}", path.display())).expect("invalid glob pattern"),
|
|
|
- );
|
|
|
- }
|
|
|
+ push_pattern(&mut allow_patterns, path);
|
|
|
}
|
|
|
}
|
|
|
- Self { allow_patterns }
|
|
|
+ Self {
|
|
|
+ allow_patterns: Arc::new(Mutex::new(allow_patterns)),
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Extend the allowed patterns with the given directory.
|
|
|
+ ///
|
|
|
+ /// After this function has been called, the frontend will be able to use the Tauri API to read
|
|
|
+ /// the directory and all of its files and subdirectories.
|
|
|
+ pub fn allow_directory<P: AsRef<Path>>(&self, path: P, recursive: bool) {
|
|
|
+ let path = path.as_ref().to_path_buf();
|
|
|
+ let mut list = self.allow_patterns.lock().unwrap();
|
|
|
+
|
|
|
+ // allow the directory to be read
|
|
|
+ push_pattern(&mut list, &path);
|
|
|
+ // allow its files and subdirectories to be read
|
|
|
+ push_pattern(&mut list, path.join(if recursive { "**" } else { "*" }));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Extend the allowed patterns with the given file path.
|
|
|
+ ///
|
|
|
+ /// After this function has been called, the frontend will be able to use the Tauri API to read the contents of this file.
|
|
|
+ pub fn allow_file<P: AsRef<Path>>(&self, path: P) {
|
|
|
+ push_pattern(&mut self.allow_patterns.lock().unwrap(), path);
|
|
|
}
|
|
|
|
|
|
/// Determines if the given path is allowed on this scope.
|
|
@@ -71,7 +100,12 @@ impl Scope {
|
|
|
|
|
|
if let Ok(path) = path {
|
|
|
let path: PathBuf = path.components().collect();
|
|
|
- let allowed = self.allow_patterns.iter().any(|p| p.matches_path(&path));
|
|
|
+ let allowed = self
|
|
|
+ .allow_patterns
|
|
|
+ .lock()
|
|
|
+ .unwrap()
|
|
|
+ .iter()
|
|
|
+ .any(|p| p.matches_path(&path));
|
|
|
allowed
|
|
|
} else {
|
|
|
false
|