#[macro_use] extern crate rust_i18n; #[cfg(test)] #[macro_export] macro_rules! testdb { () => {{ let pool = SqlitePool::connect(":memory:").await.unwrap(); sqlx::query_file!("./migration.sql") .execute(&pool) .await .unwrap(); pool }}; } i18n!("locales", fallback = "de-AT"); use admin::station::{print::station_pdf, Station}; use auth::{AuthSession, Backend, User}; use axum::{ body::Body, extract::{FromRef, State}, response::{IntoResponse, Redirect, Response}, routing::{get, post}, Form, Router, }; use axum_login::AuthManagerLayerBuilder; use maud::{html, Markup}; use partials::page; use serde::Deserialize; use sqlx::SqlitePool; use std::{env, sync::Arc}; use tokio::net::TcpListener; use tower_sessions::{cookie::time::Duration, Expiry, Session, SessionManagerLayer}; use tower_sessions_sqlx_store_chrono::SqliteStore; pub(crate) mod admin; mod auth; pub(crate) mod models; mod partials; pub(crate) mod station; pub(crate) fn test_version() -> bool { env::var("TEST_VERSION").is_ok() } pub fn url() -> String { env::var("URL").unwrap() } #[macro_export] macro_rules! err { ($session:expr, $fmt:expr $(, $arg:expr)*) => { $session .insert( "err", &format!($fmt $(, $arg)*) ) .await .unwrap() }; } #[macro_export] macro_rules! succ { ($session:expr, $fmt:expr $(, $arg:expr)*) => { $session .insert( "succ", &format!($fmt $(, $arg)*) ) .await .unwrap() }; } #[macro_export] macro_rules! suc { ($session:expr, $message:expr) => { $session.insert("succ", &$message).await.unwrap() }; } #[macro_export] macro_rules! er { ($session:expr, $message:expr) => { $session.insert("err", &$message).await.unwrap() }; } const PICO_CSS: &str = include_str!("../assets/pico.min.css"); const MY_CSS: &str = include_str!("../assets/style.css"); const LEAFLET_CSS: &str = include_str!("../assets/leaflet.css"); const LEAFLET_JS: &str = include_str!("../assets/leaflet.js"); const MARKER_PNG: &[u8] = include_bytes!("../assets/marker-icon.png"); const LOGO_HOR: &[u8] = include_bytes!("../assets/logo-horizontal.svg"); const LOGO_VER: &[u8] = include_bytes!("../assets/logo-vertical.svg"); const LOGO_HOR_INV: &[u8] = include_bytes!("../assets/logo-horizontal-inverted.svg"); const LOGO_VER_INV: &[u8] = include_bytes!("../assets/logo-vertical-inverted.svg"); async fn serve_pico_css() -> Response
{ Response::builder() .header("Content-Type", "text/css") .body(Body::from(PICO_CSS)) .unwrap() } async fn serve_my_css() -> Response { Response::builder() .header("Content-Type", "text/css") .body(Body::from(MY_CSS)) .unwrap() } async fn serve_leaflet_css() -> Response { Response::builder() .header("Content-Type", "text/css") .body(Body::from(LEAFLET_CSS)) .unwrap() } async fn serve_leaflet_js() -> Response { Response::builder() .header("Content-Type", "application/javascript") .body(Body::from(LEAFLET_JS)) .unwrap() } async fn serve_marker_png() -> Response { Response::builder() .header("Content-Type", "image/png") .body(Body::from(MARKER_PNG)) .unwrap() } async fn logo_hor() -> Response { Response::builder() .header("Content-Type", "image/svg+xml") .body(Body::from(LOGO_HOR)) .unwrap() } async fn logo_ver() -> Response { Response::builder() .header("Content-Type", "image/svg+xml") .body(Body::from(LOGO_VER)) .unwrap() } async fn logo_hor_inv() -> Response { Response::builder() .header("Content-Type", "image/svg+xml") .body(Body::from(LOGO_HOR_INV)) .unwrap() } async fn logo_ver_inv() -> Response { Response::builder() .header("Content-Type", "image/svg+xml") .body(Body::from(LOGO_VER_INV)) .unwrap() } async fn redirect() -> impl IntoResponse { Redirect::to("/admin") } #[derive(Clone)] struct AppState { db: Arc