diff --git a/.github/workflows/push-build.yml b/.github/workflows/push-build.yml index 5af189b4..d4623789 100644 --- a/.github/workflows/push-build.yml +++ b/.github/workflows/push-build.yml @@ -42,16 +42,16 @@ jobs: run: yarn build - name: Copy "dist" folder run: cp -r src/frontend/dist/. src/backend/dist/ - - name: Build amd64 + - name: Build x86_64 working-directory: src/backend run: cross build --release --target x86_64-unknown-linux-musl - - name: Build armv6 + - name: Build armv6l working-directory: src/backend run: cross build --release --target arm-unknown-linux-musleabihf - - name: Build armv7 + - name: Build armv7l working-directory: src/backend run: cross build --release --target armv7-unknown-linux-musleabihf - - name: Build armv8 + - name: Build aarch64 working-directory: src/backend run: cross build --release --target aarch64-unknown-linux-musl - uses: actions/upload-artifact@v2 @@ -70,4 +70,32 @@ jobs: with: name: dietpi-dashboard-aarch64 path: src/backend/target/aarch64-unknown-linux-musl/release/dietpi-dashboard + - name: Build x86_64 (backend only) + working-directory: src/backend + run: cross build --release --target x86_64-unknown-linux-musl --no-default-features + - name: Build armv6l (backend only) + working-directory: src/backend + run: cross build --release --target arm-unknown-linux-musleabihf --no-default-features + - name: Build armv7l (backend only) + working-directory: src/backend + run: cross build --release --target armv7-unknown-linux-musleabihf --no-default-features + - name: Build aarch64 (backend only) + working-directory: src/backend + run: cross build --release --target aarch64-unknown-linux-musl --no-default-features + - uses: actions/upload-artifact@v2 + with: + name: dietpi-dashboard-x86_64-backend + path: src/backend/target/x86_64-unknown-linux-musl/release/dietpi-dashboard + - uses: actions/upload-artifact@v2 + with: + name: dietpi-dashboard-armv6l-backend + path: src/backend/target/arm-unknown-linux-musleabihf/release/dietpi-dashboard + - uses: actions/upload-artifact@v2 + with: + name: dietpi-dashboard-armv7l-backend + path: src/backend/target/armv7-unknown-linux-musleabihf/release/dietpi-dashboard + - uses: actions/upload-artifact@v2 + with: + name: dietpi-dashboard-aarch64-backend + path: src/backend/target/aarch64-unknown-linux-musl/release/dietpi-dashboard diff --git a/config.toml b/config.toml index 9d519fe3..cc081fa8 100644 --- a/config.toml +++ b/config.toml @@ -12,4 +12,9 @@ # To get hash: "echo -n '' | sha512sum" #hash = "SHA512 hash of password" # To get random secret: "openssl rand -hex 32" -#secret = "64-character secret" \ No newline at end of file +#secret = "64-character secret" +# Other nodes viewable on frontend page +# - Default: [] +# Please insert the IP addresses/domains and ports of these nodes +# For example: ["example.com:5252", "192.168.1.60:4386"] +nodes = ["192.168.1.100:5252"] \ No newline at end of file diff --git a/src/backend/Cargo.lock b/src/backend/Cargo.lock index 318fe433..212fae66 100644 --- a/src/backend/Cargo.lock +++ b/src/backend/Cargo.lock @@ -323,9 +323,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f" dependencies = [ "cfg-if", ] @@ -376,6 +376,7 @@ dependencies = [ "sha2", "simple_logger", "tokio", + "toml", "warp", ] @@ -1607,6 +1608,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + [[package]] name = "tower-service" version = "0.3.1" diff --git a/src/backend/Cargo.toml b/src/backend/Cargo.toml index c0b1f560..7011c6a6 100644 --- a/src/backend/Cargo.toml +++ b/src/backend/Cargo.toml @@ -6,12 +6,12 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -warp = {version = "0.3.2", default-features = false, features = ["compression", "websocket", "tls"]} +warp = {version = "0.3.2", default-features = false, features = ["websocket", "tls"]} tokio = { version = "1", features = ["rt-multi-thread", "macros", "time", "sync"] } num_cpus = "1.13.0" simple_logger = "1.16.0" log = "0.4.14" -include_dir = "0.7.2" +include_dir = {version = "0.7.2", optional = true} lazy_static = "1.4.0" futures = "0.3.18" nanoserde = "0.1.29" @@ -20,6 +20,11 @@ heim = { git = "https://github.com/heim-rs/heim", features = ["cpu", "disk", "ho infer = { version = "0.5.0", default-features = false } jwts = "0.2.3" sha2 = "0.10.0" +toml = "0.5.8" + +[features] +default = ["frontend"] +frontend = ["include_dir", "warp/compression"] [profile.release] lto = "fat" diff --git a/src/backend/src/config.rs b/src/backend/src/config.rs index ca75e108..457423e1 100644 --- a/src/backend/src/config.rs +++ b/src/backend/src/config.rs @@ -1,4 +1,4 @@ -use nanoserde::{Toml, TomlParser}; +use toml::Value; pub struct Config { pub port: u16, @@ -10,72 +10,102 @@ pub struct Config { pub pass: bool, pub hash: String, pub secret: String, + + #[cfg(feature = "frontend")] + pub nodes: Vec, } pub fn config() -> Config { let mut cfgpath = std::env::current_exe().unwrap(); cfgpath.set_file_name("config.toml"); - let cfg = TomlParser::parse( - &match std::fs::read_to_string(cfgpath) { - Err(ref e) if e.kind() == std::io::ErrorKind::NotFound => { - std::fs::write("config.toml", "").unwrap(); - String::new() - } - Ok(cfg) => cfg, - Err(e) => { - panic!("Config file could not be read: {}", e); - } + let cfg = &match std::fs::read_to_string(cfgpath) { + Err(ref e) if e.kind() == std::io::ErrorKind::NotFound => { + std::fs::write("config.toml", "").unwrap(); + String::new() + } + Ok(cfg) => cfg, + Err(e) => { + panic!("Config file could not be read: {}", e); } - .lines() - .filter(|line| !line.starts_with('#')) // Remove comments, parser can't handle them - .map(|line| line.to_string() + "\n") - .collect::(), - ) + } + .parse::() .expect("Invalid config file"); #[allow(clippy::cast_sign_loss)] #[allow(clippy::cast_possible_truncation)] - let port: u16 = cfg.get("port").unwrap_or(&Toml::Num(5252.0)).num() as u16; + let port: u16 = cfg + .get("port") + .unwrap_or(&Value::Integer(5252)) + .as_integer() + .unwrap() as u16; - let tls = cfg.get("tls").unwrap_or(&Toml::Bool(false)); + let tls = cfg + .get("tls") + .unwrap_or(&Value::Boolean(false)) + .as_bool() + .unwrap(); let mut cert = String::new(); let mut key = String::new(); - if tls == &Toml::Bool(true) { + if tls { cert = cfg .get("cert") - .unwrap_or(&Toml::Str(String::new())) - .str() + .unwrap_or(&Value::String(String::new())) + .as_str() + .unwrap() .to_string(); key = cfg .get("key") - .unwrap_or(&Toml::Str(String::new())) - .str() + .unwrap_or(&Value::String(String::new())) + .as_str() + .unwrap() .to_string(); } - let pass = cfg.get("pass").unwrap_or(&Toml::Bool(false)); + let pass = cfg + .get("pass") + .unwrap_or(&Value::Boolean(false)) + .as_bool() + .unwrap(); + let mut hash = String::new(); let mut secret = String::new(); - if pass == &Toml::Bool(true) { + if pass { hash = cfg .get("hash") - .unwrap_or(&Toml::Str(String::new())) - .str() + .unwrap_or(&Value::String(String::new())) + .as_str() + .unwrap() .to_string(); secret = cfg .get("secret") - .unwrap_or(&Toml::Str(String::new())) - .str() + .unwrap_or(&Value::String(String::new())) + .as_str() + .unwrap() .to_string(); } + #[cfg(feature = "frontend")] + let mut nodes = Vec::new(); + + #[cfg(feature = "frontend")] + for i in cfg + .get("nodes") + .unwrap_or(&Value::Array(Vec::new())) + .as_array() + .unwrap() + { + nodes.push(i.as_str().unwrap().to_string()); + } + Config { port, - tls: tls == &Toml::Bool(true), + tls, cert, key, - pass: pass == &Toml::Bool(true), + pass, hash, secret, + #[cfg(feature = "frontend")] + nodes, } } diff --git a/src/backend/src/main.rs b/src/backend/src/main.rs index 61c17c7c..91a00f47 100644 --- a/src/backend/src/main.rs +++ b/src/backend/src/main.rs @@ -18,6 +18,7 @@ fn main() { .build() .unwrap() .block_on(async { + #[cfg(feature = "frontend")] const DIR: include_dir::Dir = include_dir::include_dir!("dist"); SimpleLogger::new() @@ -27,6 +28,7 @@ fn main() { .init() .unwrap(); + #[cfg(feature = "frontend")] let favicon_route = warp::path("favicon.png").map(|| { warp::reply::with_header( DIR.get_file("favicon.png").unwrap().contents(), @@ -35,6 +37,7 @@ fn main() { ) }); + #[cfg(feature = "frontend")] let assets_route = warp::path("assets") .and(warp::path::param()) .map(|path: String| { @@ -87,7 +90,11 @@ fn main() { "No login needed".to_string(), warp::http::StatusCode::OK, ) - }); + }) + .with(warp::reply::with::header( + "Access-Control-Allow-Origin", + "*", + )); let terminal_route = warp::path!("ws" / "term") .and(warp::ws()) @@ -97,20 +104,21 @@ fn main() { .and(warp::ws()) .map(|ws: warp::ws::Ws| ws.on_upgrade(sockets::socket_handler)); + #[cfg(feature = "frontend")] let main_route = warp::any().map(|| { warp::reply::html(DIR.get_file("index.html").unwrap().contents_utf8().unwrap()) }); + #[cfg(feature = "frontend")] let page_routes = favicon_route .or(assets_route) - .or(login_route) .or(main_route) .with(warp::compression::gzip()); let socket_routes = terminal_route.or(socket_route); let routes = socket_routes - .or(page_routes) + .or(login_route) .with(warp::log::custom(|info| { log::info!("Request to {}", info.path()); log::debug!( @@ -122,6 +130,9 @@ fn main() { ); })); + #[cfg(feature = "frontend")] + let routes = routes.or(page_routes); + if CONFIG.tls { warp::serve(routes) .tls() diff --git a/src/backend/src/shared.rs b/src/backend/src/shared.rs index 6e9053d8..71faf092 100644 --- a/src/backend/src/shared.rs +++ b/src/backend/src/shared.rs @@ -122,6 +122,8 @@ pub struct ServiceList { pub struct GlobalData { pub update: String, pub login: bool, + #[cfg(feature = "frontend")] + pub nodes: Vec, } #[derive(SerJson, Debug)] diff --git a/src/backend/src/systemdata.rs b/src/backend/src/systemdata.rs index 37738ba4..a5b33946 100644 --- a/src/backend/src/systemdata.rs +++ b/src/backend/src/systemdata.rs @@ -419,6 +419,8 @@ pub fn global() -> shared::GlobalData { shared::GlobalData { update, login: crate::CONFIG.pass, + #[cfg(feature = "frontend")] + nodes: crate::CONFIG.nodes.clone(), } } diff --git a/src/frontend/.yarn/install-state.gz b/src/frontend/.yarn/install-state.gz index 2a00e34a..abe41fbd 100644 Binary files a/src/frontend/.yarn/install-state.gz and b/src/frontend/.yarn/install-state.gz differ diff --git a/src/frontend/index.html b/src/frontend/index.html index c994e7f7..a3f919cb 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -4,7 +4,7 @@ + content="default-src 'self'; font-src 'self'; img-src 'self'; script-src 'self'; style-src 'unsafe-inline' 'self'; connect-src * ws:;" /> DietPi Dashboard diff --git a/src/frontend/src/App.svelte b/src/frontend/src/App.svelte index 9133abfa..e6d3de10 100755 --- a/src/frontend/src/App.svelte +++ b/src/frontend/src/App.svelte @@ -1,7 +1,6 @@
@@ -289,19 +298,92 @@ target="_blank" >DietPi logo - {#if update != ""} - DietPi update avalible: {update} + +
+ + (notificationsShown = !notificationsShown)} + > + + {#if notificationsShown && window.innerWidth >= 768} +
+
+ + {#if update} + DietPi update avalible: {update} + {/if} +
+
+
+ {/if} +
+ (settingsShown = !settingsShown)} + > + + ( + (darkMode = !darkMode), + localStorage.setItem("darkMode", darkMode.toString()) + )}> - {/if} - ( - (darkMode = !darkMode), - localStorage.setItem("darkMode", darkMode.toString()) - )}> + + {#if notificationsShown && window.innerWidth < 768} +
+
+ + {#if update} + DietPi update avalible: {update} + {/if} +
+
+
+ {/if} + {#if settingsShown && window.innerWidth < 768} +
+
+ + +
+
+
+ {/if}
- + @@ -337,7 +421,7 @@ {/if}