diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1b87afce..95b619a9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -503,15 +503,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "block2" version = "0.5.1" @@ -739,15 +730,6 @@ dependencies = [ "toml 0.8.23", ] -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - [[package]] name = "cc" version = "1.2.26" @@ -1220,31 +1202,23 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "dbus" -version = "0.9.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +checksum = "190b6255e8ab55a7b568df5a883e9497edc3e4821c06396612048b430e5ad1e9" dependencies = [ "libc", "libdbus-sys", - "winapi", + "windows-sys 0.59.0", ] [[package]] name = "dbus-secret-service" -version = "4.0.3" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" +checksum = "708b509edf7889e53d7efb0ffadd994cc6c2345ccb62f55cfd6b0682165e4fa6" dependencies = [ - "aes", - "block-padding", - "cbc", "dbus", - "futures-util", - "hkdf", - "num", - "once_cell", - "rand 0.8.5", - "sha2", + "zeroize", ] [[package]] @@ -2273,15 +2247,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - [[package]] name = "hmac" version = "0.12.1" @@ -2695,7 +2660,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "block-padding", "generic-array", ] @@ -2855,15 +2819,17 @@ dependencies = [ [[package]] name = "keyring" -version = "4.0.0-rc.1" +version = "3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb06f73ca0ea1cbd3858e54404585e33dccb860cb4fc8a66ad5e75a5736f3f19" +checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" dependencies = [ "byteorder", "dbus-secret-service", "log", + "security-framework 2.11.1", "security-framework 3.2.0", - "windows-sys 0.59.0", + "windows-sys 0.60.2", + "zeroize", ] [[package]] @@ -2936,9 +2902,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libdbus-sys" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +checksum = "5cbe856efeb50e4681f010e9aaa2bf0a644e10139e54cde10fc83a307c23bd9f" dependencies = [ "pkg-config", ] @@ -3359,76 +3325,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -7939,7 +7841,6 @@ dependencies = [ "charset", "chrono", "cookie", - "encoding_rs", "eventsource-client", "http", "log", @@ -8142,6 +8043,7 @@ dependencies = [ "dunce", "futures-util", "hex", + "keyring", "log", "md5 0.7.0", "path-slash", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index fe7ff77c..737bb50e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -42,7 +42,6 @@ openssl-sys = { version = "0.9.105", features = ["vendored"] } # For Ubuntu inst [dependencies] chrono = { workspace = true, features = ["serde"] } cookie = "0.18.1" -encoding_rs = "0.8.35" eventsource-client = { git = "https://github.com/yaakapp/rust-eventsource-client", version = "0.14.0" } http = { version = "1.2.0", default-features = false } log = "0.4.27" @@ -88,6 +87,7 @@ charset = "0.1.5" [workspace.dependencies] chrono = "0.4.41" hex = "0.4.3" +keyring = { version = "3.6.3", features = ["apple-native", "windows-native", "sync-secret-service"] } reqwest = "0.12.20" serde = "1.0.219" serde_json = "1.0.140" diff --git a/src-tauri/yaak-crypto/Cargo.toml b/src-tauri/yaak-crypto/Cargo.toml index 9f838038..a634439d 100644 --- a/src-tauri/yaak-crypto/Cargo.toml +++ b/src-tauri/yaak-crypto/Cargo.toml @@ -9,7 +9,7 @@ publish = false base32 = "0.5.1" # For encoding human-readable key base64 = "0.22.1" # For encoding in the database chacha20poly1305 = "0.10.1" -keyring = { version = "4.0.0-rc.1" } +keyring = { workspace = true } log = "0.4.26" serde = { workspace = true, features = ["derive"] } tauri = { workspace = true } diff --git a/src-tauri/yaak-models/src/error.rs b/src-tauri/yaak-models/src/error.rs index 515b2405..466e75b6 100644 --- a/src-tauri/yaak-models/src/error.rs +++ b/src-tauri/yaak-models/src/error.rs @@ -29,9 +29,6 @@ pub enum Error { #[error("Multiple base environments for {0}. Delete duplicates before continuing.")] MultipleBaseEnvironments(String), - - #[error("Multiple folder environments for {0}. Delete duplicates before continuing.")] - MultipleFolderEnvironments(String), #[error("unknown error")] Unknown, diff --git a/src-tauri/yaak-models/src/queries/environments.rs b/src-tauri/yaak-models/src/queries/environments.rs index f070ff56..d778add0 100644 --- a/src-tauri/yaak-models/src/queries/environments.rs +++ b/src-tauri/yaak-models/src/queries/environments.rs @@ -1,7 +1,5 @@ use crate::db_context::DbContext; -use crate::error::Error::{ - MissingBaseEnvironment, MultipleBaseEnvironments, MultipleFolderEnvironments, -}; +use crate::error::Error::{MissingBaseEnvironment, MultipleBaseEnvironments}; use crate::error::Result; use crate::models::{Environment, EnvironmentIden, EnvironmentVariable}; use crate::util::UpdateSource; diff --git a/src-tauri/yaak-plugins/Cargo.toml b/src-tauri/yaak-plugins/Cargo.toml index 3d877ca6..b58ac9c8 100644 --- a/src-tauri/yaak-plugins/Cargo.toml +++ b/src-tauri/yaak-plugins/Cargo.toml @@ -31,6 +31,7 @@ yaak-templates = { workspace = true } zip-extract = "0.4.0" chrono = { workspace = true } hex = { workspace = true } +keyring = { workspace = true } [build-dependencies] tauri-plugin = { workspace = true, features = ["build"] } diff --git a/src-tauri/yaak-plugins/src/error.rs b/src-tauri/yaak-plugins/src/error.rs index 64c515ec..6b3d40b8 100644 --- a/src-tauri/yaak-plugins/src/error.rs +++ b/src-tauri/yaak-plugins/src/error.rs @@ -32,7 +32,7 @@ pub enum Error { #[error("JSON error: {0}")] JsonErr(#[from] serde_json::Error), - + #[error("API Error: {0}")] ApiErr(String), diff --git a/src-tauri/yaak-plugins/src/events.rs b/src-tauri/yaak-plugins/src/events.rs index 7ec699eb..830bdaa6 100644 --- a/src-tauri/yaak-plugins/src/events.rs +++ b/src-tauri/yaak-plugins/src/events.rs @@ -1,5 +1,4 @@ use serde::{Deserialize, Serialize}; -use serde_json::Value; use std::collections::HashMap; use tauri::{Runtime, WebviewWindow}; use ts_rs::TS; @@ -163,7 +162,7 @@ pub enum InternalEventPayload { impl InternalEventPayload { pub fn type_name(&self) -> String { - if let Ok(Value::Object(map)) = serde_json::to_value(self) { + if let Ok(serde_json::Value::Object(map)) = serde_json::to_value(self) { map.get("type").map(|s| s.as_str().unwrap_or("unknown").to_string()) } else { None diff --git a/src-tauri/yaak-plugins/src/manager.rs b/src-tauri/yaak-plugins/src/manager.rs index aa8610a4..42907c79 100644 --- a/src-tauri/yaak-plugins/src/manager.rs +++ b/src-tauri/yaak-plugins/src/manager.rs @@ -14,7 +14,7 @@ use crate::events::{ ImportResponse, InternalEvent, InternalEventPayload, JsonPrimitive, PluginWindowContext, RenderPurpose, }; -use crate::native_template_functions::template_function_secure; +use crate::native_template_functions::{template_function_keyring, template_function_secure}; use crate::nodejs::start_nodejs_plugin_runtime; use crate::plugin_handle::PluginHandle; use crate::server_ws::PluginRuntimeServerWebsocket; @@ -514,7 +514,7 @@ impl PluginManager { // Add Rust-based functions result.push(GetTemplateFunctionsResponse { plugin_ref_id: "__NATIVE__".to_string(), // Meh - functions: vec![template_function_secure()], + functions: vec![template_function_secure(), template_function_keyring()], }); Ok(result) diff --git a/src-tauri/yaak-plugins/src/native_template_functions.rs b/src-tauri/yaak-plugins/src/native_template_functions.rs index 8ee09d99..5d56aca0 100644 --- a/src-tauri/yaak-plugins/src/native_template_functions.rs +++ b/src-tauri/yaak-plugins/src/native_template_functions.rs @@ -6,6 +6,8 @@ use crate::template_callback::PluginTemplateCallback; use base64::Engine; use base64::prelude::BASE64_STANDARD; use std::collections::HashMap; +use keyring::Error::NoEntry; +use log::debug; use tauri::{AppHandle, Runtime}; use yaak_crypto::manager::EncryptionManagerExt; use yaak_templates::error::Error::RenderError; @@ -32,6 +34,34 @@ pub(crate) fn template_function_secure() -> TemplateFunction { } } +pub(crate) fn template_function_keyring() -> TemplateFunction { + TemplateFunction { + name: "keyring".to_string(), + description: Some("Get a password from the OS keychain/keyring".to_string()), + aliases: None, + args: vec![ + TemplateFunctionArg::FormInput(FormInput::Text(FormInputText { + base: FormInputBase { + name: "service".to_string(), + label: Some("Service".to_string()), + description: Some("App or URL for the password".to_string()), + ..Default::default() + }, + ..Default::default() + })), + TemplateFunctionArg::FormInput(FormInput::Text(FormInputText { + base: FormInputBase { + name: "account".to_string(), + label: Some("Account".to_string()), + description: Some("Username or email address".to_string()), + ..Default::default() + }, + ..Default::default() + })), + ], + } +} + pub fn template_function_secure_run( app_handle: &AppHandle, args: HashMap, @@ -163,3 +193,15 @@ pub fn encrypt_secure_template_function( )? .to_string()) } + +pub fn template_function_keychain_run(args: HashMap) -> Result { + let service = args.get("service").and_then(|v| v.as_str()).unwrap_or_default().to_owned(); + let user = args.get("account").and_then(|v| v.as_str()).unwrap_or_default().to_owned(); + debug!("Getting password for service {} and user {}", service, user); + let entry = keyring::Entry::new(&service, &user).map_err(|e| RenderError(e.to_string()))?; + match entry.get_password() { + Ok(p) => Ok(p), + Err(NoEntry) => Err(RenderError(format!("No password found for '{}' and '{}'", service, user))), + Err(e) => Err(RenderError(e.to_string())), + } +} diff --git a/src-tauri/yaak-plugins/src/template_callback.rs b/src-tauri/yaak-plugins/src/template_callback.rs index 819b5856..2458f5c1 100644 --- a/src-tauri/yaak-plugins/src/template_callback.rs +++ b/src-tauri/yaak-plugins/src/template_callback.rs @@ -1,12 +1,13 @@ use crate::events::{PluginWindowContext, RenderPurpose}; use crate::manager::PluginManager; use crate::native_template_functions::{ - template_function_secure_run, template_function_secure_transform_arg, + template_function_keychain_run, template_function_secure_run, + template_function_secure_transform_arg, }; use std::collections::HashMap; use tauri::{AppHandle, Manager, Runtime}; -use yaak_templates::error::Result; use yaak_templates::TemplateCallback; +use yaak_templates::error::Result; #[derive(Clone)] pub struct PluginTemplateCallback { @@ -37,6 +38,8 @@ impl TemplateCallback for PluginTemplateCallback { if fn_name == "secure" { return template_function_secure_run(&self.app_handle, args, &self.window_context); + } else if fn_name == "keyring" { + return template_function_keychain_run(args); } let plugin_manager = &*self.app_handle.state::(); @@ -51,12 +54,7 @@ impl TemplateCallback for PluginTemplateCallback { Ok(resp) } - fn transform_arg( - &self, - fn_name: &str, - arg_name: &str, - arg_value: &str, - ) -> Result { + fn transform_arg(&self, fn_name: &str, arg_name: &str, arg_value: &str) -> Result { if fn_name == "secure" { return template_function_secure_transform_arg( &self.app_handle, diff --git a/src-web/components/HttpAuthenticationEditor.tsx b/src-web/components/HttpAuthenticationEditor.tsx index 9e4d2c6b..c8c15068 100644 --- a/src-web/components/HttpAuthenticationEditor.tsx +++ b/src-web/components/HttpAuthenticationEditor.tsx @@ -47,7 +47,9 @@ export function HttpAuthenticationEditor({ model }: Props) { if (model.authenticationType != null && authConfig.data == null) { return ( - Unknown authentication {authConfig.data} +

+ Auth plugin not found for {model.authenticationType} +

); }