Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(persisted-scope): Save asset protocol patterns #459

Merged
merged 1 commit into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/persisted-scope-save-asset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"persisted-scope": patch
---

Split up fs and asset scopes. **This will reset the asset protocol scope once!**
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 47 additions & 17 deletions plugins/persisted-scope/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use aho_corasick::AhoCorasick;
use serde::{Deserialize, Serialize};
use tauri::{
plugin::{Builder, TauriPlugin},
AppHandle, FsScope, FsScopeEvent, Manager, Runtime,
FsScope, FsScopeEvent, Manager, Runtime,
};

use std::{
Expand All @@ -15,7 +15,10 @@ use std::{
path::Path,
};

// Using 2 separate files so that we don't have to think about write conflicts and not break backwards compat.
const SCOPE_STATE_FILENAME: &str = ".persisted-scope";
#[cfg(feature = "protocol-asset")]
const ASSET_SCOPE_STATE_FILENAME: &str = ".persisted-scope-asset";

// Most of these patterns are just added to try to fix broken files in the wild.
// After a while we can hopefully reduce it to something like [r"[?]", r"[*]", r"\\?\\\?\"]
Expand Down Expand Up @@ -126,16 +129,14 @@ fn forbid_path(scope: &FsScope, path: &str) {
}
}

fn save_scopes<R: Runtime>(app: &AppHandle<R>, app_dir: &Path, scope_state_path: &Path) {
let fs_scope = app.fs_scope();

fn save_scopes(scope: &FsScope, app_dir: &Path, scope_state_path: &Path) {
let scope = Scope {
allowed_paths: fs_scope
allowed_paths: scope
.allowed_patterns()
.into_iter()
.map(|p| p.to_string())
.collect(),
forbidden_patterns: fs_scope
forbidden_patterns: scope
.forbidden_patterns()
.into_iter()
.map(|p| p.to_string())
Expand All @@ -161,45 +162,74 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
let app_dir = app.path_resolver().app_data_dir();

if let Some(app_dir) = app_dir {
let scope_state_path = app_dir.join(SCOPE_STATE_FILENAME);
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(&scope_state_path);
let _ = fs_scope.forbid_file(&fs_scope_state_path);
#[cfg(feature = "protocol-asset")]
let _ = asset_protocol_scope.forbid_file(&scope_state_path);
let _ = asset_protocol_scope.forbid_file(&asset_scope_state_path);

// We're trying to fix broken .persisted-scope files seamlessly, so we'll be running this on the values read on the saved file.
// 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 scope_state_path.exists() {
let scope: Scope = tauri::api::file::read_binary(&scope_state_path)
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))
.unwrap_or_default();

for allowed in &scope.allowed_paths {
let allowed = fix_pattern(&ac, allowed);
allow_path(&fs_scope, &allowed);
#[cfg(feature = "protocol-asset")]
allow_path(&asset_protocol_scope, &allowed);
}
for forbidden in &scope.forbidden_patterns {
let forbidden = fix_pattern(&ac, forbidden);
forbid_path(&fs_scope, &forbidden);
#[cfg(feature = "protocol-asset")]
forbid_path(&asset_protocol_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(&app, &app_dir, &scope_state_path);
save_scopes(&fs_scope, &app_dir, &fs_scope_state_path);
}

#[cfg(feature = "protocol-asset")]
if asset_scope_state_path.exists() {
let scope: Scope = tauri::api::file::read_binary(&asset_scope_state_path)
.map_err(Error::from)
.and_then(|scope| bincode::deserialize(&scope).map_err(Into::into))
.unwrap_or_default();

for allowed in &scope.allowed_paths {
let allowed = fix_pattern(&ac, allowed);
allow_path(&asset_protocol_scope, &allowed);
}
for forbidden in &scope.forbidden_patterns {
let forbidden = fix_pattern(&ac, forbidden);
forbid_path(&asset_protocol_scope, &forbidden);
}

// Manually save the fixed scopes to disk once.
save_scopes(&asset_protocol_scope, &app_dir, &asset_scope_state_path);
}

#[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(&app, &app_dir, &scope_state_path);
save_scopes(&fs_scope_, &app_dir, &fs_scope_state_path);
}
});
#[cfg(feature = "protocol-asset")]
{
let asset_protocol_scope_ = asset_protocol_scope.clone();
asset_protocol_scope.listen(move |event| {
if let FsScopeEvent::PathAllowed(_) = event {
save_scopes(&asset_protocol_scope_, &app_dir_, &asset_scope_state_path);
}
});}
}
Ok(())
})
Expand Down