From 12c65934300348a0f8c793e56f160904628ee0b2 Mon Sep 17 00:00:00 2001 From: scx1332 Date: Fri, 20 Sep 2024 14:09:17 +0200 Subject: [PATCH] Placeholder for serving future dashboard. Can be enabled by adding feature dashboard to build. --- .github/workflows/fast-win-build.yml | 3 +- Cargo.lock | 36 ++++++++++++++++ Cargo.toml | 3 ++ core/serv-api/web/src/middleware/auth/mod.rs | 13 +++--- core/serv/src/main.rs | 44 +++++++++++++++++++- dashboard/index.html | 11 +++++ 6 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 dashboard/index.html diff --git a/.github/workflows/fast-win-build.yml b/.github/workflows/fast-win-build.yml index cc0d729897..38e3db39ea 100644 --- a/.github/workflows/fast-win-build.yml +++ b/.github/workflows/fast-win-build.yml @@ -51,7 +51,6 @@ jobs: - name: Checkout frontend run: | - mkdir -p dashboard git clone https://github.com/scx1332/yagna-dashboard.git yagna-dashboard cd yagna-dashboard git checkout e52bb7b51d7a644acc407479332f1f4b4cda263e @@ -67,7 +66,7 @@ jobs: - name: Build run: | - cargo build --target x86_64-pc-windows-gnu --profile release-fast --features static-openssl + cargo build --target x86_64-pc-windows-gnu --profile release-fast --features dashboard,static-openssl cp target/x86_64-pc-windows-gnu/release-fast/yagna.exe yagna.exe tar -czf yagna.tar.gz yagna.exe diff --git a/Cargo.lock b/Cargo.lock index d014ad0897..12f588b7c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5985,6 +5985,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rust-embed" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.77", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" +dependencies = [ + "sha2 0.10.8", + "walkdir", +] + [[package]] name = "rust_decimal" version = "1.36.0" @@ -10403,9 +10437,11 @@ dependencies = [ "libsqlite3-sys", "log", "metrics 0.12.1", + "mime_guess", "num_cpus", "openssl", "openssl-probe", + "rust-embed", "serde", "serde_json", "structopt", diff --git a/Cargo.toml b/Cargo.toml index 69c4bd1e31..000b02d45a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ version = "0.16.0" [features] default = ['erc20-driver', 'gftp/bin'] +dashboard = ['rust-embed', 'mime_guess'] dummy-driver = ['ya-dummy-driver'] erc20-driver = ['ya-erc20-driver'] static-openssl = ["openssl/vendored", "openssl-probe"] @@ -82,9 +83,11 @@ lazy_static = "1.4" libsqlite3-sys = {workspace = true} log = "0.4" metrics = "0.12" +mime_guess = { version = "2.0", optional = true } num_cpus = "1" openssl-probe = {version = "0.1", optional = true} openssl.workspace = true +rust-embed = { version = "8.5", optional = true } serde = "1.0" serde_json = "1.0" structopt = "0.3" diff --git a/core/serv-api/web/src/middleware/auth/mod.rs b/core/serv-api/web/src/middleware/auth/mod.rs index 56533ae887..3542186f87 100644 --- a/core/serv-api/web/src/middleware/auth/mod.rs +++ b/core/serv-api/web/src/middleware/auth/mod.rs @@ -84,12 +84,13 @@ where let cache = self.cache.clone(); let service = self.service.clone(); - // TODO: remove this hack; possibly by enabling creation of arbitrary appkey from CLI - if req.uri().to_string().starts_with("/metrics-api") - || req.uri().to_string().starts_with("/version") - { - log::debug!("skipping authorization for uri={}", req.uri()); - return Box::pin(service.borrow_mut().call(req)); + let allowed_uris = vec!["/metrics-api", "/version", "/dashboard"]; + + for uri in allowed_uris { + if req.uri().to_string().starts_with(uri) { + log::debug!("skipping authorization for uri={}", req.uri()); + return Box::pin(service.borrow_mut().call(req)); + } } Box::pin(async move { diff --git a/core/serv/src/main.rs b/core/serv/src/main.rs index 9960bed5c5..05d842ee20 100644 --- a/core/serv/src/main.rs +++ b/core/serv/src/main.rs @@ -1,6 +1,6 @@ #![allow(clippy::obfuscated_if_else)] -use actix_web::{middleware, web, App, HttpServer, Responder}; +use actix_web::{middleware, web, App, HttpResponse, HttpServer, Responder}; use anyhow::{Context, Result}; use futures::prelude::*; use metrics::{counter, gauge}; @@ -568,6 +568,8 @@ impl ServiceCommand { .wrap(middleware::Logger::default()) .wrap(auth::Auth::new(cors.cache())) .wrap(cors.cors()) + .route("/dashboard", web::get().to(redirect_to_dashboard)) + .route("/dashboard/{_:.*}", web::get().to(dashboard_serve)) .route("/me", web::get().to(me)) .service(forward_gsb); let rest = Services::rest(app, &context); @@ -710,6 +712,46 @@ async fn forward_gsb( Ok::<_, actix_web::Error>(web::Json(json_resp)) } +#[cfg(feature = "dashboard")] +#[derive(rust_embed::RustEmbed)] +#[folder = "dashboard"] +struct Asset; + +pub async fn redirect_to_dashboard() -> impl Responder { + #[cfg(feature = "dashboard")] + { + let target = "/dashboard/"; + log::debug!("Redirecting to endpoint: {target}"); + HttpResponse::Ok() + .status(actix_web::http::StatusCode::PERMANENT_REDIRECT) + .append_header((actix_web::http::header::LOCATION, target)) + .finish() + } + #[cfg(not(feature = "dashboard"))] + HttpResponse::NotFound().body("404 Not Found") +} + +pub async fn dashboard_serve(path: web::Path) -> impl Responder { + #[cfg(feature = "dashboard")] + { + let mut path = path.as_str(); + let mut content = Asset::get(path); + if content.is_none() && !path.contains('.') { + path = "index.html"; + content = Asset::get(path); + } + log::debug!("Serving frontend file: {path}"); + match content { + Some(content) => HttpResponse::Ok() + .content_type(mime_guess::from_path(path).first_or_octet_stream().as_ref()) + .body(content.data.into_owned()), + None => HttpResponse::NotFound().body("404 Not Found"), + } + } + #[cfg(not(feature = "dashboard"))] + HttpResponse::NotFound().body(format!("404 Not Found: {}", path)) +} + #[actix_rt::main] async fn main() -> Result<()> { dotenv::dotenv().ok(); diff --git a/dashboard/index.html b/dashboard/index.html new file mode 100644 index 0000000000..5bdc8c3c01 --- /dev/null +++ b/dashboard/index.html @@ -0,0 +1,11 @@ + + + + + Yagna Dashboard + + +

Yagna Dashboard

+

This is placeholder, place your files into ./dashboard directory to serve them from yagna

+ +