mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-04-21 11:26:15 +02:00
fix(fs)!: use tauri::scope::fs::Scope (#2070)
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
fs: minor
|
||||
persisted-scope: minor
|
||||
---
|
||||
|
||||
**Breaking Change:** Replaced the custom `tauri_plugin_fs::Scope` struct with `tauri::fs::Scope`.
|
||||
@@ -143,7 +143,7 @@ pub(crate) async fn open<R: Runtime>(
|
||||
for folder in folders {
|
||||
if let Ok(path) = folder.clone().into_path() {
|
||||
if let Some(s) = window.try_fs_scope() {
|
||||
s.allow_directory(&path, options.recursive);
|
||||
s.allow_directory(&path, options.recursive)?;
|
||||
}
|
||||
tauri_scope.allow_directory(&path, options.directory)?;
|
||||
}
|
||||
@@ -157,7 +157,7 @@ pub(crate) async fn open<R: Runtime>(
|
||||
if let Some(folder) = &folder {
|
||||
if let Ok(path) = folder.clone().into_path() {
|
||||
if let Some(s) = window.try_fs_scope() {
|
||||
s.allow_directory(&path, options.recursive);
|
||||
s.allow_directory(&path, options.recursive)?;
|
||||
}
|
||||
tauri_scope.allow_directory(&path, options.directory)?;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ pub(crate) async fn open<R: Runtime>(
|
||||
for file in files {
|
||||
if let Ok(path) = file.clone().into_path() {
|
||||
if let Some(s) = window.try_fs_scope() {
|
||||
s.allow_file(&path);
|
||||
s.allow_file(&path)?;
|
||||
}
|
||||
|
||||
tauri_scope.allow_file(&path)?;
|
||||
@@ -190,7 +190,7 @@ pub(crate) async fn open<R: Runtime>(
|
||||
if let Some(file) = &file {
|
||||
if let Ok(path) = file.clone().into_path() {
|
||||
if let Some(s) = window.try_fs_scope() {
|
||||
s.allow_file(&path);
|
||||
s.allow_file(&path)?;
|
||||
}
|
||||
tauri_scope.allow_file(&path)?;
|
||||
}
|
||||
@@ -232,7 +232,7 @@ pub(crate) async fn save<R: Runtime>(
|
||||
if let Some(p) = &path {
|
||||
if let Ok(path) = p.clone().into_path() {
|
||||
if let Some(s) = window.try_fs_scope() {
|
||||
s.allow_file(&path);
|
||||
s.allow_file(&path)?;
|
||||
}
|
||||
tauri_scope.allow_file(&path)?;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ rustc-args = ["--cfg", "docsrs"]
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[package.metadata.platforms.support]
|
||||
windows = { level = "full", notes = "" }
|
||||
windows = { level = "full", notes = "Apps installed via MSI or NSIS in `perMachine` and `both` mode require admin permissions for write acces in `$RESOURCES` folder" }
|
||||
linux = { level = "full", notes = "No write access to `$RESOURCES` folder" }
|
||||
macos = { level = "full", notes = "No write access to `$RESOURCES` folder" }
|
||||
android = { level = "partial", notes = "Access is restricted to Application folder by default" }
|
||||
|
||||
+63
-20
@@ -16,13 +16,13 @@ use std::{
|
||||
borrow::Cow,
|
||||
fs::File,
|
||||
io::{BufRead, BufReader, Read, Write},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
sync::Mutex,
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use crate::{scope::Entry, Error, FsExt, SafeFilePath};
|
||||
use crate::{scope::Entry, Error, SafeFilePath};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CommandError {
|
||||
@@ -942,6 +942,8 @@ pub fn resolve_file<R: Runtime>(
|
||||
path: SafeFilePath,
|
||||
open_options: OpenOptions,
|
||||
) -> CommandResult<(File, PathBuf)> {
|
||||
use crate::FsExt;
|
||||
|
||||
match path {
|
||||
SafeFilePath::Url(url) => {
|
||||
let path = url.as_str().into();
|
||||
@@ -974,40 +976,81 @@ pub fn resolve_path<R: Runtime>(
|
||||
path
|
||||
};
|
||||
|
||||
let fs_scope = webview.state::<crate::Scope>();
|
||||
|
||||
let scope = tauri::scope::fs::Scope::new(
|
||||
webview,
|
||||
&FsScope::Scope {
|
||||
allow: webview
|
||||
.fs_scope()
|
||||
.allowed
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.chain(global_scope.allows().iter().filter_map(|e| e.path.clone()))
|
||||
allow: global_scope
|
||||
.allows()
|
||||
.iter()
|
||||
.filter_map(|e| e.path.clone())
|
||||
.chain(command_scope.allows().iter().filter_map(|e| e.path.clone()))
|
||||
.collect(),
|
||||
deny: webview
|
||||
.fs_scope()
|
||||
.denied
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.chain(global_scope.denies().iter().filter_map(|e| e.path.clone()))
|
||||
deny: global_scope
|
||||
.denies()
|
||||
.iter()
|
||||
.filter_map(|e| e.path.clone())
|
||||
.chain(command_scope.denies().iter().filter_map(|e| e.path.clone()))
|
||||
.collect(),
|
||||
require_literal_leading_dot: webview.fs_scope().require_literal_leading_dot,
|
||||
require_literal_leading_dot: fs_scope.require_literal_leading_dot,
|
||||
},
|
||||
)?;
|
||||
|
||||
if scope.is_allowed(&path) {
|
||||
let require_literal_leading_dot = fs_scope.require_literal_leading_dot.unwrap_or(cfg!(unix));
|
||||
|
||||
if is_forbidden(&fs_scope.scope, &path, require_literal_leading_dot)
|
||||
|| is_forbidden(&scope, &path, require_literal_leading_dot)
|
||||
{
|
||||
return Err(CommandError::Plugin(Error::PathForbidden(path)));
|
||||
}
|
||||
|
||||
if fs_scope.scope.is_allowed(&path) || scope.is_allowed(&path) {
|
||||
Ok(path)
|
||||
} else {
|
||||
Err(CommandError::Plugin(Error::PathForbidden(path)))
|
||||
}
|
||||
}
|
||||
|
||||
fn is_forbidden<P: AsRef<Path>>(
|
||||
scope: &tauri::fs::Scope,
|
||||
path: P,
|
||||
require_literal_leading_dot: bool,
|
||||
) -> bool {
|
||||
let path = path.as_ref();
|
||||
let path = if path.is_symlink() {
|
||||
match std::fs::read_link(path) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return false,
|
||||
}
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
};
|
||||
let path = if !path.exists() {
|
||||
crate::Result::Ok(path)
|
||||
} else {
|
||||
std::fs::canonicalize(path).map_err(Into::into)
|
||||
};
|
||||
|
||||
if let Ok(path) = path {
|
||||
let path: PathBuf = path.components().collect();
|
||||
scope.forbidden_patterns().iter().any(|p| {
|
||||
p.matches_path_with(
|
||||
&path,
|
||||
glob::MatchOptions {
|
||||
// this is needed so `/dir/*` doesn't match files within subdirectories such as `/dir/subdir/file.txt`
|
||||
// see: <https://github.com/tauri-apps/tauri/security/advisories/GHSA-6mv3-wm7j-h4w5>
|
||||
require_literal_separator: true,
|
||||
require_literal_leading_dot,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct StdFileResource(Mutex<File>);
|
||||
|
||||
impl StdFileResource {
|
||||
|
||||
+21
-15
@@ -15,7 +15,7 @@ use serde::Deserialize;
|
||||
use tauri::{
|
||||
ipc::ScopeObject,
|
||||
plugin::{Builder as PluginBuilder, TauriPlugin},
|
||||
utils::acl::Value,
|
||||
utils::{acl::Value, config::FsScope},
|
||||
AppHandle, DragDropEvent, Manager, RunEvent, Runtime, WindowEvent,
|
||||
};
|
||||
|
||||
@@ -39,7 +39,6 @@ pub use desktop::Fs;
|
||||
pub use mobile::Fs;
|
||||
|
||||
pub use error::Error;
|
||||
pub use scope::{Event as ScopeEvent, Scope};
|
||||
|
||||
pub use file_path::FilePath;
|
||||
pub use file_path::SafeFilePath;
|
||||
@@ -365,21 +364,26 @@ impl ScopeObject for scope::Entry {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Scope {
|
||||
pub(crate) scope: tauri::fs::Scope,
|
||||
pub(crate) require_literal_leading_dot: Option<bool>,
|
||||
}
|
||||
|
||||
pub trait FsExt<R: Runtime> {
|
||||
fn fs_scope(&self) -> &Scope;
|
||||
fn try_fs_scope(&self) -> Option<&Scope>;
|
||||
fn fs_scope(&self) -> tauri::fs::Scope;
|
||||
fn try_fs_scope(&self) -> Option<tauri::fs::Scope>;
|
||||
|
||||
/// Cross platform file system APIs that also support manipulating Android files.
|
||||
fn fs(&self) -> &Fs<R>;
|
||||
}
|
||||
|
||||
impl<R: Runtime, T: Manager<R>> FsExt<R> for T {
|
||||
fn fs_scope(&self) -> &Scope {
|
||||
self.state::<Scope>().inner()
|
||||
fn fs_scope(&self) -> tauri::fs::Scope {
|
||||
self.state::<Scope>().scope.clone()
|
||||
}
|
||||
|
||||
fn try_fs_scope(&self) -> Option<&Scope> {
|
||||
self.try_state::<Scope>().map(|s| s.inner())
|
||||
fn try_fs_scope(&self) -> Option<tauri::fs::Scope> {
|
||||
self.try_state::<Scope>().map(|s| s.scope.clone())
|
||||
}
|
||||
|
||||
fn fs(&self) -> &Fs<R> {
|
||||
@@ -419,11 +423,13 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
|
||||
watcher::unwatch
|
||||
])
|
||||
.setup(|app, api| {
|
||||
let mut scope = Scope::default();
|
||||
scope.require_literal_leading_dot = api
|
||||
.config()
|
||||
.as_ref()
|
||||
.and_then(|c| c.require_literal_leading_dot);
|
||||
let scope = Scope {
|
||||
require_literal_leading_dot: api
|
||||
.config()
|
||||
.as_ref()
|
||||
.and_then(|c| c.require_literal_leading_dot),
|
||||
scope: tauri::fs::Scope::new(app, &FsScope::default())?,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
@@ -446,9 +452,9 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
|
||||
let scope = app.fs_scope();
|
||||
for path in paths {
|
||||
if path.is_file() {
|
||||
scope.allow_file(path);
|
||||
let _ = scope.allow_file(path);
|
||||
} else {
|
||||
scope.allow_directory(path, true);
|
||||
let _ = scope.allow_directory(path, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-118
@@ -2,130 +2,18 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
sync::{
|
||||
atomic::{AtomicU32, Ordering},
|
||||
Mutex,
|
||||
},
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Entry {
|
||||
pub path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub(crate) enum EntryRaw {
|
||||
Value(PathBuf),
|
||||
Object { path: PathBuf },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Entry {
|
||||
pub path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub type EventId = u32;
|
||||
type EventListener = Box<dyn Fn(&Event) + Send>;
|
||||
|
||||
/// Scope change event.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
/// A path has been allowed.
|
||||
PathAllowed(PathBuf),
|
||||
/// A path has been forbidden.
|
||||
PathForbidden(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Scope {
|
||||
pub(crate) allowed: Mutex<Vec<PathBuf>>,
|
||||
pub(crate) denied: Mutex<Vec<PathBuf>>,
|
||||
event_listeners: Mutex<HashMap<EventId, EventListener>>,
|
||||
next_event_id: AtomicU32,
|
||||
pub(crate) require_literal_leading_dot: Option<bool>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
/// 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. If `recursive` is `true`, subdirectories will be accessible too.
|
||||
pub fn allow_directory<P: AsRef<Path>>(&self, path: P, recursive: bool) {
|
||||
let path = path.as_ref();
|
||||
|
||||
{
|
||||
let mut allowed = self.allowed.lock().unwrap();
|
||||
allowed.push(path.to_path_buf());
|
||||
allowed.push(path.join(if recursive { "**" } else { "*" }));
|
||||
}
|
||||
|
||||
self.emit(Event::PathAllowed(path.to_path_buf()));
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
let path = path.as_ref();
|
||||
|
||||
self.allowed.lock().unwrap().push(path.to_path_buf());
|
||||
|
||||
self.emit(Event::PathAllowed(path.to_path_buf()));
|
||||
}
|
||||
|
||||
/// Set the given directory path to be forbidden by this scope.
|
||||
///
|
||||
/// **Note:** this takes precedence over allowed paths, so its access gets denied **always**.
|
||||
pub fn forbid_directory<P: AsRef<Path>>(&self, path: P, recursive: bool) {
|
||||
let path = path.as_ref();
|
||||
|
||||
{
|
||||
let mut denied = self.denied.lock().unwrap();
|
||||
denied.push(path.to_path_buf());
|
||||
denied.push(path.join(if recursive { "**" } else { "*" }));
|
||||
}
|
||||
|
||||
self.emit(Event::PathForbidden(path.to_path_buf()));
|
||||
}
|
||||
|
||||
/// Set the given file path to be forbidden by this scope.
|
||||
///
|
||||
/// **Note:** this takes precedence over allowed paths, so its access gets denied **always**.
|
||||
pub fn forbid_file<P: AsRef<Path>>(&self, path: P) {
|
||||
let path = path.as_ref();
|
||||
|
||||
self.denied.lock().unwrap().push(path.to_path_buf());
|
||||
|
||||
self.emit(Event::PathForbidden(path.to_path_buf()));
|
||||
}
|
||||
|
||||
/// List of allowed paths.
|
||||
pub fn allowed(&self) -> Vec<PathBuf> {
|
||||
self.allowed.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
/// List of forbidden paths.
|
||||
pub fn forbidden(&self) -> Vec<PathBuf> {
|
||||
self.denied.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
fn next_event_id(&self) -> u32 {
|
||||
self.next_event_id.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn emit(&self, event: Event) {
|
||||
let listeners = self.event_listeners.lock().unwrap();
|
||||
let handlers = listeners.values();
|
||||
for listener in handlers {
|
||||
listener(&event);
|
||||
}
|
||||
}
|
||||
|
||||
/// Listen to an event on this scope.
|
||||
pub fn listen<F: Fn(&Event) + Send + 'static>(&self, f: F) -> EventId {
|
||||
let id = self.next_event_id();
|
||||
self.event_listeners.lock().unwrap().insert(id, Box::new(f));
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,11 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use tauri::{
|
||||
plugin::{Builder, TauriPlugin},
|
||||
scope::fs::Pattern as GlobPattern,
|
||||
Manager, Runtime,
|
||||
};
|
||||
use tauri_plugin_fs::FsExt;
|
||||
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fs::{create_dir_all, File},
|
||||
io::Write,
|
||||
path::Path,
|
||||
@@ -44,81 +42,6 @@ const PATTERNS: &[&str] = &[
|
||||
];
|
||||
const REPLACE_WITH: &[&str] = &[r"[", r"]", r"?", r"*", r"\?", r"\\?\", r"\\?\"];
|
||||
|
||||
trait ScopeExt {
|
||||
type Pattern: ToString;
|
||||
|
||||
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<Self::Pattern>;
|
||||
fn forbidden_patterns(&self) -> HashSet<Self::Pattern>;
|
||||
}
|
||||
|
||||
impl ScopeExt for tauri::scope::fs::Scope {
|
||||
type Pattern = GlobPattern;
|
||||
|
||||
fn allow_file(&self, path: &Path) {
|
||||
let _ = tauri::scope::fs::Scope::allow_file(self, path);
|
||||
}
|
||||
|
||||
fn allow_directory(&self, path: &Path, recursive: bool) {
|
||||
let _ = tauri::scope::fs::Scope::allow_directory(self, path, recursive);
|
||||
}
|
||||
|
||||
fn forbid_file(&self, path: &Path) {
|
||||
let _ = tauri::scope::fs::Scope::forbid_file(self, path);
|
||||
}
|
||||
|
||||
fn forbid_directory(&self, path: &Path, recursive: bool) {
|
||||
let _ = tauri::scope::fs::Scope::forbid_directory(self, path, recursive);
|
||||
}
|
||||
|
||||
fn allowed_patterns(&self) -> HashSet<Self::Pattern> {
|
||||
tauri::scope::fs::Scope::allowed_patterns(self)
|
||||
}
|
||||
|
||||
fn forbidden_patterns(&self) -> HashSet<Self::Pattern> {
|
||||
tauri::scope::fs::Scope::forbidden_patterns(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ScopeExt for tauri_plugin_fs::Scope {
|
||||
type Pattern = String;
|
||||
|
||||
fn allow_file(&self, path: &Path) {
|
||||
tauri_plugin_fs::Scope::allow_file(self, path);
|
||||
}
|
||||
|
||||
fn allow_directory(&self, path: &Path, recursive: bool) {
|
||||
tauri_plugin_fs::Scope::allow_directory(self, path, recursive);
|
||||
}
|
||||
|
||||
fn forbid_file(&self, path: &Path) {
|
||||
tauri_plugin_fs::Scope::forbid_file(self, path);
|
||||
}
|
||||
|
||||
fn forbid_directory(&self, path: &Path, recursive: bool) {
|
||||
tauri_plugin_fs::Scope::forbid_directory(self, path, recursive);
|
||||
}
|
||||
|
||||
fn allowed_patterns(&self) -> HashSet<Self::Pattern> {
|
||||
self.allowed()
|
||||
.into_iter()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn forbidden_patterns(&self) -> HashSet<Self::Pattern> {
|
||||
self.forbidden()
|
||||
.into_iter()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
enum Error {
|
||||
#[error(transparent)]
|
||||
@@ -179,41 +102,41 @@ fn fix_directory(path_str: &str) -> &Path {
|
||||
path
|
||||
}
|
||||
|
||||
fn allow_path(scope: &impl ScopeExt, path: &str) {
|
||||
fn allow_path(scope: &tauri::fs::Scope, path: &str) {
|
||||
let target_type = detect_scope_type(path);
|
||||
|
||||
match target_type {
|
||||
TargetType::File => {
|
||||
scope.allow_file(Path::new(path));
|
||||
let _ = scope.allow_file(Path::new(path));
|
||||
}
|
||||
TargetType::Directory => {
|
||||
// We remove the '*' at the end of it, else it will be escaped by the pattern.
|
||||
scope.allow_directory(fix_directory(path), false);
|
||||
let _ = 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.
|
||||
scope.allow_directory(fix_directory(path), true);
|
||||
let _ = scope.allow_directory(fix_directory(path), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn forbid_path(scope: &impl ScopeExt, path: &str) {
|
||||
fn forbid_path(scope: &tauri::fs::Scope, path: &str) {
|
||||
let target_type = detect_scope_type(path);
|
||||
|
||||
match target_type {
|
||||
TargetType::File => {
|
||||
scope.forbid_file(Path::new(path));
|
||||
let _ = scope.forbid_file(Path::new(path));
|
||||
}
|
||||
TargetType::Directory => {
|
||||
scope.forbid_directory(fix_directory(path), false);
|
||||
let _ = scope.forbid_directory(fix_directory(path), false);
|
||||
}
|
||||
TargetType::RecursiveDirectory => {
|
||||
scope.forbid_directory(fix_directory(path), true);
|
||||
let _ = scope.forbid_directory(fix_directory(path), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn save_scopes(scope: &impl ScopeExt, app_dir: &Path, scope_state_path: &Path) {
|
||||
fn save_scopes(scope: &tauri::fs::Scope, app_dir: &Path, scope_state_path: &Path) {
|
||||
let scope = Scope {
|
||||
allowed_paths: scope
|
||||
.allowed_patterns()
|
||||
@@ -250,8 +173,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
#[cfg(feature = "protocol-asset")]
|
||||
let asset_scope_state_path = app_dir.join(ASSET_SCOPE_STATE_FILENAME);
|
||||
|
||||
if let Some(fs_scope) = fs_scope {
|
||||
fs_scope.forbid_file(&fs_scope_state_path);
|
||||
if let Some(fs_scope) = &fs_scope {
|
||||
let _ = fs_scope.forbid_file(&fs_scope_state_path);
|
||||
} else {
|
||||
#[cfg(debug_assertions)]
|
||||
eprintln!("Please make sure to register the `fs` plugin before the `persisted-scope` plugin!");
|
||||
}
|
||||
#[cfg(feature = "protocol-asset")]
|
||||
let _ = asset_protocol_scope.forbid_file(&asset_scope_state_path);
|
||||
@@ -260,7 +186,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
// 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 let Some(fs_scope) = fs_scope {
|
||||
if let Some(fs_scope) = &fs_scope {
|
||||
if fs_scope_state_path.exists() {
|
||||
let scope: Scope = std::fs::read(&fs_scope_state_path)
|
||||
.map_err(Error::from)
|
||||
@@ -305,11 +231,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
#[cfg(feature = "protocol-asset")]
|
||||
let app_dir_ = app_dir.clone();
|
||||
|
||||
if let Some(fs_scope) = fs_scope {
|
||||
if let Some(fs_scope) = &fs_scope {
|
||||
let app_ = app.clone();
|
||||
fs_scope.listen(move |event| {
|
||||
if let tauri_plugin_fs::ScopeEvent::PathAllowed(_) = event {
|
||||
save_scopes(app_.fs_scope(), &app_dir, &fs_scope_state_path);
|
||||
if let tauri::fs::Event::PathAllowed(_) = event {
|
||||
save_scopes(&app_.fs_scope(), &app_dir, &fs_scope_state_path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user