From e8422f4b3c34c3086ba1c61d323a8380659041b6 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Tue, 12 Dec 2023 15:45:56 +0100 Subject: [PATCH] Can generate release builds --- Makefile | 9 +++ virtweb_backend/.gitignore | 1 + virtweb_backend/Cargo.lock | 57 +++++++++++++++++++ virtweb_backend/Cargo.toml | 4 +- virtweb_backend/src/app_config.rs | 11 +++- virtweb_backend/src/controllers/mod.rs | 1 + .../src/controllers/server_controller.rs | 4 -- .../src/controllers/static_controller.rs | 45 +++++++++++++++ virtweb_backend/src/main.rs | 16 +++++- .../src/middlewares/auth_middleware.rs | 5 +- virtweb_frontend/.env.production | 1 + 11 files changed, 143 insertions(+), 11 deletions(-) create mode 100644 Makefile create mode 100644 virtweb_backend/src/controllers/static_controller.rs create mode 100644 virtweb_frontend/.env.production diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..521cae6 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: frontend backend + +frontend: + cd virtweb_frontend && npm run build && cd .. + rm -rf virtweb_backend/static + mv virtweb_frontend/build virtweb_backend/static + +backend: frontend + cd virtweb_backend && cargo clippy -- -D warnings && cargo build --release diff --git a/virtweb_backend/.gitignore b/virtweb_backend/.gitignore index 9642100..1e75095 100644 --- a/virtweb_backend/.gitignore +++ b/virtweb_backend/.gitignore @@ -1,3 +1,4 @@ target/ .idea storage +static diff --git a/virtweb_backend/Cargo.lock b/virtweb_backend/Cargo.lock index ec81201..3031f89 100644 --- a/virtweb_backend/Cargo.lock +++ b/virtweb_backend/Cargo.lock @@ -2022,6 +2022,42 @@ dependencies = [ "winreg", ] +[[package]] +name = "rust-embed" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40" +dependencies = [ + "actix-web", + "mime_guess", + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.29", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2056,6 +2092,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.22" @@ -2629,9 +2674,11 @@ dependencies = [ "lazy_static", "light-openid", "log", + "mime_guess", "num", "rand", "reqwest", + "rust-embed", "serde", "serde-xml-rs", "serde_json", @@ -2644,6 +2691,16 @@ dependencies = [ "virt", ] +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" diff --git a/virtweb_backend/Cargo.toml b/virtweb_backend/Cargo.toml index 30a9512..b1e7eed 100644 --- a/virtweb_backend/Cargo.toml +++ b/virtweb_backend/Cargo.toml @@ -40,4 +40,6 @@ bytes = "1.5.0" tokio = "1.32.0" futures = "0.3.28" ipnetwork = "0.20.0" -num = "0.4.1" \ No newline at end of file +num = "0.4.1" +rust-embed = { version = "8.0.0", features = ["actix"] } +mime_guess = "2.0.4" \ No newline at end of file diff --git a/virtweb_backend/src/app_config.rs b/virtweb_backend/src/app_config.rs index 96c94fc..2afb8fa 100644 --- a/virtweb_backend/src/app_config.rs +++ b/virtweb_backend/src/app_config.rs @@ -12,10 +12,17 @@ pub struct AppConfig { #[clap(short, long, env, default_value = "0.0.0.0:8000")] pub listen_address: String, - /// Website origin + /// Website main origin #[clap(short, long, env, default_value = "http://localhost:3000")] pub website_origin: String, + /// Additional allowed website origin + /// + /// Warning! These origins won't be usable for OpenID authentication, + /// only for local auth + #[clap(long, env)] + pub additional_origins: Vec, + /// Proxy IP, might end with a star "*" #[clap(short, long, env)] pub proxy_ip: Option, @@ -74,7 +81,7 @@ pub struct AppConfig { oidc_redirect_url: String, /// Storage directory - #[arg(long, env, default_value = "storage")] + #[arg(short, long, env, default_value = "storage")] pub storage: String, /// Directory where temporary files are stored diff --git a/virtweb_backend/src/controllers/mod.rs b/virtweb_backend/src/controllers/mod.rs index a2607c3..d5dbcc9 100644 --- a/virtweb_backend/src/controllers/mod.rs +++ b/virtweb_backend/src/controllers/mod.rs @@ -9,6 +9,7 @@ pub mod auth_controller; pub mod iso_controller; pub mod network_controller; pub mod server_controller; +pub mod static_controller; pub mod vm_controller; /// Custom error to ease controller writing diff --git a/virtweb_backend/src/controllers/server_controller.rs b/virtweb_backend/src/controllers/server_controller.rs index 6d3881c..0f699e1 100644 --- a/virtweb_backend/src/controllers/server_controller.rs +++ b/virtweb_backend/src/controllers/server_controller.rs @@ -8,10 +8,6 @@ use crate::libvirt_rest_structures::HypervisorInfo; use actix_web::{HttpResponse, Responder}; use sysinfo::{NetworksExt, System, SystemExt}; -pub async fn root_index() -> impl Responder { - HttpResponse::Ok().body("Hello world!") -} - #[derive(serde::Serialize)] struct StaticConfig { auth_disabled: bool, diff --git a/virtweb_backend/src/controllers/static_controller.rs b/virtweb_backend/src/controllers/static_controller.rs new file mode 100644 index 0000000..137f0cc --- /dev/null +++ b/virtweb_backend/src/controllers/static_controller.rs @@ -0,0 +1,45 @@ +#[cfg(debug_assertions)] +pub use serve_static_debug::{root_index, serve_static_content}; +#[cfg(not(debug_assertions))] +pub use serve_static_release::{root_index, serve_static_content}; + +#[cfg(debug_assertions)] +mod serve_static_debug { + use actix_web::{HttpResponse, Responder}; + + pub async fn root_index() -> impl Responder { + HttpResponse::Ok().body("Hello world! Debug=on for VirtWeb!") + } + + pub async fn serve_static_content() -> impl Responder { + HttpResponse::NotFound().body("Hello world! Static assets are not served in debug mode") + } +} + +#[cfg(not(debug_assertions))] +mod serve_static_release { + use actix_web::{web, HttpResponse, Responder}; + use rust_embed::RustEmbed; + + #[derive(RustEmbed)] + #[folder = "static/"] + struct Asset; + + fn handle_embedded_file(path: &str, can_fallback: bool) -> HttpResponse { + match (Asset::get(path), can_fallback) { + (Some(content), _) => HttpResponse::Ok() + .content_type(mime_guess::from_path(path).first_or_octet_stream().as_ref()) + .body(content.data.into_owned()), + (None, false) => HttpResponse::NotFound().body("404 Not Found"), + (None, true) => handle_embedded_file("index.html", false), + } + } + + pub async fn root_index() -> impl Responder { + handle_embedded_file("index.html", false) + } + + pub async fn serve_static_content(path: web::Path) -> impl Responder { + handle_embedded_file(path.as_ref(), !path.as_ref().starts_with("static/")) + } +} diff --git a/virtweb_backend/src/main.rs b/virtweb_backend/src/main.rs index 39749fa..401f0d4 100644 --- a/virtweb_backend/src/main.rs +++ b/virtweb_backend/src/main.rs @@ -22,7 +22,8 @@ use virtweb_backend::constants::{ MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME, }; use virtweb_backend::controllers::{ - auth_controller, iso_controller, network_controller, server_controller, vm_controller, + auth_controller, iso_controller, network_controller, server_controller, static_controller, + vm_controller, }; use virtweb_backend::libvirt_client::LibVirtClient; use virtweb_backend::middlewares::auth_middleware::AuthChecker; @@ -69,7 +70,7 @@ async fn main() -> std::io::Result<()> { .login_deadline(Some(Duration::from_secs(MAX_SESSION_DURATION))) .build(); - let cors = Cors::default() + let mut cors = Cors::default() .allowed_origin(&AppConfig::get().website_origin) .allowed_methods(vec!["GET", "POST", "DELETE", "PUT"]) .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) @@ -77,6 +78,10 @@ async fn main() -> std::io::Result<()> { .supports_credentials() .max_age(3600); + for additional_origin in &AppConfig::get().additional_origins { + cors = cors.allowed_origin(additional_origin); + } + App::new() .wrap(Logger::default()) .wrap(AuthChecker) @@ -93,7 +98,6 @@ async fn main() -> std::io::Result<()> { .app_data(MultipartFormConfig::default().total_limit(constants::ISO_MAX_SIZE)) .app_data(TempFileConfig::default().directory(&AppConfig::get().temp_dir)) // Server controller - .route("/", web::get().to(server_controller::root_index)) .route( "/api/server/static_config", web::get().to(server_controller::static_config), @@ -231,6 +235,12 @@ async fn main() -> std::io::Result<()> { "/api/network/{uid}/stop", web::get().to(network_controller::stop), ) + // Static assets + .route("/", web::get().to(static_controller::root_index)) + .route( + "/{tail:.*}", + web::get().to(static_controller::serve_static_content), + ) }) .bind(&AppConfig::get().listen_address)? .run() diff --git a/virtweb_backend/src/middlewares/auth_middleware.rs b/virtweb_backend/src/middlewares/auth_middleware.rs index 2c8ea5a..f279216 100644 --- a/virtweb_backend/src/middlewares/auth_middleware.rs +++ b/virtweb_backend/src/middlewares/auth_middleware.rs @@ -69,7 +69,10 @@ where let auth_disabled = AppConfig::get().unsecure_disable_auth; // Check authentication, if required - if !auth_disabled && !constants::ROUTES_WITHOUT_AUTH.contains(&req.path()) { + if !auth_disabled + && !constants::ROUTES_WITHOUT_AUTH.contains(&req.path()) + && req.path().starts_with("/api/") + { let auth = match AuthExtractor::from_request(req.request(), &mut Payload::None) .into_inner() { diff --git a/virtweb_frontend/.env.production b/virtweb_frontend/.env.production new file mode 100644 index 0000000..20a1d42 --- /dev/null +++ b/virtweb_frontend/.env.production @@ -0,0 +1 @@ +REACT_APP_BACKEND=/api