diff options
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/rbw-agent/actions.rs | 54 | ||||
-rw-r--r-- | src/bin/rbw-agent/agent.rs | 26 | ||||
-rw-r--r-- | src/bin/rbw/actions.rs | 6 | ||||
-rw-r--r-- | src/bin/rbw/commands.rs | 10 |
4 files changed, 63 insertions, 33 deletions
diff --git a/src/bin/rbw-agent/actions.rs b/src/bin/rbw-agent/actions.rs index 1974736..c44f601 100644 --- a/src/bin/rbw-agent/actions.rs +++ b/src/bin/rbw-agent/actions.rs @@ -1,4 +1,5 @@ use anyhow::Context as _; +use copypasta::ClipboardProvider as _; pub async fn register( sock: &mut crate::sock::Sock, @@ -79,7 +80,7 @@ pub async fn register( pub async fn login( sock: &mut crate::sock::Sock, - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, tty: Option<&str>, ) -> anyhow::Result<()> { let db = load_db().await.unwrap_or_else(|_| rbw::db::Db::new()); @@ -311,7 +312,7 @@ async fn two_factor( } async fn login_success( - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, access_token: String, refresh_token: String, kdf: rbw::api::KdfType, @@ -356,7 +357,7 @@ async fn login_success( match res { Ok((keys, org_keys)) => { - let mut state = state.write().await; + let mut state = state.lock().await; state.priv_key = Some(keys); state.org_keys = Some(org_keys); } @@ -368,10 +369,10 @@ async fn login_success( pub async fn unlock( sock: &mut crate::sock::Sock, - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, tty: Option<&str>, ) -> anyhow::Result<()> { - if state.read().await.needs_unlock() { + if state.lock().await.needs_unlock() { let db = load_db().await?; let Some(kdf) = db.kdf @@ -464,11 +465,11 @@ pub async fn unlock( } async fn unlock_success( - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, keys: rbw::locked::Keys, org_keys: std::collections::HashMap<String, rbw::locked::Keys>, ) -> anyhow::Result<()> { - let mut state = state.write().await; + let mut state = state.lock().await; state.priv_key = Some(keys); state.org_keys = Some(org_keys); Ok(()) @@ -476,9 +477,9 @@ async fn unlock_success( pub async fn lock( sock: &mut crate::sock::Sock, - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, ) -> anyhow::Result<()> { - state.write().await.clear(); + state.lock().await.clear(); respond_ack(sock).await?; @@ -487,10 +488,10 @@ pub async fn lock( pub async fn check_lock( sock: &mut crate::sock::Sock, - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, _tty: Option<&str>, ) -> anyhow::Result<()> { - if state.read().await.needs_unlock() { + if state.lock().await.needs_unlock() { return Err(anyhow::anyhow!("agent is locked")); } @@ -538,11 +539,11 @@ pub async fn sync( pub async fn decrypt( sock: &mut crate::sock::Sock, - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, cipherstring: &str, org_id: Option<&str>, ) -> anyhow::Result<()> { - let state = state.read().await; + let state = state.lock().await; let Some(keys) = state.key(org_id) else { return Err(anyhow::anyhow!( @@ -565,11 +566,11 @@ pub async fn decrypt( pub async fn encrypt( sock: &mut crate::sock::Sock, - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, plaintext: &str, org_id: Option<&str>, ) -> anyhow::Result<()> { - let state = state.read().await; + let state = state.lock().await; let Some(keys) = state.key(org_id) else { return Err(anyhow::anyhow!( @@ -587,6 +588,25 @@ pub async fn encrypt( Ok(()) } +pub async fn clipboard_store( + sock: &mut crate::sock::Sock, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, + text: &str, +) -> anyhow::Result<()> { + state + .lock() + .await + .clipboard + .set_contents(text.to_owned()) + .map_err(|e| { + anyhow::anyhow!("couldn't store value to clipboard: {e}") + })?; + + respond_ack(sock).await?; + + Ok(()) +} + pub async fn version(sock: &mut crate::sock::Sock) -> anyhow::Result<()> { sock.send(&rbw::protocol::Response::Version { version: rbw::protocol::version(), @@ -663,7 +683,7 @@ async fn config_pinentry() -> anyhow::Result<String> { } pub async fn subscribe_to_notifications( - state: std::sync::Arc<tokio::sync::RwLock<crate::agent::State>>, + state: std::sync::Arc<tokio::sync::Mutex<crate::agent::State>>, ) -> anyhow::Result<()> { // access token might be out of date, so we do a sync to refresh it sync(None).await?; @@ -685,7 +705,7 @@ pub async fn subscribe_to_notifications( + "/notifications/hub?access_token="; websocket_url.push_str(&access_token); - let mut state = state.write().await; + let mut state = state.lock().await; let err = state .notifications_handler .connect(websocket_url) diff --git a/src/bin/rbw-agent/agent.rs b/src/bin/rbw-agent/agent.rs index d4b3341..fe46e3b 100644 --- a/src/bin/rbw-agent/agent.rs +++ b/src/bin/rbw-agent/agent.rs @@ -12,6 +12,7 @@ pub struct State { pub sync_timeout: crate::timeout::Timeout, pub sync_timeout_duration: std::time::Duration, pub notifications_handler: crate::notifications::Handler, + pub clipboard: copypasta::ClipboardContext, } impl State { @@ -43,7 +44,7 @@ impl State { pub struct Agent { timer_r: tokio::sync::mpsc::UnboundedReceiver<()>, sync_timer_r: tokio::sync::mpsc::UnboundedReceiver<()>, - state: std::sync::Arc<tokio::sync::RwLock<State>>, + state: std::sync::Arc<tokio::sync::Mutex<State>>, } impl Agent { @@ -59,10 +60,13 @@ impl Agent { sync_timeout.set(sync_timeout_duration); } let notifications_handler = crate::notifications::Handler::new(); + let clipboard = copypasta::ClipboardContext::new().map_err(|e| { + anyhow::anyhow!("couldn't create clipboard context: {e}") + })?; Ok(Self { timer_r, sync_timer_r, - state: std::sync::Arc::new(tokio::sync::RwLock::new(State { + state: std::sync::Arc::new(tokio::sync::Mutex::new(State { priv_key: None, org_keys: None, timeout, @@ -70,6 +74,7 @@ impl Agent { sync_timeout, sync_timeout_duration, notifications_handler, + clipboard, })), }) } @@ -95,7 +100,7 @@ impl Agent { notifications::NotificationMessage, > = { self.state - .write() + .lock() .await .notifications_handler .get_channel() @@ -148,7 +153,7 @@ impl Agent { }); } Event::Timeout(()) => { - self.state.write().await.clear(); + self.state.lock().await.clear(); } Event::Sync(()) => { // this could fail if we aren't logged in, but we don't @@ -159,7 +164,7 @@ impl Agent { if let Err(e) = result { eprintln!("failed to sync: {e:#}"); } else if !state - .write() + .lock() .await .notifications_handler .is_connected() @@ -174,7 +179,7 @@ impl Agent { } } }); - self.state.write().await.set_sync_timeout(); + self.state.lock().await.set_sync_timeout(); } } } @@ -184,7 +189,7 @@ impl Agent { async fn handle_request( sock: &mut crate::sock::Sock, - state: std::sync::Arc<tokio::sync::RwLock<State>>, + state: std::sync::Arc<tokio::sync::Mutex<State>>, ) -> anyhow::Result<()> { let req = sock.recv().await?; let req = match req { @@ -249,6 +254,11 @@ async fn handle_request( .await?; true } + rbw::protocol::Action::ClipboardStore { text } => { + crate::actions::clipboard_store(sock, state.clone(), text) + .await?; + true + } rbw::protocol::Action::Quit => std::process::exit(0), rbw::protocol::Action::Version => { crate::actions::version(sock).await?; @@ -257,7 +267,7 @@ async fn handle_request( }; if set_timeout { - state.write().await.set_timeout(); + state.lock().await.set_timeout(); } Ok(()) diff --git a/src/bin/rbw/actions.rs b/src/bin/rbw/actions.rs index 29cd6fe..e0e7a2e 100644 --- a/src/bin/rbw/actions.rs +++ b/src/bin/rbw/actions.rs @@ -101,6 +101,12 @@ pub fn encrypt( } } +pub fn clipboard_store(text: &str) -> anyhow::Result<()> { + simple_action(rbw::protocol::Action::ClipboardStore { + text: text.to_string(), + }) +} + pub fn version() -> anyhow::Result<u32> { let mut sock = connect()?; sock.send(&rbw::protocol::Request { diff --git a/src/bin/rbw/commands.rs b/src/bin/rbw/commands.rs index 03f07b3..10f981d 100644 --- a/src/bin/rbw/commands.rs +++ b/src/bin/rbw/commands.rs @@ -1,5 +1,4 @@ use anyhow::Context as _; -use copypasta::{ClipboardContext, ClipboardProvider}; use serde::Serialize; use std::io; use std::io::prelude::Write; @@ -741,13 +740,8 @@ pub fn config_unset(key: &str) -> anyhow::Result<()> { } fn clipboard_store(val: &str) -> anyhow::Result<()> { - let mut ctx = ClipboardContext::new().map_err(|e| { - anyhow::anyhow!("couldn't create clipboard context: {e}") - })?; - - ctx.set_contents(val.to_owned()).map_err(|e| { - anyhow::anyhow!("couldn't store value to clipboard: {e}") - })?; + ensure_agent()?; + crate::actions::clipboard_store(val)?; Ok(()) } |