From e103fa9f282980c6458a8d94f8b252965665b252 Mon Sep 17 00:00:00 2001 From: Andrew Rioux Date: Sat, 22 Feb 2025 20:30:32 -0500 Subject: [PATCH] feat: added live updates for checking in --- sparse-handler/src/error.rs | 10 +++++++++ sparse-handler/src/lib.rs | 6 ++--- sparse-handler/src/router.rs | 4 ++++ sparse-server/src/beacons/sidebar.rs | 25 ++++++++++++--------- sparse-server/src/webserver.rs | 27 +++++++++++++++++++++++ sparse-server/style/beacons/_sidebar.scss | 6 ++++- 6 files changed, 62 insertions(+), 16 deletions(-) diff --git a/sparse-handler/src/error.rs b/sparse-handler/src/error.rs index f4b2ae7..b4a1abd 100644 --- a/sparse-handler/src/error.rs +++ b/sparse-handler/src/error.rs @@ -12,6 +12,7 @@ pub enum Error { Rustls(rustls::Error), Rcgen(rcgen::Error), WebPki(rustls::client::VerifierBuilderError), + TokioSend, } impl std::fmt::Display for Error { @@ -38,6 +39,9 @@ impl std::fmt::Display for Error { Error::WebPki(err) => { write!(f, "webpki error: {err:?}") } + Error::TokioSend => { + write!(f, "tokio broadcast error") + } } } } @@ -105,3 +109,9 @@ impl From for Error { Self::WebPki(err) } } + +impl From> for Error { + fn from(_: tokio::sync::broadcast::error::SendError) -> Self { + Self::TokioSend + } +} diff --git a/sparse-handler/src/lib.rs b/sparse-handler/src/lib.rs index 944477f..3b4b3b9 100644 --- a/sparse-handler/src/lib.rs +++ b/sparse-handler/src/lib.rs @@ -107,9 +107,7 @@ pub async fn start_listener( .fetch_one(&db) .await?; - let sender = broadcast::Sender::new(128); - - let app = router::get_router(db, sender.clone()); + let app = router::get_router(db, beacon_event_broadcast.clone()); let ca_cert = rustls::pki_types::CertificateDer::from(listener.certificate.clone()); @@ -182,7 +180,7 @@ pub async fn start_listener( )); }; - blm_handle.insert(listener_id, BeaconListenerHandle { join_handle, events_broadcast: sender }); + blm_handle.insert(listener_id, BeaconListenerHandle { join_handle, events_broadcast: beacon_event_broadcast }); Ok(()) } diff --git a/sparse-handler/src/router.rs b/sparse-handler/src/router.rs index 9988535..17202a7 100644 --- a/sparse-handler/src/router.rs +++ b/sparse-handler/src/router.rs @@ -76,6 +76,8 @@ pub async fn handle_checkin( let current_beacon_reg = match current_beacon_reg { Some(rec) => { + state.event_publisher.send(BeaconEvent::Checkin(reg.beacon_id.clone()))?; + parse_db_config(rec) }, None => { @@ -111,6 +113,8 @@ pub async fn handle_checkin( .fetch_one(&state.db) .await?; + state.event_publisher.send(BeaconEvent::NewBeacon(reg.beacon_id.clone()))?; + parse_db_config(rec) } }; diff --git a/sparse-server/src/beacons/sidebar.rs b/sparse-server/src/beacons/sidebar.rs index f6a5f51..6173877 100644 --- a/sparse-server/src/beacons/sidebar.rs +++ b/sparse-server/src/beacons/sidebar.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use leptos::{either::Either, prelude::*}; +use leptos_router::components::A; #[cfg(feature = "hydrate")] use leptos_use::use_websocket; use serde::{Deserialize, Serialize}; @@ -62,7 +63,7 @@ pub struct CurrentBeaconInstance { unsafe impl Send for CurrentBeaconInstance {} unsafe impl Send for SidebarEvents {} -#[derive(Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum SidebarEvents { BeaconList(Vec), NewBeacon(CurrentBeaconInstance), @@ -99,6 +100,8 @@ pub fn BeaconSidebar() -> impl IntoView { return; }; + leptos::logging::log!("Received message: {m:?}"); + match m { SidebarEvents::BeaconList(bs) => { let mut bs = bs.to_vec(); @@ -125,6 +128,7 @@ pub fn BeaconSidebar() -> impl IntoView { return; }; if let Some(ref mut b) = bs.iter_mut().find(|b| b.beacon_id == *bid) { + leptos::logging::log!("Found beacon to check in"); b.last_checkin = chrono::Utc::now(); } }), @@ -163,10 +167,6 @@ pub fn BeaconSidebar() -> impl IntoView { let partitions = move || -> Vec { use regex::Regex; - leptos::logging::log!( - "There are {:?} beacons", - current_beacons.read().as_ref().map(Vec::len) - ); let sm = sort_method.read(); let search_regex = Regex::new(&*search_input.read()); let str_match_search = { @@ -558,23 +558,26 @@ pub fn BeaconSidebar() -> impl IntoView {
{match &*beacon.nickname { "" => Either::Left(view! { - {beacon.beacon_id.clone()} + + {beacon.beacon_id.clone()} + }), nick => { let nick = nick.to_string(); Either::Right(view! { - {nick} - "(" {beacon.beacon_id.clone()} ")" + + {nick} + "(" {beacon.beacon_id.clone()} ")" + }) } }} diff --git a/sparse-server/src/webserver.rs b/sparse-server/src/webserver.rs index d18ba20..7f587fe 100644 --- a/sparse-server/src/webserver.rs +++ b/sparse-server/src/webserver.rs @@ -430,8 +430,35 @@ async fn handle_listener_events( let mut event_receiver = state.beacon_event_broadcast.subscribe(); loop { + use sparse_handler::BeaconEvent; + let event = event_receiver.recv().await; + match event { + Ok(BeaconEvent::Checkin(bid)) => { + socket.send(ws::Message::Text(serde_json::to_string(&SidebarEvents::Checkin(bid.clone()))?)).await?; + } + Ok(BeaconEvent::NewBeacon(bid)) => { + let beacons = sqlx::query!( + "SELECT template_id, peer_ip, nickname, cwd, operating_system, beacon_userent, hostname, config_id FROM beacon_instance + WHERE beacon_id = ?", + bid + ) + .fetch_one(&state.db) + .await?; + + let category_ids = sqlx::query!( + "SELECT category_id FROM beacon_category_assignment + WHERE beacon_id = ?", + bid + ) + .fetch_one(&state.db) + .await?; + } + Err(e) => { + tracing::warn!("Unable to handle general event: {e:?}"); + } + } } } diff --git a/sparse-server/style/beacons/_sidebar.scss b/sparse-server/style/beacons/_sidebar.scss index 1ce628c..29c4ac5 100644 --- a/sparse-server/style/beacons/_sidebar.scss +++ b/sparse-server/style/beacons/_sidebar.scss @@ -66,7 +66,11 @@ aside.beacons { color: yellow; } - .beacon-instance-id { + .beacon-instance-id a { + text-decoration: none; + &:hover { + text-decoration: underline; + } } }