diff --git a/Cargo.lock b/Cargo.lock index 0bb37e5..9e642c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -253,6 +253,19 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bigdecimal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d6867f1565b3aad85681f1015055b087fcfd840d6aeee6eee7f2da317603695" +dependencies = [ + "autocfg", + "libm", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -863,11 +876,15 @@ version = "2.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4ae09a41a4b89f94ec1e053623da8340d996bc32c6517d325a9daad9b239358" dependencies = [ + "bigdecimal", "bitflags 2.11.0", "byteorder", "diesel_derives", "downcast-rs", "itoa", + "num-bigint", + "num-integer", + "num-traits", "pq-sys", "r2d2", ] @@ -2541,6 +2558,7 @@ name = "httpserver" version = "0.1.0" dependencies = [ "axum-core", + "bigdecimal", "chrono", "diesel", "dioxus", @@ -3039,6 +3057,12 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libredox" version = "0.1.15" @@ -3404,6 +3428,16 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-conv" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index a3e59c5..b0391a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,9 @@ edition = "2021" [dependencies] axum-core = { version = "0.5.6", optional = true } +bigdecimal = "0.4.10" chrono = { version = "0.4.44", features = ["serde"] } -diesel = { version = "2.3.7", features = ["postgres", "r2d2"], optional = true } +diesel = { version = "2.3.7", features = ["postgres", "r2d2", "numeric"], optional = true } dioxus = { version = "0.7.1", features = ["router", "fullstack"] } dioxus-asset-resolver = "0.7.4" dioxus-html = "0.7.3" diff --git a/assets/tailwind.css b/assets/tailwind.css index 2438a8f..8602486 100644 --- a/assets/tailwind.css +++ b/assets/tailwind.css @@ -182,15 +182,9 @@ .table { display: table; } - .h-full { - height: 100%; - } .h-screen { height: 100vh; } - .w-full { - width: 100%; - } .w-screen { width: 100vw; } diff --git a/src/components/upload/create.rs b/src/components/upload/create.rs index 105c1a6..f63b375 100644 --- a/src/components/upload/create.rs +++ b/src/components/upload/create.rs @@ -153,7 +153,7 @@ pub fn UploadFile() -> Element { let mut selected : Signal>)>> = use_signal(|| vec![]); rsx! { - div { class : "p-2 h-full w-full", + div { class : "p-2", p { class: "text-4xl font-bold p-1", "Upload a file" } form { diff --git a/src/components/upload/get.rs b/src/components/upload/get.rs index b7163ca..3e12576 100644 --- a/src/components/upload/get.rs +++ b/src/components/upload/get.rs @@ -51,7 +51,7 @@ async fn download_file(id: String) -> Result { let db_file = result.unwrap(); if db_file.len() == 0 { - return HttpError::internal_server_error("The requested file does not exist"); + return HttpError::not_found("The requested file does not exist"); } let file_path = s_config.upload_folder + &id; diff --git a/src/components/upload/mod.rs b/src/components/upload/mod.rs index 41b10a1..6138d93 100644 --- a/src/components/upload/mod.rs +++ b/src/components/upload/mod.rs @@ -6,3 +6,6 @@ pub use info::FileInfo; mod get; +mod stats; +pub use stats::UploadStats; + diff --git a/src/components/upload/stats.rs b/src/components/upload/stats.rs new file mode 100644 index 0000000..61f4b94 --- /dev/null +++ b/src/components/upload/stats.rs @@ -0,0 +1,85 @@ +use dioxus::prelude::*; + +#[cfg(feature = "server")] +use httpserver::models::GetFile; +#[cfg(feature = "server")] +use diesel::prelude::*; +#[cfg(feature = "server")] +use httpserver::DB; +#[cfg(feature = "server")] +use diesel::dsl; + +#[cfg(feature = "server")] +use httpserver::schema; + +#[cfg(feature = "server")] +use crate::config::ServerConfig; + +use serde::{Deserialize, Serialize}; + +use bigdecimal::{BigDecimal, ToPrimitive}; + +use httpserver::utils::byte_to_human_size; +#[derive(Deserialize, Serialize)] +struct UploadServerStats { + total_limit_soft: u64, + total_limit_hard : u64, + used_space: u64, + nb_active_files: u64, + nb_total_files: u64 +} + +#[get("/upload/stats")] +async fn get_upload_stats() -> Result { + use httpserver::schema::file; + + let s_config = ServerConfig::load(); + + let active_files = match DB.with(|pool| file::table.select((dsl::sum(file::file_size), dsl::count(file::id))) + .filter(file::deleted.eq(false)) + .first::<(Option, i64)>(&mut pool.get().unwrap())) { + + Ok((Some(val1),val2)) => (val1, val2), + _ => return HttpError::internal_server_error("wth ?") + }; + + let total_files = match DB.with(|pool| file::table.select((dsl::count(file::id))) + .first::<(i64)>(&mut pool.get().unwrap())) { + Ok(val) => val, + _ => return HttpError::internal_server_error("wth ?") + }; + + + Ok(UploadServerStats { + total_limit_soft: s_config.upload_storage_limit_soft, + total_limit_hard: s_config.upload_storage_limit_hard, + + used_space: active_files.0.to_u64().unwrap(), + nb_active_files: active_files.1.to_u64().unwrap(), + nb_total_files: total_files.to_u64().unwrap() + }) +} + +fn render_stats(stats : &UploadServerStats) -> Element { + let soft_percentage = stats.used_space as f32 / stats.total_limit_soft as f32; + let hard_percentage = stats.used_space as f32 / stats.total_limit_hard as f32; + + rsx! { + h1 {class: "text-4xl font-bold", "Server info"} + p { "percentage of the soft limit used : {soft_percentage}%"} + p { "percentage of the hard limit used : {hard_percentage}%"} + p { "number of currenlty active files : {stats.nb_active_files}"} + p { "number of files uploaded : {stats.nb_total_files}" } + } +} + +#[component] +pub fn UploadStats() -> Element { + let r_stats = use_resource(move || get_upload_stats()); + + match &*r_stats.read_unchecked() { + Some(Ok(stats)) => { render_stats(stats) }, + Some(Err(err)) => { rsx! { p {"server retrned an error : {err}"} } }, + _ => { rsx! { p {"Loading ..."} } } + } +} diff --git a/src/config.rs b/src/config.rs index 4abf866..670514f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,6 +2,9 @@ pub struct ServerConfig { pub upload_folder: String, pub db_url: String, + + pub upload_storage_limit_soft: u64, + pub upload_storage_limit_hard: u64, } #[cfg(feature = "server")] @@ -10,6 +13,10 @@ impl ServerConfig { Self { upload_folder: "./test/".to_string(), db_url: std::env::var("DATABASE_URL").expect("missing DATABASE_URL"), + + upload_storage_limit_soft: 1024 * 1024 * 1024 * 200, + upload_storage_limit_hard: 1024 * 1024 * 1024 * 300, + } } } diff --git a/src/main.rs b/src/main.rs index 18c329a..35ba1f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use dioxus::prelude::*; -use crate::components::upload::{FileInfo, UploadFile}; +use crate::components::upload::{FileInfo, UploadFile, UploadStats}; use tracing::Level; pub mod config; @@ -34,7 +34,9 @@ fn App() -> Element { div { class: "h-screen w-screen bg-zinc-900 text-white", ToastProvider { + UploadFile { } FileInfo {file: "ULI0GZWJQH9BGEZR1VZ1"} + UploadStats { } // Router:: {} } }