From c967103a16a38710c3d41959246aa15e003c60ed Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Thu, 20 Mar 2025 21:17:47 +0100 Subject: [PATCH] Prepare release generation --- Makefile | 18 +++++ moneymgr_backend/.gitignore | 1 + moneymgr_backend/Cargo.lock | 80 +++++++++++++++++++ moneymgr_backend/Cargo.toml | 4 +- .../docker/moneymgr_backend/Dockerfile | 10 +++ moneymgr_backend/src/controllers/mod.rs | 1 + .../src/controllers/static_controller.rs | 45 +++++++++++ moneymgr_backend/src/main.rs | 6 ++ moneymgr_web/src/routes/TokensRoute.tsx | 10 +-- moneymgr_web/src/widgets/MoneyNavList.tsx | 2 - 10 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 Makefile create mode 100644 moneymgr_backend/docker/moneymgr_backend/Dockerfile create mode 100644 moneymgr_backend/src/controllers/static_controller.rs diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cdee702 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +DOCKER_TEMP_DIR=temp + +all: frontend backend + +frontend: + cd moneymgr_web && npm run build && cd .. + rm -rf moneymgr_backend/static + mv moneymgr_web/dist moneymgr_backend/static + +backend: frontend + cd moneymgr_backend && cargo clippy -- -D warnings && cargo build --release + +backend_docker: backend + rm -rf $(DOCKER_TEMP_DIR) + mkdir $(DOCKER_TEMP_DIR) + cp moneymgr_backend/target/release/moneymgr_backend $(DOCKER_TEMP_DIR) + docker build -t pierre42100/moneymgr_backend -f moneymgr_backend/docker/moneymgr_backend/Dockerfile "$(DOCKER_TEMP_DIR)" + rm -rf $(DOCKER_TEMP_DIR) diff --git a/moneymgr_backend/.gitignore b/moneymgr_backend/.gitignore index f0767f5..faf9d85 100644 --- a/moneymgr_backend/.gitignore +++ b/moneymgr_backend/.gitignore @@ -1,3 +1,4 @@ target .idea storage +static \ No newline at end of file diff --git a/moneymgr_backend/Cargo.lock b/moneymgr_backend/Cargo.lock index ba6f0ab..16f148c 100644 --- a/moneymgr_backend/Cargo.lock +++ b/moneymgr_backend/Cargo.lock @@ -2043,6 +2043,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minidom" version = "0.16.0" @@ -2094,7 +2104,9 @@ dependencies = [ "lazy_static", "light-openid", "log", + "mime_guess", "rand 0.9.0", + "rust-embed", "rust-s3", "serde", "serde_json", @@ -2712,6 +2724,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rust-embed" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b3aba5104622db5c9fc61098de54708feb732e7763d7faa2fa625899f00bf6f" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f198c73be048d2c5aa8e12f7960ad08443e56fd39cc26336719fdb4ea0ebaae" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a2fcdc9f40c8dc2922842ca9add611ad19f332227fc651d015881ad1552bd9a" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rust-ini" version = "0.21.1" @@ -2855,6 +2901,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.27" @@ -3447,6 +3502,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -3522,6 +3583,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -3649,6 +3720,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "windows-link" version = "0.1.0" diff --git a/moneymgr_backend/Cargo.toml b/moneymgr_backend/Cargo.toml index d5f5abc..fbd1a99 100644 --- a/moneymgr_backend/Cargo.toml +++ b/moneymgr_backend/Cargo.toml @@ -26,4 +26,6 @@ light-openid = "1.0.4" rand = "0.9.0" ipnet = { version = "2.11.0", features = ["serde"] } lazy-regex = "3.4.1" -jwt-simple = { version = "0.12.11", default-features = false, features = ["pure-rust"] } \ No newline at end of file +jwt-simple = { version = "0.12.11", default-features = false, features = ["pure-rust"] } +mime_guess = "2.0.5" +rust-embed = { version = "8.6.0" } diff --git a/moneymgr_backend/docker/moneymgr_backend/Dockerfile b/moneymgr_backend/docker/moneymgr_backend/Dockerfile new file mode 100644 index 0000000..b47ec66 --- /dev/null +++ b/moneymgr_backend/docker/moneymgr_backend/Dockerfile @@ -0,0 +1,10 @@ +FROM debian:bookworm-slim + +RUN apt-get update \ + && apt-get install -y libcurl4 libpq5 \ + && rm -rf /var/lib/apt/lists/* + + +COPY moneymgr_backend /usr/local/bin/moneymgr_backend + +ENTRYPOINT ["/usr/local/bin/moneymgr_backend"] \ No newline at end of file diff --git a/moneymgr_backend/src/controllers/mod.rs b/moneymgr_backend/src/controllers/mod.rs index d358e30..9b6f8a7 100644 --- a/moneymgr_backend/src/controllers/mod.rs +++ b/moneymgr_backend/src/controllers/mod.rs @@ -4,6 +4,7 @@ use std::error::Error; pub mod auth_controller; pub mod server_controller; +pub mod static_controller; pub mod tokens_controller; #[derive(thiserror::Error, Debug)] diff --git a/moneymgr_backend/src/controllers/static_controller.rs b/moneymgr_backend/src/controllers/static_controller.rs new file mode 100644 index 0000000..3d5b313 --- /dev/null +++ b/moneymgr_backend/src/controllers/static_controller.rs @@ -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 Money manager!") + } + + 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::{HttpResponse, Responder, web}; + 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) -> impl Responder { + handle_embedded_file(path.as_ref(), !path.as_ref().starts_with("static/")) + } +} diff --git a/moneymgr_backend/src/main.rs b/moneymgr_backend/src/main.rs index ac7a5a4..8cb0e37 100644 --- a/moneymgr_backend/src/main.rs +++ b/moneymgr_backend/src/main.rs @@ -100,6 +100,12 @@ async fn main() -> std::io::Result<()> { "/api/tokens/{id}", web::delete().to(tokens_controller::delete), ) + // 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.as_str())? .run() diff --git a/moneymgr_web/src/routes/TokensRoute.tsx b/moneymgr_web/src/routes/TokensRoute.tsx index aa9f9de..01bdb9b 100644 --- a/moneymgr_web/src/routes/TokensRoute.tsx +++ b/moneymgr_web/src/routes/TokensRoute.tsx @@ -1,12 +1,16 @@ +import AddIcon from "@mui/icons-material/Add"; import DeleteIcon from "@mui/icons-material/DeleteOutlined"; -import { Alert, AlertTitle, Button, IconButton, Tooltip } from "@mui/material"; +import RefreshIcon from "@mui/icons-material/Refresh"; +import { Alert, AlertTitle, IconButton, Tooltip } from "@mui/material"; import { DataGrid, GridActionsCellItem, GridColDef, GridRowId, } from "@mui/x-data-grid"; +import { QRCodeCanvas } from "qrcode.react"; import React from "react"; +import { APIClient } from "../api/ApiClient"; import { Token, TokenWithSecret, TokensApi } from "../api/TokensApi"; import { CreateTokenDialog } from "../dialogs/CreateTokenDialog"; import { useAlert } from "../hooks/context_providers/AlertDialogProvider"; @@ -16,10 +20,6 @@ import { AsyncWidget } from "../widgets/AsyncWidget"; import { CopyTextChip } from "../widgets/CopyTextChip"; import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer"; import { TimeWidget } from "../widgets/TimeWidget"; -import { QRCodeCanvas } from "qrcode.react"; -import { APIClient } from "../api/ApiClient"; -import AddIcon from "@mui/icons-material/Add"; -import RefreshIcon from "@mui/icons-material/Refresh"; export function TokensRoute(): React.ReactElement { const count = React.useRef(0); diff --git a/moneymgr_web/src/widgets/MoneyNavList.tsx b/moneymgr_web/src/widgets/MoneyNavList.tsx index ca614d6..20c08be 100644 --- a/moneymgr_web/src/widgets/MoneyNavList.tsx +++ b/moneymgr_web/src/widgets/MoneyNavList.tsx @@ -7,11 +7,9 @@ import { ListItemText, } from "@mui/material"; import { useLocation } from "react-router-dom"; -import { useAuthInfo } from "./BaseAuthenticatedPage"; import { RouterLink } from "./RouterLink"; export function MoneyNavList(): React.ReactElement { - const user = useAuthInfo().info; return (