Files
spacedrive/apps/desktop/src-tauri/src/app_linux.rs
Oscar Beaumont a9fceae819 improvements to spacedrive:// custom URI protocol (#550)
* fix `spacedrive://` custom protocol on Windows
(hopefully)

* custom protocol using `http::Response` + fix broken web

* import patches before App on web

* use `http::Request` for input to `handle_custom_uri`

* break  into dedicated file + error handling

* serving files via custom protocol

* cargo fmt because vscode did cringe

* lru cache to reduce video chunk request time

* add  helper to JS

* clippy be like

* remove duplicate Open buttons in context menu

* fix Linux 🙏

* no shot

* fix Windows custom URI passing (hopefully)

* better fix for custom uri on Linux

* upgrade Tauri for  feature

* switch url replacement order

* prevent React dev tools script being added in prod to desktop

* remove React devtools from html

* upgrade Tauri; required upgrading rspc, Axum, PCR

* pass typecheck + less cringe bigint

* clippy is love, clippy is life

* Typecheck plz

* fix bigint to number conversion

* use httpz + localhost server for Linux

* clippy be right

* Remove console.log

* [wip] proper auth

* fix Linux sidebar padding

* Secure Axum server with random

* Extracting app setup specific to linux to a different file

* remove outdated comment

* Some tweaks on cursom_uri.rs

* file_path_with_location doesn't need to be a named include

* fix typo

* factually wrong comment

* Change `unwrap` to `expect`

* bruh

---------

Co-authored-by: Ericson Soares <ericson.ds999@gmail.com>
2023-02-14 13:27:11 +08:00

96 lines
2.5 KiB
Rust

use std::{
net::{SocketAddr, TcpListener},
sync::Arc,
};
use sd_core::Node;
use axum::{
extract::State,
http::{Request, StatusCode},
middleware::{self, Next},
response::{IntoResponse, Response},
routing::get,
};
use httpz::{Endpoint, HttpEndpoint};
use rand::{distributions::Alphanumeric, Rng};
use tauri::{plugin::TauriPlugin, Builder, Runtime};
use tracing::debug;
use url::Url;
pub(super) async fn setup<R: Runtime>(
app: Builder<R>,
node: Arc<Node>,
endpoint: Endpoint<impl HttpEndpoint>,
) -> Builder<R> {
let signal = server::utils::axum_shutdown_signal(node);
let auth_token: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(10)
.map(char::from)
.collect();
let axum_app = axum::Router::new()
.route("/", get(|| async { "Spacedrive Server!" }))
.nest("/spacedrive", endpoint.axum())
.route_layer(middleware::from_fn_with_state(
auth_token.clone(),
auth_middleware,
))
.fallback(|| async { "404 Not Found: We're past the event horizon..." });
// Only allow current device to access it and randomise port
let listener = TcpListener::bind("127.0.0.1:0").expect("Error creating localhost server!");
let listen_addr = listener
.local_addr()
.expect("Error getting localhost server listen addr!");
debug!("Localhost server listening on: http://{:?}", listen_addr);
tokio::spawn(async move {
axum::Server::from_tcp(listener)
.expect("error creating HTTP server!")
.serve(axum_app.into_make_service())
.with_graceful_shutdown(signal)
.await
.expect("Error with HTTP server!");
});
app.plugin(spacedrive_plugin_init(&auth_token, listen_addr))
}
async fn auth_middleware<B>(
State(auth_token): State<String>,
request: Request<B>,
next: Next<B>,
) -> Response {
let url = Url::parse(&request.uri().to_string()).unwrap();
if let Some((_, v)) = url.query_pairs().find(|(k, _)| k == "token") {
if v == auth_token {
return next.run(request).await;
}
} else if let Some(v) = request
.headers()
.get("Authorization")
.and_then(|v| v.to_str().ok())
{
if v == auth_token {
return next.run(request).await;
}
}
(StatusCode::UNAUTHORIZED, "Unauthorized!").into_response()
}
pub fn spacedrive_plugin_init<R: Runtime>(
auth_token: &str,
listen_addr: SocketAddr,
) -> TauriPlugin<R> {
tauri::plugin::Builder::new("spacedrive")
.js_init_script(format!(
r#"window.__SD_CUSTOM_SERVER_AUTH_TOKEN__ = "{auth_token}"; window.__SD_CUSTOM_URI_SERVER__ = "http://{listen_addr}";"#
))
.build()
}