dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 1 | use std::path::PathBuf; |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 2 | |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 3 | use malice::{ |
aa3dce5114d0 | atagen | 2026-10-26 06:09 UTC | 4 | push::HostedPush, |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 5 | routes::router, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 6 | state::{AppState, ensure_dirs, load_or_create_master_key}, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 7 | }; |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 8 | use malice_static::{bind_listener, serve}; |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 9 | |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 10 | fn env_flag(name: &str, default: bool) -> bool { |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 11 | match std::env::var(name) { |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 12 | Ok(value) => { |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 13 | let value = value.trim().to_ascii_lowercase(); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 14 | match value.as_str() { |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 15 | "1" | "true" | "yes" | "on" => true, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 16 | "0" | "false" | "no" | "off" => false, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 17 | _ => default, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 18 | } |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 19 | } |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 20 | Err(_) => default, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 21 | } |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 22 | } |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 23 | |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 24 | fn data_dir() -> PathBuf { |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 25 | std::env::var("MALICE_DATA_DIR") |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 26 | .map(PathBuf::from) |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 27 | .unwrap_or_else(|_| PathBuf::from("local-data")) |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 28 | } |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 29 | |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 30 | fn web_dir() -> Option<String> { |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 31 | if let Ok(dir) = std::env::var("MALICE_WEB_DIR") { |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 32 | assert!( |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 33 | std::path::Path::new(&dir).join("index.html").is_file(), |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 34 | "MALICE_WEB_DIR must point to built frontend assets containing index.html" |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 35 | ); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 36 | return Some(dir); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 37 | } |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 38 | |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 39 | let local = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("web/dist"); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 40 | local |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 41 | .join("index.html") |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 42 | .is_file() |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 43 | .then(|| local.to_string_lossy().into_owned()) |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 44 | } |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 45 | |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 46 | #[tokio::main] |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 47 | async fn main() { |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 48 | tracing_subscriber::fmt() |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 49 | .with_env_filter( |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 50 | tracing_subscriber::EnvFilter::try_from_default_env() |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 51 | .unwrap_or_else(|_| "malice=info,tower_http=info".into()), |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 52 | ) |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 53 | .with_target(false) |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 54 | .compact() |
dffd63b58af4 | atagen | 2026-09-28 09:10 UTC | 55 | .init(); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 56 | |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 57 | let data_dir = data_dir(); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 58 | ensure_dirs(&data_dir); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 59 | let master_key = |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 60 | load_or_create_master_key(&data_dir).expect("loading the master key must succeed"); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 61 | let cookie_secure = env_flag("MALICE_SESSION_COOKIE_SECURE", true); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 62 | let allow_http_homeserver = env_flag("MALICE_ALLOW_HTTP_HOMESERVER", false); |
aa3dce5114d0 | atagen | 2026-10-26 06:09 UTC | 63 | let push = HostedPush::from_env(&data_dir).expect("setting up web push must succeed"); |
aa3dce5114d0 | atagen | 2026-10-26 06:09 UTC | 64 | let state = AppState::new(data_dir, master_key, cookie_secure, allow_http_homeserver) |
aa3dce5114d0 | atagen | 2026-10-26 06:09 UTC | 65 | .with_push(push); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 66 | let app = router(state.clone(), web_dir()); |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 67 | let listener = bind_listener().await; |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 68 | serve( |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 69 | listener, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 70 | app, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 71 | async move { state.shutdown_gracefully().await }, |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 72 | ) |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 73 | .await; |
973f8fbdaf80 | atagen | 2026-09-28 09:10 UTC | 74 | } |