gmarche-rs/src/server.rs

97 lines
2.0 KiB
Rust

use super::{cli, config, db, static_files, templates};
use handlebars::to_json;
use serde::{Deserialize, Serialize};
use serde_json::value::{Map, Value as Json};
use sha2::{Digest, Sha512Trunc256};
use std::{
convert::TryInto,
sync::{Arc, RwLock},
};
use warp::Filter;
type PasswordHash = [u8; 32];
pub async fn start_server(
config: config::Config,
dbs: db::Dbs,
templates: templates::Templates<'static>,
opt: cli::MainOpt,
) {
let templates = Arc::new(templates);
let ads = vec![];
let mut data = Map::<String, Json>::new();
data.insert("lang".into(), to_json("fr"));
data.insert("ads".into(), to_json(ads.clone()));
let ads = Arc::new(RwLock::new(ads));
let data = Arc::new(RwLock::new(data));
let handle_index = {
let data = data.clone();
move || {
warp::reply::html(
templates
.hb
.render("index.html", &*data.read().unwrap())
.unwrap_or_else(|e| e.to_string()),
)
}
};
let route_static = warp::path("static")
.and(warp::get())
.and(warp::fs::dir(opt.dir.0.join(static_files::STATIC_DIR)));
let route_index = warp::path::end()
.and(
warp::get()
.map(handle_index.clone())
.or(warp::post()
.and(warp::body::form::<NewAdQuery>())
.map(move |ad: NewAdQuery| {
let mut hasher = Sha512Trunc256::new();
hasher.update(ad.password);
ads.write().unwrap().push(Ad {
author: ad.author,
password: hasher.finalize()[..].try_into().unwrap(),
pubkey: (!ad.pubkey.is_empty()).then_some(ad.pubkey),
time: 0,
title: ad.title,
});
data.write().unwrap().insert("ads".into(), to_json(&*ads.read().unwrap()));
handle_index()
})
)
);
warp::serve(route_static.or(route_index))
.run(config.listen)
.await;
}
#[derive(Debug, Deserialize)]
struct WotdQuery {
wotd: String,
}
#[derive(Clone, Debug, Deserialize)]
struct NewAdQuery {
author: String,
password: String,
pubkey: String,
title: String,
}
#[derive(Clone, Debug, Serialize)]
struct Ad {
author: String,
password: PasswordHash,
pubkey: Option<String>,
time: u64,
title: String,
}