#![allow(clippy::too_many_arguments)] pub mod api; pub mod page; use crate::{config::*, db::*, locales::*}; use argon2::{Argon2, PasswordHash, PasswordVerifier}; pub async fn run_server( config: &'static Config, dbs: Dbs, templates: &'static page::templates::Templates, locales: &'static Locales, ) { tide::log::start(); let (notify_send, notify_recv) = crossbeam_channel::bounded(10); tokio::spawn(crate::notify::run_notifier(config, notify_recv)); let mut app = tide::new(); // CORS sucks app.at(&format!("{}*", config.root_url)) .options(|_req: tide::Request<()>| async { Ok(tide::Response::builder(200) .header("Access-Control-Allow-Origin", &config.cors_allow_origin) .header("Access-Control-Allow-Headers", "*") .build()) }); api::init_routes(&mut app, config, dbs.clone(), notify_send.clone()).await; page::init_routes(&mut app, config, dbs, templates, locales, notify_send).await; app.listen(config.listen).await.unwrap(); } fn check_admin_password(config: &Config, password: &str) -> Option { let argon2 = Argon2::default(); config .admin_passwords .iter() .filter_map(|admin_password| PasswordHash::new(admin_password).ok()) .find(|admin_password| { argon2 .verify_password(password.as_bytes(), admin_password) .is_ok() }) .map(|password_hash| password_hash.to_string()) } fn check_admin_password_hash(config: &Config, password_hash: &str) -> bool { config.admin_passwords.iter().any(|h| h == password_hash) }