Can generate release builds
This commit is contained in:
parent
f651c756b6
commit
e8422f4b3c
9
Makefile
Normal file
9
Makefile
Normal file
@ -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
|
1
virtweb_backend/.gitignore
vendored
1
virtweb_backend/.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
target/
|
target/
|
||||||
.idea
|
.idea
|
||||||
storage
|
storage
|
||||||
|
static
|
||||||
|
57
virtweb_backend/Cargo.lock
generated
57
virtweb_backend/Cargo.lock
generated
@ -2022,6 +2022,42 @@ dependencies = [
|
|||||||
"winreg",
|
"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]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.23"
|
version = "0.1.23"
|
||||||
@ -2056,6 +2092,15 @@ version = "1.0.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
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]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
@ -2629,9 +2674,11 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"light-openid",
|
"light-openid",
|
||||||
"log",
|
"log",
|
||||||
|
"mime_guess",
|
||||||
"num",
|
"num",
|
||||||
"rand",
|
"rand",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"rust-embed",
|
||||||
"serde",
|
"serde",
|
||||||
"serde-xml-rs",
|
"serde-xml-rs",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -2644,6 +2691,16 @@ dependencies = [
|
|||||||
"virt",
|
"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]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -40,4 +40,6 @@ bytes = "1.5.0"
|
|||||||
tokio = "1.32.0"
|
tokio = "1.32.0"
|
||||||
futures = "0.3.28"
|
futures = "0.3.28"
|
||||||
ipnetwork = "0.20.0"
|
ipnetwork = "0.20.0"
|
||||||
num = "0.4.1"
|
num = "0.4.1"
|
||||||
|
rust-embed = { version = "8.0.0", features = ["actix"] }
|
||||||
|
mime_guess = "2.0.4"
|
@ -12,10 +12,17 @@ pub struct AppConfig {
|
|||||||
#[clap(short, long, env, default_value = "0.0.0.0:8000")]
|
#[clap(short, long, env, default_value = "0.0.0.0:8000")]
|
||||||
pub listen_address: String,
|
pub listen_address: String,
|
||||||
|
|
||||||
/// Website origin
|
/// Website main origin
|
||||||
#[clap(short, long, env, default_value = "http://localhost:3000")]
|
#[clap(short, long, env, default_value = "http://localhost:3000")]
|
||||||
pub website_origin: String,
|
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<String>,
|
||||||
|
|
||||||
/// Proxy IP, might end with a star "*"
|
/// Proxy IP, might end with a star "*"
|
||||||
#[clap(short, long, env)]
|
#[clap(short, long, env)]
|
||||||
pub proxy_ip: Option<String>,
|
pub proxy_ip: Option<String>,
|
||||||
@ -74,7 +81,7 @@ pub struct AppConfig {
|
|||||||
oidc_redirect_url: String,
|
oidc_redirect_url: String,
|
||||||
|
|
||||||
/// Storage directory
|
/// Storage directory
|
||||||
#[arg(long, env, default_value = "storage")]
|
#[arg(short, long, env, default_value = "storage")]
|
||||||
pub storage: String,
|
pub storage: String,
|
||||||
|
|
||||||
/// Directory where temporary files are stored
|
/// Directory where temporary files are stored
|
||||||
|
@ -9,6 +9,7 @@ pub mod auth_controller;
|
|||||||
pub mod iso_controller;
|
pub mod iso_controller;
|
||||||
pub mod network_controller;
|
pub mod network_controller;
|
||||||
pub mod server_controller;
|
pub mod server_controller;
|
||||||
|
pub mod static_controller;
|
||||||
pub mod vm_controller;
|
pub mod vm_controller;
|
||||||
|
|
||||||
/// Custom error to ease controller writing
|
/// Custom error to ease controller writing
|
||||||
|
@ -8,10 +8,6 @@ use crate::libvirt_rest_structures::HypervisorInfo;
|
|||||||
use actix_web::{HttpResponse, Responder};
|
use actix_web::{HttpResponse, Responder};
|
||||||
use sysinfo::{NetworksExt, System, SystemExt};
|
use sysinfo::{NetworksExt, System, SystemExt};
|
||||||
|
|
||||||
pub async fn root_index() -> impl Responder {
|
|
||||||
HttpResponse::Ok().body("Hello world!")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
struct StaticConfig {
|
struct StaticConfig {
|
||||||
auth_disabled: bool,
|
auth_disabled: bool,
|
||||||
|
45
virtweb_backend/src/controllers/static_controller.rs
Normal file
45
virtweb_backend/src/controllers/static_controller.rs
Normal file
@ -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<String>) -> impl Responder {
|
||||||
|
handle_embedded_file(path.as_ref(), !path.as_ref().starts_with("static/"))
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,8 @@ use virtweb_backend::constants::{
|
|||||||
MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME,
|
MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME,
|
||||||
};
|
};
|
||||||
use virtweb_backend::controllers::{
|
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::libvirt_client::LibVirtClient;
|
||||||
use virtweb_backend::middlewares::auth_middleware::AuthChecker;
|
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)))
|
.login_deadline(Some(Duration::from_secs(MAX_SESSION_DURATION)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let cors = Cors::default()
|
let mut cors = Cors::default()
|
||||||
.allowed_origin(&AppConfig::get().website_origin)
|
.allowed_origin(&AppConfig::get().website_origin)
|
||||||
.allowed_methods(vec!["GET", "POST", "DELETE", "PUT"])
|
.allowed_methods(vec!["GET", "POST", "DELETE", "PUT"])
|
||||||
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
|
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
|
||||||
@ -77,6 +78,10 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.supports_credentials()
|
.supports_credentials()
|
||||||
.max_age(3600);
|
.max_age(3600);
|
||||||
|
|
||||||
|
for additional_origin in &AppConfig::get().additional_origins {
|
||||||
|
cors = cors.allowed_origin(additional_origin);
|
||||||
|
}
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(Logger::default())
|
.wrap(Logger::default())
|
||||||
.wrap(AuthChecker)
|
.wrap(AuthChecker)
|
||||||
@ -93,7 +98,6 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.app_data(MultipartFormConfig::default().total_limit(constants::ISO_MAX_SIZE))
|
.app_data(MultipartFormConfig::default().total_limit(constants::ISO_MAX_SIZE))
|
||||||
.app_data(TempFileConfig::default().directory(&AppConfig::get().temp_dir))
|
.app_data(TempFileConfig::default().directory(&AppConfig::get().temp_dir))
|
||||||
// Server controller
|
// Server controller
|
||||||
.route("/", web::get().to(server_controller::root_index))
|
|
||||||
.route(
|
.route(
|
||||||
"/api/server/static_config",
|
"/api/server/static_config",
|
||||||
web::get().to(server_controller::static_config),
|
web::get().to(server_controller::static_config),
|
||||||
@ -231,6 +235,12 @@ async fn main() -> std::io::Result<()> {
|
|||||||
"/api/network/{uid}/stop",
|
"/api/network/{uid}/stop",
|
||||||
web::get().to(network_controller::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)?
|
.bind(&AppConfig::get().listen_address)?
|
||||||
.run()
|
.run()
|
||||||
|
@ -69,7 +69,10 @@ where
|
|||||||
let auth_disabled = AppConfig::get().unsecure_disable_auth;
|
let auth_disabled = AppConfig::get().unsecure_disable_auth;
|
||||||
|
|
||||||
// Check authentication, if required
|
// 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)
|
let auth = match AuthExtractor::from_request(req.request(), &mut Payload::None)
|
||||||
.into_inner()
|
.into_inner()
|
||||||
{
|
{
|
||||||
|
1
virtweb_frontend/.env.production
Normal file
1
virtweb_frontend/.env.production
Normal file
@ -0,0 +1 @@
|
|||||||
|
REACT_APP_BACKEND=/api
|
Loading…
Reference in New Issue
Block a user