diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b830105f4..c3a64fcf9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,7 @@ on: push: branches: - main + tags: [ 'v*', '*' ] jobs: build-rustfs: @@ -60,9 +61,12 @@ jobs: # Create package mkdir -p ${ARTIFACT_NAME} cp "$bin_path" ${ARTIFACT_NAME}/rustfs - # cp -r static ${ARTIFACT_NAME}/ zip -r ${ARTIFACT_NAME}.zip ${ARTIFACT_NAME} ls -la + + # Copy files to the specified directory + mkdir -p cli/rustfs-gui/embedded-rustfs + cp -r ${ARTIFACT_NAME}/rustfs cli/rustfs-gui/embedded-rustfs/ - uses: actions/upload-artifact@v4 with: @@ -70,9 +74,40 @@ jobs: path: ${{ steps.package.outputs.artifact_name }}.zip retention-days: 7 - merge: + build-rustfs-gui: runs-on: ubuntu-latest needs: build-rustfs + if: startsWith(github.ref, 'refs/tags/') + steps: + - uses: actions/checkout@v4 + - name: Install dioxus-cli + run: cargo install dioxus-cli + + - name: Build and Bundle rustfs-gui + run: | + relaese_path = "target/${{ matrix.variant.target }}" + mkdir -p ${relaese_path} + cd cli/rustfs-gui + if [[ "${{ matrix.variant.target }}" == *"apple-darwin"* ]]; then + dx bundle --platform macos --package-types "macos" --package-types "dmg" --package-types "ios" --release --profile release --out-dir ../../${relaese_path} + elif [[ "${{ matrix.variant.target }}" == *"windows-msvc"* ]]; then + dx bundle --platform windows --package-types "msi" --release --profile release --out-dir ../../target/${relaese_path} + fi + cd ../.. + GUI_ARTIFACT_NAME="rustfs-gui-${{ matrix.variant.profile }}-${{ matrix.variant.target }}" + zip -r ${GUI_ARTIFACT_NAME}.zip target/${{ matrix.variant.target }}/rustfs-gui + echo "gui_artifact_name=${GUI_ARTIFACT_NAME}" >> $GITHUB_OUTPUT + ls -la + + - uses: actions/upload-artifact@v4 + with: + name: ${{ steps.package.outputs.gui_artifact_name }} + path: ${{ steps.package.outputs.gui_artifact_name }}.zip + retention-days: 7 + + merge: + runs-on: ubuntu-latest + needs: [ build-rustfs, build-rustfs-gui ] steps: - uses: actions/upload-artifact/merge@v4 with: diff --git a/.gitignore b/.gitignore index 81d415f64..faba350da 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /logs .devcontainer rustfs/static/* +vendor \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index c8cae648d..89db6bc20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,15 +158,6 @@ version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" -[[package]] -name = "arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" -dependencies = [ - "derive_arbitrary", -] - [[package]] name = "arc-swap" version = "1.7.1" @@ -629,25 +620,6 @@ dependencies = [ "bytes", ] -[[package]] -name = "bzip2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" -dependencies = [ - "bzip2-sys", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "cairo-rs" version = "0.18.5" @@ -679,8 +651,6 @@ version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ - "jobserver", - "libc", "shlex", ] @@ -1014,12 +984,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - [[package]] name = "convert_case" version = "0.4.0" @@ -1118,21 +1082,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32c" version = "0.6.8" @@ -1325,12 +1274,6 @@ dependencies = [ "rand 0.8.5", ] -[[package]] -name = "deflate64" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" - [[package]] name = "deranged" version = "0.3.11" @@ -1341,17 +1284,6 @@ dependencies = [ "serde", ] -[[package]] -name = "derive_arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - [[package]] name = "derive_more" version = "0.99.19" @@ -1445,7 +1377,7 @@ dependencies = [ "futures-util", "generational-box", "longest-increasing-subsequence", - "rustc-hash 1.1.0", + "rustc-hash", "rustversion", "serde", "slab", @@ -1511,7 +1443,7 @@ dependencies = [ "objc_id", "once_cell", "rfd 0.14.1", - "rustc-hash 1.1.0", + "rustc-hash", "serde", "serde_json", "signal-hook", @@ -1672,7 +1604,7 @@ dependencies = [ "dioxus-html", "js-sys", "lazy-js-bundle", - "rustc-hash 1.1.0", + "rustc-hash", "serde", "sledgehammer_bindgen", "sledgehammer_utils", @@ -1778,7 +1710,7 @@ dependencies = [ "generational-box", "once_cell", "parking_lot 0.12.3", - "rustc-hash 1.1.0", + "rustc-hash", "tracing", "warnings", ] @@ -1805,7 +1737,7 @@ dependencies = [ "generational-box", "js-sys", "lazy-js-bundle", - "rustc-hash 1.1.0", + "rustc-hash", "serde", "serde-wasm-bindgen", "serde_json", @@ -2039,15 +1971,6 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - [[package]] name = "endi" version = "1.1.0" @@ -2958,24 +2881,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.27.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - [[package]] name = "hyper-timeout" version = "0.5.2" @@ -3345,15 +3250,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.77" @@ -3577,12 +3473,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "lockfree-object-pool" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" - [[package]] name = "log" version = "0.4.26" @@ -3604,16 +3494,6 @@ dependencies = [ "hashbrown 0.12.3", ] -[[package]] -name = "lzma-rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" -dependencies = [ - "byteorder", - "crc", -] - [[package]] name = "mac" version = "0.1.1" @@ -4903,58 +4783,6 @@ dependencies = [ "serde", ] -[[package]] -name = "quinn" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.1.1", - "rustls", - "socket2", - "thiserror 2.0.11", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" -dependencies = [ - "bytes", - "getrandom 0.2.15", - "rand 0.8.5", - "ring", - "rustc-hash 2.1.1", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.11", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "quote" version = "1.0.38" @@ -5210,15 +5038,12 @@ checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2", "http", "http-body", "http-body-util", "hyper", - "hyper-rustls", "hyper-util", "ipnet", "js-sys", @@ -5228,17 +5053,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", - "rustls-pemfile", - "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", - "tokio-rustls", "tokio-util", "tower 0.5.2", "tower-service", @@ -5247,7 +5066,6 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", "windows-registry", ] @@ -5381,12 +5199,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustc_version" version = "0.4.1" @@ -5468,15 +5280,17 @@ dependencies = [ "dioxus", "dirs 6.0.0", "futures-util", + "hex", "keyring", - "reqwest", + "lazy_static", "rfd 0.15.2", + "rust-embed", "serde", "serde_json", + "sha2 0.10.8", "tokio", "tracing-appender", "tracing-subscriber", - "zip", ] [[package]] @@ -5521,9 +5335,6 @@ name = "rustls-pki-types" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" -dependencies = [ - "web-time", -] [[package]] name = "rustls-webpki" @@ -6026,7 +5837,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "debdd4b83524961983cea3c55383b3910fd2f24fd13a188f5b091d2d504a61ae" dependencies = [ - "rustc-hash 1.1.0", + "rustc-hash", ] [[package]] @@ -6210,27 +6021,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.9.4", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "system-deps" version = "6.2.2" @@ -6458,21 +6248,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinyvec" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.43.0" @@ -7240,16 +7015,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webbrowser" version = "0.8.15" @@ -7311,15 +7076,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "webpki-roots" -version = "0.26.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "webview2-com" version = "0.33.0" @@ -8030,20 +7786,6 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] [[package]] name = "zerovec" @@ -8067,77 +7809,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "zip" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b280484c454e74e5fff658bbf7df8fdbe7a07c6b2de4a53def232c15ef138f3a" -dependencies = [ - "aes", - "arbitrary", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "deflate64", - "displaydoc", - "flate2", - "hmac 0.12.1", - "indexmap 2.7.1", - "lzma-rs", - "memchr", - "pbkdf2", - "rand 0.8.5", - "sha1 0.10.6", - "thiserror 2.0.11", - "time", - "zeroize", - "zopfli", - "zstd", -] - -[[package]] -name = "zopfli" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" -dependencies = [ - "bumpalo", - "crc32fast", - "lockfree-object-pool", - "log", - "once_cell", - "simd-adler32", -] - -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.14+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "zvariant" version = "4.2.0" diff --git a/Cargo.toml b/Cargo.toml index 539489414..c034c32dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,18 @@ [workspace] members = [ - "madmin", # Management dashboard and admin API interface - "rustfs", # Core file system implementation - "ecstore", # Erasure coding storage implementation - "e2e_test", # End-to-end test suite - "common/common", # Shared utilities and data structures - "common/lock", # Distributed locking implementation - "common/protos", # Protocol buffer definitions - "api/admin", # Admin HTTP API endpoints - "reader", # Object reading service - "common/workers", # Worker thread pools and task scheduling - "iam", # Identity and Access Management - "crypto", # Cryptography and security features - "cli/rustfs-gui", # Graphical user interface client + "madmin", # Management dashboard and admin API interface + "rustfs", # Core file system implementation + "ecstore", # Erasure coding storage implementation + "e2e_test", # End-to-end test suite + "common/common", # Shared utilities and data structures + "common/lock", # Distributed locking implementation + "common/protos", # Protocol buffer definitions + "api/admin", # Admin HTTP API endpoints + "reader", # Object reading service + "common/workers", # Worker thread pools and task scheduling + "iam", # Identity and Access Management + "crypto", # Cryptography and security features + "cli/rustfs-gui", # Graphical user interface client ] resolver = "2" @@ -45,6 +45,7 @@ futures = "0.3.31" futures-util = "0.3.31" common = { path = "./common/common" } reader = { path = "./reader" } +hex = "0.4.3" hyper = "1.6.0" hyper-util = { version = "0.1.10", features = [ "tokio", @@ -57,6 +58,7 @@ humantime = "2.1.0" keyring = { version = "3.6.1", features = ["apple-native", "windows-native", "sync-secret-service"] } lock = { path = "./common/lock" } lazy_static = "1.5.0" +local-ip-address = "0.6.3" mime = "0.3.17" netif = "0.1.6" pin-project-lite = "0.2" @@ -71,6 +73,7 @@ reqwest = { version = "0.12.12", default-features = false, features = ["rustls-t rfd = { version = "0.15.2", default-features = false, features = ["xdg-portal", "tokio"] } rmp = "0.8.14" rmp-serde = "1.3.0" +rust-embed = "8.6.0" s3s = { git = "https://github.com/Nugine/s3s.git", rev = "ab139f72fe768fb9d8cecfe36269451da1ca9779", default-features = true, features = [ "tower", ] } @@ -78,6 +81,7 @@ s3s-policy = { git = "https://github.com/Nugine/s3s.git", rev = "ab139f72fe768fb shadow-rs = { version = "0.38.0", default-features = false } serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.138" +sha2 = "0.10.8" tempfile = "3.16.0" thiserror = "2.0.11" time = { version = "0.3.37", features = [ diff --git a/cli/rustfs-gui/Cargo.toml b/cli/rustfs-gui/Cargo.toml index 4caa5a972..c9af2fc37 100644 --- a/cli/rustfs-gui/Cargo.toml +++ b/cli/rustfs-gui/Cargo.toml @@ -11,15 +11,17 @@ chrono = { workspace = true } dioxus = { workspace = true, features = ["router"] } dirs = { workspace = true } futures-util = { workspace = true } +hex = { workspace = true } keyring = { workspace = true } -reqwest = { workspace = true } +lazy_static = { workspace = true } rfd = { workspace = true } +rust-embed = { workspace = true, features = ["interpolate-folder-path"] } serde = { workspace = true } serde_json = { workspace = true } +sha2 = { workspace = true } tokio = { workspace = true, features = ["io-util", "net", "process", "sync"] } tracing-subscriber = { workspace = true, features = ["fmt", "env-filter", "tracing-log", "time", "local-time", "json"] } tracing-appender = { workspace = true } -zip = { workspace = true } [features] default = ["desktop"] diff --git a/cli/rustfs-gui/embedded-rustfs/README.md b/cli/rustfs-gui/embedded-rustfs/README.md new file mode 100644 index 000000000..190bfa361 --- /dev/null +++ b/cli/rustfs-gui/embedded-rustfs/README.md @@ -0,0 +1 @@ +rustfs bin path, do not delete \ No newline at end of file diff --git a/cli/rustfs-gui/src/components/home.rs b/cli/rustfs-gui/src/components/home.rs index 141f48d6b..94b306e88 100644 --- a/cli/rustfs-gui/src/components/home.rs +++ b/cli/rustfs-gui/src/components/home.rs @@ -1,5 +1,5 @@ use crate::components::navbar::LoadingSpinner; -use crate::router::Route; +use crate::route::Route; use crate::utils::{RustFSConfig, ServiceManager}; use chrono::Datelike; use dioxus::logger::tracing::debug; diff --git a/cli/rustfs-gui/src/components/navbar.rs b/cli/rustfs-gui/src/components/navbar.rs index 6a23541b4..98726b7ab 100644 --- a/cli/rustfs-gui/src/components/navbar.rs +++ b/cli/rustfs-gui/src/components/navbar.rs @@ -1,4 +1,4 @@ -use crate::router::Route; +use crate::route::Route; use dioxus::logger::tracing::debug; use dioxus::prelude::*; diff --git a/cli/rustfs-gui/src/main.rs b/cli/rustfs-gui/src/main.rs index eba783370..6a8e1644f 100644 --- a/cli/rustfs-gui/src/main.rs +++ b/cli/rustfs-gui/src/main.rs @@ -1,5 +1,5 @@ mod components; -mod router; +mod route; mod utils; mod views; diff --git a/cli/rustfs-gui/src/router/mod.rs b/cli/rustfs-gui/src/route/mod.rs similarity index 100% rename from cli/rustfs-gui/src/router/mod.rs rename to cli/rustfs-gui/src/route/mod.rs diff --git a/cli/rustfs-gui/src/router/router.rs b/cli/rustfs-gui/src/route/router.rs similarity index 100% rename from cli/rustfs-gui/src/router/router.rs rename to cli/rustfs-gui/src/route/router.rs diff --git a/cli/rustfs-gui/src/utils/helper.rs b/cli/rustfs-gui/src/utils/helper.rs index b597ef81e..57c7f4ac4 100644 --- a/cli/rustfs-gui/src/utils/helper.rs +++ b/cli/rustfs-gui/src/utils/helper.rs @@ -1,14 +1,31 @@ use crate::utils::RustFSConfig; use dioxus::logger::tracing::{debug, error, info}; -use futures_util::TryStreamExt; +use lazy_static::lazy_static; +use rust_embed::RustEmbed; +use sha2::{Digest, Sha256}; use std::error::Error; -use std::fs::File; use std::path::{Path, PathBuf}; use std::process::Command as StdCommand; use std::time::Duration; +use tokio::fs; +use tokio::fs::File; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; -use tokio::sync::mpsc; +use tokio::sync::{mpsc, Mutex}; + +#[derive(RustEmbed)] +#[folder = "$CARGO_MANIFEST_DIR/embedded-rustfs/"] +struct Asset; + +// Use `lazy_static` to cache the checksum of embedded resources +lazy_static! { + static ref RUSTFS_HASH: Mutex = { + let rustfs_file = if cfg!(windows) { "rustfs.exe" } else { "rustfs" }; + let rustfs_data = Asset::get(rustfs_file).expect("RustFs binary not embedded"); + let hash = hex::encode(Sha256::digest(&rustfs_data.data)); + Mutex::new(hash) + }; +} /// Service command /// This enum represents the commands that can be sent to the service manager @@ -159,107 +176,38 @@ impl ServiceManager { } } - let executable_path = if cfg!(windows) { - bin_dir.join("rustfs.exe") - } else { - bin_dir.join("rustfs") - }; + let rustfs_file = if cfg!(windows) { "rustfs.exe" } else { "rustfs" }; + let executable_path = bin_dir.join(rustfs_file); + let hash_path = bin_dir.join("embedded_rustfs.sha256"); - // If the executable file doesn't exist, download and unzip it - if !executable_path.exists() { - // download the file - let tmp_zip = rustfs_dir.join("rustfs.zip"); - let file_download_url = if cfg!(windows) { - "https://api.xmb.xyz/download/rustfs-win.zip" - } else { - "https://api.xmb.xyz/download/rustfs.zip" - }; - - let download_task = Self::download_file(file_download_url, &tmp_zip); - let unzip_task = async { - download_task.await?; - Self::unzip_file(&tmp_zip, &bin_dir)?; - tokio::fs::remove_file(&tmp_zip).await?; - Ok::<(), Box>(()) - }; - unzip_task.await?; - - // delete the temporary zip file - tokio::fs::remove_file(&tmp_zip).await?; - - // set execution permissions on unix systems - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - let mut perms = std::fs::metadata(&executable_path)?.permissions(); - perms.set_mode(0o755); - std::fs::set_permissions(&executable_path, perms)?; + if executable_path.exists() && hash_path.exists() { + let cached_hash = fs::read_to_string(&hash_path).await?; + let expected_hash = RUSTFS_HASH.lock().await; + if cached_hash == *expected_hash { + println!("Use cached rustfs: {:?}", executable_path); + return Ok(executable_path); } - Self::show_info("服务程序已成功下载并准备就绪"); + } + + // Extract and write files + let rustfs_data = Asset::get(rustfs_file).expect("RustFS binary not embedded"); + let mut file = File::create(&executable_path).await?; + file.write_all(&rustfs_data.data).await?; + let expected_hash = hex::encode(Sha256::digest(&rustfs_data.data)); + fs::write(&hash_path, expected_hash).await?; + + // set execution permissions on unix systems + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let mut perms = std::fs::metadata(&executable_path)?.permissions(); + perms.set_mode(0o755); + std::fs::set_permissions(&executable_path, perms)?; } Ok(executable_path) } - /// Download the file - /// This function is a modified version of the example from the `reqwest` crate documentation - /// - /// # Example - /// ``` - /// let url = "https://api.xmb.xyz/download/rustfs.zip"; - /// let path = Path::new("rustfs.zip"); - /// download_file(url, path).await; - /// ``` - async fn download_file(url: &str, path: &Path) -> Result<(), Box> { - let client = reqwest::Client::new(); - let res = client.get(url).send().await?; - - if !res.status().is_success() { - return Err(format!("下载失败:{}", res.status()).into()); - } - - let mut file = tokio::fs::File::create(path).await?; - let mut stream = res.bytes_stream(); - while let Ok(Some(chunk)) = stream.try_next().await { - file.write_all(&chunk).await?; - } - - Ok(()) - } - - /// unzip the file - /// This function is a modified version of the example from the `zip` crate documentation - /// - /// # Example - /// ``` - /// let zip_path = Path::new("rustfs.zip"); - /// let extract_path = Path::new("rustfs"); - /// unzip_file(zip_path, extract_path); - /// ``` - fn unzip_file(zip_path: &Path, extract_path: &Path) -> Result<(), Box> { - let file = File::open(zip_path)?; - let mut archive = zip::ZipArchive::new(file)?; - - for i in 0..archive.len() { - let mut file = archive.by_index(i)?; - let out_path = extract_path.join(file.name()); - - if file.name().ends_with('/') { - std::fs::create_dir_all(&out_path)?; - } else { - if let Some(p) = out_path.parent() { - if !p.exists() { - std::fs::create_dir_all(p)?; - } - } - let mut outfile = File::create(&out_path)?; - std::io::copy(&mut file, &mut outfile)?; - } - } - - Ok(()) - } - /// Helper function: Extracts the port from the address string /// /// # Example diff --git a/cli/rustfs-gui/src/views/app.rs b/cli/rustfs-gui/src/views/app.rs index 1523eb0b4..708a8974d 100644 --- a/cli/rustfs-gui/src/views/app.rs +++ b/cli/rustfs-gui/src/views/app.rs @@ -1,4 +1,4 @@ -use crate::router::Route; +use crate::route::Route; use dioxus::logger::tracing::info; use dioxus::prelude::*; diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index eb5182abc..e27c59575 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -73,9 +73,9 @@ iam = { path = "../iam" } jsonwebtoken = "9.3.0" tower-http = { version = "0.6.2", features = ["cors"] } mime_guess = "2.0.5" -rust-embed = { version = "8.6.0", features = ["interpolate-folder-path"] } -local-ip-address = "0.6.3" -chrono = "0.4" +rust-embed = { workspace = true, features = ["interpolate-folder-path"] } +local-ip-address = { workspace = true } +chrono = { workspace = true } [build-dependencies] prost-build.workspace = true @@ -87,7 +87,7 @@ futures-util.workspace = true # uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] } ecstore = { path = "../ecstore" } s3s.workspace = true -clap = { version = "4.5.31", features = ["derive","env"] } +clap = { version = "4.5.31", features = ["derive", "env"] } tracing-subscriber = { version = "0.3.19", features = ["env-filter", "time"] } hyper-util = { version = "0.1.10", features = [ "tokio",