feat: replace custom WebDAV credential IO with pluginSwitch credential storage and retrieval the tauri_plugin_credentialsplugin and thread the AppHandle into handlers that need it.

- Import Credentials and initialize its plugin inuriBuilder.
- Replace blocking webdav::load_credentials/store calls with Credentials::load and Credentials::store to avoid spawn_blocking and centralize credential handling- AppHandle parameters to commands that need credential access:
 rename_workspace, add_webdav_workspace, store_credentials, load_credentials,
 and sync_workspace- Update save flow in add_webdav_workspace to use plugin storage after updating config.

This reduces manual blocking calls, unifies credential management andintegrates with Tauri app state for safer runtime access.
This commit is contained in:
Tristan Michael 2026-04-05 17:30:07 -07:00
parent 633337da4e
commit 501f991f2c

View file

@ -17,6 +17,7 @@ use onyx_core::{
sync::{self, SyncMode, SyncResult as CoreSyncResult}, sync::{self, SyncMode, SyncResult as CoreSyncResult},
webdav, webdav,
}; };
use tauri_plugin_credentials::Credentials;
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
/// Active file watcher stored globally so it lives for the app lifetime. /// Active file watcher stored globally so it lives for the app lifetime.
@ -163,6 +164,7 @@ fn remove_workspace(
async fn rename_workspace( async fn rename_workspace(
id: String, id: String,
new_name: String, new_name: String,
app_handle: tauri::AppHandle,
state: State<'_, Mutex<AppState>>, state: State<'_, Mutex<AppState>>,
) -> Result<(), String> { ) -> Result<(), String> {
// Extract workspace info while holding the lock briefly // Extract workspace info while holding the lock briefly
@ -205,11 +207,8 @@ async fn rename_workspace(
.split("://").nth(1) .split("://").nth(1)
.and_then(|rest| rest.split('/').next()) .and_then(|rest| rest.split('/').next())
.unwrap_or("").to_string(); .unwrap_or("").to_string();
let (username, password) = tokio::task::spawn_blocking(move || { let creds = app_handle.state::<Credentials<tauri::Wry>>();
webdav::load_credentials(&domain) let (username, password) = creds.load(&domain)?;
.map(|(u, p)| ((*u).clone(), (*p).clone()))
.map_err(|e| e.to_string())
}).await.map_err(|e| e.to_string())??;
let client = webdav::WebDavClient::new(base_url, &username, &password) let client = webdav::WebDavClient::new(base_url, &username, &password)
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
@ -639,6 +638,7 @@ fn add_webdav_workspace(
webdav_path: String, webdav_path: String,
username: String, username: String,
password: String, password: String,
app_handle: tauri::AppHandle,
state: State<'_, Mutex<AppState>>, state: State<'_, Mutex<AppState>>,
) -> Result<(), String> { ) -> Result<(), String> {
let mut s = lock_state(&state)?; let mut s = lock_state(&state)?;
@ -666,7 +666,8 @@ fn add_webdav_workspace(
.to_string(); .to_string();
s.config.save_to_file(&s.config_path.clone()).map_err(|e| e.to_string())?; s.config.save_to_file(&s.config_path.clone()).map_err(|e| e.to_string())?;
drop(s); drop(s);
webdav::store_credentials(&domain, &username, &password).map_err(|e| e.to_string())?; let creds = app_handle.state::<Credentials<tauri::Wry>>();
creds.store(&domain, &username, &password)?;
Ok(()) Ok(())
} }
@ -675,23 +676,19 @@ async fn store_credentials(
domain: String, domain: String,
username: String, username: String,
password: String, password: String,
app_handle: tauri::AppHandle,
) -> Result<(), String> { ) -> Result<(), String> {
tokio::task::spawn_blocking(move || { let creds = app_handle.state::<Credentials<tauri::Wry>>();
webdav::store_credentials(&domain, &username, &password).map_err(|e| e.to_string()) creds.store(&domain, &username, &password)
})
.await
.map_err(|e| e.to_string())?
} }
#[tauri::command] #[tauri::command]
async fn load_credentials(domain: String) -> Result<(String, String), String> { async fn load_credentials(
tokio::task::spawn_blocking(move || { domain: String,
webdav::load_credentials(&domain) app_handle: tauri::AppHandle,
.map(|(u, p)| ((*u).clone(), (*p).clone())) ) -> Result<(String, String), String> {
.map_err(|e| e.to_string()) let creds = app_handle.state::<Credentials<tauri::Wry>>();
}) creds.load(&domain)
.await
.map_err(|e| e.to_string())?
} }
#[tauri::command] #[tauri::command]
@ -712,6 +709,7 @@ async fn test_webdav_connection(
async fn sync_workspace( async fn sync_workspace(
workspace_id: String, workspace_id: String,
mode: String, mode: String,
app_handle: tauri::AppHandle,
state: State<'_, Mutex<AppState>>, state: State<'_, Mutex<AppState>>,
) -> Result<SyncResult, String> { ) -> Result<SyncResult, String> {
// Step 1: read config — combine base URL with the user-chosen remote path // Step 1: read config — combine base URL with the user-chosen remote path
@ -734,13 +732,8 @@ async fn sync_workspace(
.and_then(|rest| rest.split('/').next()) .and_then(|rest| rest.split('/').next())
.unwrap_or("") .unwrap_or("")
.to_string(); .to_string();
let (username, password) = tokio::task::spawn_blocking(move || { let creds = app_handle.state::<Credentials<tauri::Wry>>();
webdav::load_credentials(&domain) let (username, password) = creds.load(&domain)?;
.map(|(u, p)| ((*u).clone(), (*p).clone()))
.map_err(|e| e.to_string())
})
.await
.map_err(|e| e.to_string())??;
let sync_mode = match mode.as_str() { let sync_mode = match mode.as_str() {
"push" => SyncMode::Push, "push" => SyncMode::Push,
@ -831,6 +824,7 @@ pub fn run() {
tauri::Builder::default() tauri::Builder::default()
.plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_credentials::init())
.setup(|app| { .setup(|app| {
// Resolve app data dir and config path // Resolve app data dir and config path
let app_data_dir = app.path().app_data_dir() let app_data_dir = app.path().app_data_dir()