Moved uploaded banner and generated styles to a persistent data directory. Fixes #9

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 15:25:57 +02:00
co-authored by Claude Opus 5.5
parent cc21056ed3
commit 21b7007d28
10 changed files with 270 additions and 49 deletions
+42 -6
View File
@@ -3,7 +3,7 @@ use std::fs::read_to_string;
#[cfg(feature = "ssr")]
use std::net::SocketAddr;
#[cfg(feature = "ssr")]
use std::path::Path;
use std::path::{Path, PathBuf};
#[cfg(feature = "ssr")]
use std::str::FromStr;
#[cfg(feature = "ssr")]
@@ -122,6 +122,21 @@ impl Logging {
}
}
/// Where files created at runtime (uploaded banner, generated CSS) are kept
#[cfg(feature = "ssr")]
#[derive(Deserialize, Default)]
pub struct Storage {
data_dir: Option<String>
}
#[cfg(feature = "ssr")]
impl Storage {
/// Directory served under `/data`. Defaults to `data` in the working directory.
pub fn data_dir(&self) -> PathBuf {
PathBuf::from(self.data_dir.as_deref().unwrap_or("data"))
}
}
#[cfg(feature = "ssr")]
#[derive(Deserialize)]
pub struct Configuration {
@@ -129,7 +144,9 @@ pub struct Configuration {
network: Network,
database: Database,
mailing: Mailing,
logging: Logging
logging: Logging,
#[serde(default)]
storage: Storage
}
#[cfg(feature = "ssr")]
@@ -149,13 +166,16 @@ impl Configuration {
pub fn logging(&self) -> &Logging {
&self.logging
}
pub fn storage(&self) -> &Storage {
&self.storage
}
}
/// The config file holds passwords and the session key, so it must never lie in the directory
/// that is served as static files. Returns true when `config_path` is inside `site_root`.
/// The config file holds passwords and the session key, so it must never lie in a directory
/// that is served as static files. Returns true when `config_path` is inside `public_dir`.
#[cfg(feature = "ssr")]
pub fn is_publicly_served(config_path: &Path, site_root: &Path) -> bool {
match (config_path.canonicalize(), site_root.canonicalize()) {
pub fn is_publicly_served(config_path: &Path, public_dir: &Path) -> bool {
match (config_path.canonicalize(), public_dir.canonicalize()) {
(Ok(config), Ok(root)) => config.starts_with(root),
_ => false
}
@@ -224,6 +244,22 @@ mod tests {
std::fs::remove_dir_all(base).unwrap();
}
#[test]
fn data_dir_defaults_to_data() {
// The sample config has the storage section commented out
assert_eq!(sample().storage().data_dir(), PathBuf::from("data"));
let storage: Storage = toml::from_str("").unwrap();
assert_eq!(storage.data_dir(), PathBuf::from("data"));
}
#[test]
fn data_dir_can_be_configured() {
let storage: Storage = toml::from_str("data_dir = '/var/lib/rezervator'").unwrap();
assert_eq!(storage.data_dir(), PathBuf::from("/var/lib/rezervator"));
}
#[test]
fn sample_session_key_is_long_enough() {
// actix_web::cookie::Key::from panics on keys shorter than 64 bytes