feat: added download and upload commands
redid actions to better support different clients
This commit is contained in:
@@ -50,6 +50,7 @@ regex = "1.11.1"
|
||||
server_fn = { version = "0.7.7", features = ["multipart"] }
|
||||
multer = { version = "3.1.0", optional = true }
|
||||
uuid = { version = "1.14.0", features = ["v4"], optional = true }
|
||||
tokio-util = { version = "0.7.13", features = ["io"], optional = true }
|
||||
|
||||
sparse-actions = { path = "../sparse-actions", features = ["server"] }
|
||||
sparse-handler = { path = "../sparse-handler", optional = true }
|
||||
@@ -82,6 +83,7 @@ ssr = [
|
||||
"dep:rand",
|
||||
"dep:multer",
|
||||
"dep:uuid",
|
||||
"dep:tokio-util",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"leptos_router/ssr",
|
||||
|
||||
@@ -242,27 +242,35 @@ pub fn InstancesView() -> impl IntoView {
|
||||
let (done_with_scrolling, set_done_with_scrolling) = signal(false);
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
let (web_socket, rebuild_websocket) = signal(use_websocket::<
|
||||
BeaconClientMessage,
|
||||
BeaconViewEvent,
|
||||
codee::string::JsonSerdeCodec,
|
||||
>("/api/subscribe/listener"));
|
||||
|
||||
let user = expect_context::<ReadSignal<Option<crate::users::User>>>();
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
(web_socket.get_untracked().send)(&BeaconClientMessage::LoadHistorical(0));
|
||||
let web_socket = Memo::new_with_compare(
|
||||
move |_| {
|
||||
// subscribe to changes in the user, so that if a user signs it is possible
|
||||
// to recreate the websocket with a new session ID
|
||||
user.get();
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
Effect::new(move |_| {
|
||||
let user = expect_context::<ReadSignal<Option<crate::users::User>>>();
|
||||
user.with(move |_| {
|
||||
rebuild_websocket(use_websocket::<
|
||||
leptos::logging::log!("Recreating socket");
|
||||
|
||||
use_websocket::<
|
||||
BeaconClientMessage,
|
||||
BeaconViewEvent,
|
||||
codee::string::JsonSerdeCodec,
|
||||
>(&format!(
|
||||
"/api/subscribe/beacon/{}",
|
||||
instance_id.get().expect("could not extract ID from URL").id)
|
||||
));
|
||||
)
|
||||
},
|
||||
|_, _| true
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
Effect::new(move |_| {
|
||||
web_socket.get().ready_state.with(move |state| {
|
||||
if *state == leptos_use::core::ConnectionReadyState::Open {
|
||||
update_line_items(VecDeque::new());
|
||||
(web_socket.get_untracked().send)(&BeaconClientMessage::LoadHistorical(0));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -409,7 +417,7 @@ pub fn InstancesView() -> impl IntoView {
|
||||
{format!("command {command_id} finished executing at {result_date}")}<br/>
|
||||
</div>
|
||||
<div class="instance-hist-body">
|
||||
{action.render_data(action_result)}
|
||||
{action.render_composite_action(action_result)}
|
||||
</div>
|
||||
</div>
|
||||
}),
|
||||
|
||||
@@ -183,11 +183,13 @@ pub async fn start_listener(listener_id: i64) -> Result<(), ServerFnError> {
|
||||
));
|
||||
}
|
||||
|
||||
let target_file_path = expect_context::<std::path::PathBuf>();
|
||||
sparse_handler::start_listener(
|
||||
expect_context(),
|
||||
listener_id,
|
||||
expect_context(),
|
||||
expect_context()
|
||||
expect_context(),
|
||||
target_file_path,
|
||||
).await?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -12,6 +12,7 @@ use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use serde::Deserialize;
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
use tokio::signal;
|
||||
use tokio_util::io::ReaderStream;
|
||||
|
||||
use sparse_actions::version::Version;
|
||||
use sparse_server::app::*;
|
||||
@@ -101,6 +102,7 @@ pub struct AppState {
|
||||
leptos_options: leptos::config::LeptosOptions,
|
||||
beacon_listeners: sparse_handler::BeaconListenerMap,
|
||||
beacon_event_broadcast: tokio::sync::broadcast::Sender<sparse_handler::BeaconEvent>,
|
||||
file_store: PathBuf,
|
||||
}
|
||||
|
||||
async fn get_parameters_bytes(
|
||||
@@ -323,6 +325,41 @@ pub async fn download_beacon_installer(
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn download_file(
|
||||
State(state): State<AppState>,
|
||||
cookie_jar: CookieJar,
|
||||
Path(file_id): Path<String>
|
||||
) -> axum::response::Response {
|
||||
if let Err(e) = crate::db::user::get_auth_session_inner(
|
||||
state.db.clone(),
|
||||
cookie_jar
|
||||
).await {
|
||||
tracing::warn!("Could not load user session: {e:?}");
|
||||
return axum::http::StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
||||
}
|
||||
|
||||
let mut file_path = state.file_store.clone();
|
||||
file_path.push(file_id);
|
||||
let file = match tokio::fs::File::open(file_path).await {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
tracing::warn!("Could not open file: {e:?}");
|
||||
return axum::http::StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
||||
}
|
||||
};
|
||||
|
||||
let stream = ReaderStream::new(file);
|
||||
|
||||
use axum::http::header;
|
||||
|
||||
(
|
||||
[
|
||||
(header::CONTENT_TYPE, "application/octet-stream".to_string())
|
||||
],
|
||||
axum::body::Body::from_stream(stream).into_response()
|
||||
).into_response()
|
||||
}
|
||||
|
||||
pub async fn subscribe_to_listener_events(
|
||||
State(state): State<AppState>,
|
||||
cookie_jar: CookieJar,
|
||||
@@ -813,14 +850,16 @@ pub async fn serve_web(
|
||||
sparse_handler::start_all_listeners(
|
||||
beacon_listeners.clone(),
|
||||
db.clone(),
|
||||
beacon_event_broadcast.clone()
|
||||
beacon_event_broadcast.clone(),
|
||||
file_store.clone(),
|
||||
).await?;
|
||||
|
||||
let state = AppState {
|
||||
leptos_options: leptos_options.clone(),
|
||||
db: db.clone(),
|
||||
beacon_listeners: beacon_listeners.clone(),
|
||||
beacon_event_broadcast: beacon_event_broadcast.clone()
|
||||
beacon_event_broadcast: beacon_event_broadcast.clone(),
|
||||
file_store: file_store.clone(),
|
||||
};
|
||||
|
||||
let app = Router::new()
|
||||
@@ -829,6 +868,7 @@ pub async fn serve_web(
|
||||
get(download_beacon_installer),
|
||||
)
|
||||
.route("/binaries/beacon/:template_id", get(download_beacon))
|
||||
.route("/binaries/files/:file_id", get(download_file))
|
||||
.route(
|
||||
"/api/subscribe/listener",
|
||||
axum::routing::any(subscribe_to_listener_events)
|
||||
|
||||
Reference in New Issue
Block a user