Application can now run as Docker container.

main
Josef Rokos 1 day ago
parent 3f0136e1c2
commit 87d1b33d7c

1
Cargo.lock generated

@ -3235,6 +3235,7 @@ dependencies = [
"lettre",
"log",
"pwhash",
"rand",
"regex",
"rust_decimal",
"serde",

@ -41,6 +41,7 @@ leptos-captcha = "0.2.0"
charts-rs = { version = "0.3.5", optional = true}
#image = { version = "0.24.8", optional = true }
base64 = "0.22.0"
rand = "0.8.5"
[features]
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]

@ -0,0 +1,51 @@
FROM rust:1.86.0-bookworm AS builder
# Install cargo-binstall, which makes it easier to install other
# cargo extensions like cargo-leptos
RUN wget https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz
RUN tar -xvf cargo-binstall-x86_64-unknown-linux-musl.tgz
RUN cp cargo-binstall /usr/local/cargo/bin
# Install required tools
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends clang
# Install cargo-leptos
RUN cargo binstall cargo-leptos -y
RUN rustup default stable
# Add the WASM target
RUN rustup target add wasm32-unknown-unknown
#RUN rustup target add wasm32-unknown-unknown --toolchain nightly
# Make an /app dir, which everything will eventually live in
RUN mkdir -p /app
WORKDIR /app
COPY . .
# Build the app
#RUN cargo leptos build --release -vv
RUN LEPTOS_OUTPUT_NAME="rezervator-$(tr -dc a-z0-9 </dev/urandom | head -c 10)" cargo leptos build -r -P
FROM debian:bookworm-slim AS runtime
WORKDIR /app
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends openssl ca-certificates \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# Copy the server binary to the /app directory
COPY --from=builder /app/target/release/rezervator /app/
# /target/site contains our JS/WASM/CSS, etc.
COPY --from=builder /app/target/site /app/target/site
# Set any required env variables and
EXPOSE 3000
# -- NB: update binary name from "leptos_start" to match your app name in Cargo.toml --
# Run the server
CMD ["/app/rezervator", "-c /app/target/site/data/config.toml"]

@ -0,0 +1 @@
ALTER TABLE appearance ADD css_name VARCHAR;

@ -6,6 +6,7 @@ use crate::components::data_form::ForValidation;
cfg_if! { if #[cfg(feature = "ssr")] {
use std::fs;
use actix_web::{post, Responder};
use actix_multipart::Multipart;
use actix_session::Session;
@ -20,6 +21,8 @@ cfg_if! { if #[cfg(feature = "ssr")] {
use actix_web::web::Data;
use crate::backend::AppData;
use regex::Regex;
use rand::Rng;
use rand::distributions::Alphanumeric;
pub async fn check_appearance(pool: &PgPool) -> Result<(), AppError> {
let count: (i64,) = query_as("SELECT COUNT(id) FROM appearance")
@ -32,6 +35,11 @@ cfg_if! { if #[cfg(feature = "ssr")] {
.await?;
}
let app = query_as::<_, Appearance>("SELECT * FROM appearance").fetch_one(pool).await?;
if let None = app.css_name {
query("UPDATE appearance SET css_name = 'banner.css'").execute(pool).await?;
}
Ok(())
}
@ -44,8 +52,8 @@ cfg_if! { if #[cfg(feature = "ssr")] {
Ok(())
}
async fn modify_style(file_name: &str) -> Result<(), AppError> {
let mut css_file = File::open("target/site/banner.css")?;
async fn modify_style(file_name: &str, pool: &PgPool) -> Result<(), AppError> {
let mut css_file = File::open("target/site/data/banner.css")?;
let mut css_str= String::new();
css_file.read_to_string(&mut css_str)?;
@ -56,8 +64,26 @@ cfg_if! { if #[cfg(feature = "ssr")] {
css_str = re.replace(&css_str, &format!("background-image: url('{}')", file_name)).to_string();
}
let mut css_file = File::create("target/site/banner.css")?;
let old_css: (String,) = query_as("SELECT css_name FROM appearance")
.fetch_one(pool)
.await?;
if old_css.0 != "banner.css" {
fs::remove_file(format!("target/site/data/{}", old_css.0))?;
}
let s: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(5)
.map(char::from)
.collect();
let css_name = format!("banner-{}.css", s);
let mut css_file = File::create(format!("target/site/data/{}", css_name))?;
css_file.write_all(css_str.as_bytes())?;
query("UPDATE appearance SET css_name = $1")
.bind(css_name)
.execute(pool)
.await?;
Ok(())
}
@ -84,14 +110,14 @@ cfg_if! { if #[cfg(feature = "ssr")] {
return Redirect::to("/admin/appearance").see_other();
}
let mut file = File::create(format!("target/site/{}", file_name)).unwrap();
let mut file = File::create(format!("target/site/data/{}", file_name)).unwrap();
let _name = field.name();
while let Some(chunk) = field.next().await {
let c = chunk.unwrap();
let _ = file.write_all(&c);
}
let _ = set_banner_name(&file_name, &app_data.db_pool).await;
let _ = modify_style(&file_name).await;
let _ = modify_style(&file_name, &app_data.db_pool).await;
}
Redirect::to("/admin/appearance").see_other()
@ -149,7 +175,7 @@ pub async fn delete_banner() -> Result<ApiResponse<()>, ServerFnError> {
.await?;
if let Some(f) = appearance.banner {
fs::remove_file(format!("target/site/{}", f))?;
fs::remove_file(format!("target/site/data/{}", f))?;
}
Ok(ApiResponse::Data(()))

@ -719,7 +719,8 @@ pub struct Appearance {
id: i32,
pub banner: Option<String>,
pub text: Option<String>,
pub title: Option<String>
pub title: Option<String>,
pub css_name: Option<String>
}
impl Appearance {

@ -1,13 +1,14 @@
use leptos::*;
use leptos_meta::*;
use crate::app::DialogHelper;
use crate::backend::appearance::get_appearance;
use crate::components::user_menu::MenuOpener;
#[component]
pub fn Header() -> impl IntoView {
let drawer = use_context::<MenuOpener>().expect("No drawer opener");
let dlg_helper = use_context::<DialogHelper>().expect("No dialog helper");
//let banner_css = create_signal(String::new());
let appearance = create_blocking_resource(||(), |_| get_appearance());
view! {
<Html
@ -39,7 +40,14 @@ pub fn Header() -> impl IntoView {
<Link rel="stylesheet" href="/vendor/css/core.css" />
<Link rel="stylesheet" href="/vendor/css/theme-default.css" />
<Link rel="stylesheet" href="/css/demo.css" />
<Link rel="stylesheet" href="/banner.css" />
<Transition fallback=move || view! {""}>
{
appearance.get().map(|a| match a {
Ok(a) => view! {<Link rel="stylesheet" href={format!("/data/{}", a.css_name.unwrap_or_default())} />},
Err(_) => view! {<Link rel="stylesheet" href="/data/banner.css" />}
})
}
</Transition>
<Link rel="stylesheet" href="/vendor/css/control.css" />
//<!-- Vendors CSS -->

@ -43,7 +43,7 @@ async fn main() -> std::io::Result<()> {
Pow::init_random().expect("Cannot init captcha");
let cfg_path = matches.opt_str("c").unwrap_or("config.toml".to_string());
let srv_conf = load_config(&cfg_path);
let srv_conf = load_config(cfg_path.trim());
env_logger::Builder::from_env(Env::default().default_filter_or(srv_conf.logging().severity())).init();
info!("Starting server");

Loading…
Cancel
Save