feat: locales

This commit is contained in:
Pascal Engélibert 2022-12-04 10:12:34 +01:00
commit 7ee817de46
Signed by: tuxmain
GPG key ID: 3504BC6D362F7DCA
11 changed files with 618 additions and 200 deletions

View file

@ -1,11 +1,20 @@
use crate::{config::*, db::*, helpers, queries::*, templates::*};
#![allow(clippy::too_many_arguments)]
use crate::{config::*, db::*, helpers, locales::*, queries::*, templates::*};
use argon2::{Argon2, PasswordHash, PasswordVerifier};
use crossbeam_channel::Sender;
use fluent_bundle::FluentArgs;
use log::{error, warn};
use tera::Context;
use unic_langid::LanguageIdentifier;
pub async fn run_server(config: &'static Config, dbs: Dbs, templates: &'static Templates) {
pub async fn run_server(
config: &'static Config,
dbs: Dbs,
templates: &'static Templates,
locales: &'static Locales,
) {
tide::log::start();
let (notify_send, notify_recv) = crossbeam_channel::bounded(10);
@ -15,17 +24,36 @@ pub async fn run_server(config: &'static Config, dbs: Dbs, templates: &'static T
app.at(&format!("{}t/:topic", config.root_url)).get({
let dbs = dbs.clone();
move |req: tide::Request<()>| {
serve_comments(req, config, templates, dbs.clone(), Context::new(), 200)
let client_langs = get_client_langs(&req);
serve_comments(
req,
config,
templates,
dbs.clone(),
client_langs,
Context::new(),
200,
)
}
});
app.at(&format!("{}t/:topic", config.root_url)).post({
let dbs = dbs.clone();
move |req: tide::Request<()>| {
handle_post_comments(req, config, templates, dbs.clone(), notify_send.clone())
handle_post_comments(
req,
config,
templates,
dbs.clone(),
locales,
notify_send.clone(),
)
}
});
app.at(&format!("{}admin", config.root_url))
.get(move |req: tide::Request<()>| serve_admin_login(req, config, templates));
.get(move |req: tide::Request<()>| {
let client_langs = get_client_langs(&req);
serve_admin_login(req, config, templates, client_langs)
});
app.at(&format!("{}admin", config.root_url)).post({
let dbs = dbs.clone();
move |req: tide::Request<()>| handle_post_admin(req, config, templates, dbs.clone())
@ -38,6 +66,7 @@ async fn serve_comments<'a>(
config: &Config,
templates: &Templates,
dbs: Dbs,
client_langs: Vec<LanguageIdentifier>,
mut context: Context,
status_code: u16,
) -> tide::Result<tide::Response> {
@ -53,6 +82,18 @@ async fn serve_comments<'a>(
context.insert("config", &config);
context.insert("admin", &admin);
let time_lang = get_time_lang(&client_langs);
context.insert(
"time_lang",
time_lang.as_ref().unwrap_or(&config.default_lang),
);
context.insert(
"l",
&client_langs
.iter()
.map(|lang| lang.language.as_str())
.collect::<Vec<&str>>(),
);
if admin {
if let Ok(query) = req.query::<ApproveQuery>() {
@ -120,10 +161,23 @@ async fn serve_admin<'a>(
config: &Config,
templates: &Templates,
dbs: Dbs,
client_langs: &[LanguageIdentifier],
) -> tide::Result<tide::Response> {
let mut context = Context::new();
context.insert("config", &config);
context.insert("admin", &true);
let time_lang = get_time_lang(client_langs);
context.insert(
"time_lang",
time_lang.as_ref().unwrap_or(&config.default_lang),
);
context.insert(
"l",
&client_langs
.iter()
.map(|lang| lang.language.as_str())
.collect::<Vec<&str>>(),
);
context.insert(
"comments",
@ -164,9 +218,22 @@ async fn serve_admin_login(
_req: tide::Request<()>,
config: &Config,
templates: &Templates,
client_langs: Vec<LanguageIdentifier>,
) -> tide::Result<tide::Response> {
let mut context = Context::new();
context.insert("config", &config);
let time_lang = get_time_lang(&client_langs);
context.insert(
"time_lang",
time_lang.as_ref().unwrap_or(&config.default_lang),
);
context.insert(
"l",
&client_langs
.iter()
.map(|lang| lang.language.as_str())
.collect::<Vec<&str>>(),
);
Ok(tide::Response::builder(200)
.content_type(tide::http::mime::HTML)
@ -179,12 +246,15 @@ async fn handle_post_comments(
config: &Config,
templates: &Templates,
dbs: Dbs,
locales: &Locales,
notify_send: Sender<()>,
) -> tide::Result<tide::Response> {
let admin = req.cookie("admin").map_or(false, |psw| {
check_admin_password_hash(config, &String::from(psw.value()))
});
let client_langs = get_client_langs(&req);
let client_addr = if !admin && config.antispam_enable {
match helpers::get_client_addr(config, &req) {
Some(Ok(addr)) => {
@ -222,10 +292,19 @@ async fn handle_post_comments(
if let Some(antispam_timeout) =
helpers::antispam_check_client_mutation(client_addr, &dbs, config).unwrap()
{
errors.push(format!(
"The edition quota from your IP is reached. You will be unblocked in {}s.",
antispam_timeout
));
errors.push(
locales
.tr(
&client_langs,
"error-antispam",
Some(&FluentArgs::from_iter([(
"antispam_timeout",
antispam_timeout,
)])),
)
.unwrap()
.into_owned(),
);
}
}
@ -283,21 +362,33 @@ async fn handle_post_comments(
return Err(tide::Error::from_str(404, "Not found"));
};
if let Some(client_addr) = &client_addr {
// We're admin
/*if let Some(client_addr) = &client_addr {
if let Some(antispam_timeout) =
helpers::antispam_check_client_mutation(client_addr, &dbs, config).unwrap()
{
errors.push(format!(
"The edition quota from your IP is reached. You will be unblocked in {}s.",
antispam_timeout
));
let client_langs = get_client_langs(&req);
errors.push(
locales
.tr(
&client_langs,
"error-antispam",
Some(&FluentArgs::from_iter([(
"antispam_timeout",
antispam_timeout,
)])),
)
.unwrap()
.into_owned(),
);
}
}
}*/
if errors.is_empty() {
if let Some(client_addr) = &client_addr {
// We're admin
/*if let Some(client_addr) = &client_addr {
helpers::antispam_update_client_mutation(client_addr, &dbs).unwrap();
}
}*/
let time = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
@ -328,6 +419,7 @@ async fn handle_post_comments(
config,
templates,
dbs,
client_langs,
context,
if errors.is_empty() { 200 } else { 400 },
)
@ -344,31 +436,40 @@ async fn handle_post_admin(
if check_admin_password(config, &String::from(psw.value())).is_some() {
#[allow(clippy::match_single_binding)]
match req.body_form::<AdminQuery>().await? {
_ => serve_admin(req, config, templates, dbs).await,
_ => {
let client_langs = get_client_langs(&req);
serve_admin(req, config, templates, dbs, &client_langs).await
}
}
} else {
serve_admin_login(req, config, templates).await
let client_langs = get_client_langs(&req);
serve_admin_login(req, config, templates, client_langs).await
}
} else if let AdminQuery::Login(query) = req.body_form::<AdminQuery>().await? {
if let Some(password_hash) = check_admin_password(config, &query.psw) {
serve_admin(req, config, templates, dbs).await.map(|mut r| {
let mut cookie = tide::http::Cookie::new("admin", password_hash);
cookie.set_http_only(Some(true));
cookie.set_path(config.root_url.clone());
if let Some(domain) = &config.cookies_domain {
cookie.set_domain(domain.clone());
}
if config.cookies_https_only {
cookie.set_secure(Some(true));
}
r.insert_cookie(cookie);
r
})
let client_langs = get_client_langs(&req);
serve_admin(req, config, templates, dbs, &client_langs)
.await
.map(|mut r| {
let mut cookie = tide::http::Cookie::new("admin", password_hash);
cookie.set_http_only(Some(true));
cookie.set_path(config.root_url.clone());
if let Some(domain) = &config.cookies_domain {
cookie.set_domain(domain.clone());
}
if config.cookies_https_only {
cookie.set_secure(Some(true));
}
r.insert_cookie(cookie);
r
})
} else {
serve_admin_login(req, config, templates).await
let client_langs = get_client_langs(&req);
serve_admin_login(req, config, templates, client_langs).await
}
} else {
serve_admin_login(req, config, templates).await
let client_langs = get_client_langs(&req);
serve_admin_login(req, config, templates, client_langs).await
}
}