|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
|
|
use aho_corasick::AhoCorasick;
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use tauri::{
|
|
|
|
|
plugin::{Builder, TauriPlugin},
|
|
|
|
@ -14,6 +15,8 @@ use std::{
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SCOPE_STATE_FILENAME: &str = ".persisted-scope";
|
|
|
|
|
const PATTERNS: &[&str] = &["[?]", "[[]", "[]]", "[*]"];
|
|
|
|
|
const REPLACE_WITH: &[&str] = &["?", "[", "]", "*"];
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
|
enum Error {
|
|
|
|
@ -45,6 +48,29 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|
|
|
|
if let Some(app_dir) = app_dir {
|
|
|
|
|
let scope_state_path = app_dir.join(SCOPE_STATE_FILENAME);
|
|
|
|
|
|
|
|
|
|
// We need to filter out glob pattern paths from the scope configs to not pollute the scope with incorrect paths.
|
|
|
|
|
// We can't plainly filter for `*` because `*` is valid in paths on unix.
|
|
|
|
|
let initial_fs_allowed: Vec<String> = fs_scope
|
|
|
|
|
.allowed_patterns()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
|
.collect();
|
|
|
|
|
let initial_asset_allowed: Vec<String> = asset_protocol_scope
|
|
|
|
|
.allowed_patterns()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
|
.collect();
|
|
|
|
|
let initial_fs_forbidden: Vec<String> = fs_scope
|
|
|
|
|
.forbidden_patterns()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
|
.collect();
|
|
|
|
|
let initial_asset_forbidden: Vec<String> = asset_protocol_scope
|
|
|
|
|
.forbidden_patterns()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
let _ = fs_scope.forbid_file(&scope_state_path);
|
|
|
|
|
#[cfg(feature = "protocol-asset")]
|
|
|
|
|
let _ = asset_protocol_scope.forbid_file(&scope_state_path);
|
|
|
|
@ -55,19 +81,29 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|
|
|
|
.and_then(|scope| bincode::deserialize(&scope).map_err(Into::into))
|
|
|
|
|
.unwrap_or_default();
|
|
|
|
|
for allowed in &scope.allowed_paths {
|
|
|
|
|
// allows the path as is
|
|
|
|
|
let _ = fs_scope.allow_file(allowed);
|
|
|
|
|
if !initial_fs_allowed.contains(&allowed) {
|
|
|
|
|
let _ = fs_scope.allow_file(&allowed);
|
|
|
|
|
}
|
|
|
|
|
#[cfg(feature = "protocol-asset")]
|
|
|
|
|
let _ = asset_protocol_scope.allow_file(allowed);
|
|
|
|
|
if !initial_asset_allowed.contains(&allowed) {
|
|
|
|
|
let _ = asset_protocol_scope.allow_file(&allowed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for forbidden in &scope.forbidden_patterns {
|
|
|
|
|
// forbid the path as is
|
|
|
|
|
let _ = fs_scope.forbid_file(forbidden);
|
|
|
|
|
if !initial_fs_forbidden.contains(&forbidden) {
|
|
|
|
|
let _ = fs_scope.forbid_file(&forbidden);
|
|
|
|
|
}
|
|
|
|
|
#[cfg(feature = "protocol-asset")]
|
|
|
|
|
let _ = asset_protocol_scope.forbid_file(forbidden);
|
|
|
|
|
if !initial_asset_forbidden.contains(&forbidden) {
|
|
|
|
|
let _ = asset_protocol_scope.forbid_file(&forbidden);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We could also "fix" the paths on app start if we notice any runtime performance problems.
|
|
|
|
|
let ac = AhoCorasick::new_auto_configured(PATTERNS);
|
|
|
|
|
|
|
|
|
|
fs_scope.listen(move |event| {
|
|
|
|
|
let fs_scope = app.fs_scope();
|
|
|
|
|
if let FsScopeEvent::PathAllowed(_) = event {
|
|
|
|
@ -75,18 +111,17 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|
|
|
|
allowed_paths: fs_scope
|
|
|
|
|
.allowed_patterns()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
|
.map(|p| ac.replace_all(p.as_str(), REPLACE_WITH))
|
|
|
|
|
.collect(),
|
|
|
|
|
forbidden_patterns: fs_scope
|
|
|
|
|
.forbidden_patterns()
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|p| p.to_string())
|
|
|
|
|
.map(|p| ac.replace_all(p.as_str(), REPLACE_WITH))
|
|
|
|
|
.collect(),
|
|
|
|
|
};
|
|
|
|
|
let scope_state_path = scope_state_path.clone();
|
|
|
|
|
|
|
|
|
|
let _ = create_dir_all(&app_dir)
|
|
|
|
|
.and_then(|_| File::create(scope_state_path))
|
|
|
|
|
.and_then(|_| File::create(&scope_state_path))
|
|
|
|
|
.map_err(Error::Io)
|
|
|
|
|
.and_then(|mut f| {
|
|
|
|
|
f.write_all(&bincode::serialize(&scope).map_err(Error::from)?)
|
|
|
|
|