Admin
This commit is contained in:
parent
fb2d18f879
commit
70ceb146bf
|
@ -434,6 +434,7 @@ dependencies = [
|
|||
"sled",
|
||||
"structopt",
|
||||
"tokio",
|
||||
"urlencoding",
|
||||
"warp",
|
||||
]
|
||||
|
||||
|
|
|
@ -16,4 +16,5 @@ sha2 = "0.9.1"
|
|||
sled = "0.34.4"
|
||||
structopt = "0.3.20"
|
||||
tokio = { version = "0.2.22", features = ["macros", "rt-threaded"] }
|
||||
urlencoding = "1.1.1"
|
||||
warp = "0.2.5"
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::{
|
|||
sync::{Arc, RwLock},
|
||||
};
|
||||
use warp::Filter;
|
||||
use warp::Reply;
|
||||
|
||||
type PasswordHash = [u8; 32];
|
||||
|
||||
|
@ -56,10 +57,12 @@ pub async fn start_server(
|
|||
.collect::<Vec<AdWithId>>(),
|
||||
)));
|
||||
|
||||
let config = Arc::new(config);
|
||||
let dbs = Arc::new(dbs);
|
||||
|
||||
let handle_index = {
|
||||
let cache_ads = cache_ads.clone();
|
||||
let templates = templates.clone();
|
||||
move |errors: &[ErrorTemplate]| {
|
||||
warp::reply::html(
|
||||
templates
|
||||
|
@ -77,6 +80,32 @@ pub async fn start_server(
|
|||
}
|
||||
};
|
||||
|
||||
let handle_admin_login = {
|
||||
let templates = templates.clone();
|
||||
move |errors: &[ErrorTemplate]| {
|
||||
warp::reply::html(
|
||||
templates
|
||||
.hb
|
||||
.render(
|
||||
"admin_login.html",
|
||||
&AdminLoginTemplate { lang: "fr", errors },
|
||||
)
|
||||
.unwrap_or_else(|e| e.to_string()),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let handle_admin = {
|
||||
move |errors: &[ErrorTemplate]| {
|
||||
warp::reply::html(
|
||||
templates
|
||||
.hb
|
||||
.render("admin.html", &AdminTemplate { lang: "fr", errors })
|
||||
.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)));
|
||||
|
@ -184,7 +213,57 @@ pub async fn start_server(
|
|||
),
|
||||
));
|
||||
|
||||
warp::serve(route_static.or(route_index))
|
||||
let route_admin = warp::path("admin").and(
|
||||
warp::path::end()
|
||||
.and(
|
||||
warp::cookie("admin")
|
||||
.map({
|
||||
let handle_admin = handle_admin.clone();
|
||||
let handle_admin_login = handle_admin_login.clone();
|
||||
let config = config.clone();
|
||||
move |psw: String| {
|
||||
if !config.admin_passwords.contains(&psw) {
|
||||
handle_admin_login(&[ErrorTemplate {
|
||||
text: "Mot de passe administrateur invalide",
|
||||
}])
|
||||
} else {
|
||||
handle_admin(&[])
|
||||
}
|
||||
}
|
||||
})
|
||||
.or(warp::path::end().map({
|
||||
let handle_admin_login = handle_admin_login.clone();
|
||||
move || handle_admin_login(&[])
|
||||
})),
|
||||
)
|
||||
.or(warp::path("login").and(warp::path::end()).and(
|
||||
warp::post()
|
||||
.and(warp::get().map(move || handle_admin(&[])))
|
||||
.or(warp::body::form::<AdminLoginQuery>().map({
|
||||
let config = config.clone();
|
||||
move |query: AdminLoginQuery| {
|
||||
if config.admin_passwords.contains(&query.psw) {
|
||||
warp::reply::with_header(
|
||||
warp::redirect(warp::http::Uri::from_static("/admin")),
|
||||
"Set-Cookie",
|
||||
format!("admin={}; HttpOnly", urlencoding::encode(&query.psw)),
|
||||
)
|
||||
.into_response()
|
||||
} else {
|
||||
handle_admin_login(&[ErrorTemplate {
|
||||
text: "Mot de passe administrateur invalide",
|
||||
}])
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
})),
|
||||
))
|
||||
.or(warp::path("logout")
|
||||
.and(warp::path::end())
|
||||
.map(|| warp::redirect(warp::http::Uri::from_static("/")))),
|
||||
);
|
||||
|
||||
warp::serve(route_static.or(route_index).or(route_admin))
|
||||
.run(config.listen)
|
||||
.await;
|
||||
}
|
||||
|
@ -196,6 +275,18 @@ struct IndexTemplate<'a> {
|
|||
ads: &'a Json,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct AdminLoginTemplate<'a> {
|
||||
lang: &'a str,
|
||||
errors: &'a [ErrorTemplate<'a>],
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct AdminTemplate<'a> {
|
||||
lang: &'a str,
|
||||
errors: &'a [ErrorTemplate<'a>],
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ErrorTemplate<'a> {
|
||||
text: &'a str,
|
||||
|
@ -217,6 +308,11 @@ struct RmAdQuery {
|
|||
psw: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct AdminLoginQuery {
|
||||
psw: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(tag = "a")]
|
||||
enum Query {
|
||||
|
|
|
@ -2,8 +2,14 @@ use handlebars::Handlebars;
|
|||
use std::path::Path;
|
||||
|
||||
const TEMPLATES_DIR: &'static str = "templates";
|
||||
static TEMPLATE_FILES: &'static [(&str, &str)] =
|
||||
&[("index.html", include_str!("../templates/index.html"))];
|
||||
static TEMPLATE_FILES: &'static [(&str, &str)] = &[
|
||||
("index.html", include_str!("../templates/index.html")),
|
||||
("admin.html", include_str!("../templates/admin.html")),
|
||||
(
|
||||
"admin_login.html",
|
||||
include_str!("../templates/admin_login.html"),
|
||||
),
|
||||
];
|
||||
|
||||
pub struct Templates<'reg> {
|
||||
pub hb: Handlebars<'reg>,
|
||||
|
|
|
@ -31,6 +31,7 @@ h1, h2, h3, h4 {
|
|||
}
|
||||
|
||||
#errors {
|
||||
margin-bottom: 1em;
|
||||
padding: 4px;
|
||||
border: 2px dashed rgba(128, 0, 0, 0.2);
|
||||
border-radius: 3px;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<!doctype html>
|
||||
<html lang="{{lang}}">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Administration | ĞMarché</title>
|
||||
<link rel="stylesheet" href="/static/style1.css"/>
|
||||
<link rel="shortcut icon" href="/static/icon.png"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="center">
|
||||
<a href="/"><img id="banner" alt="ĞMarché" src="/static/banner.jpg"/></a>
|
||||
|
||||
<h1>Administration – ĞMarché</h1>
|
||||
|
||||
{{#if errors}}
|
||||
<div id="errors">
|
||||
<span>Oups, il y a un problème :</span>
|
||||
<ul>
|
||||
{{#each errors}}
|
||||
<li>{{this.text}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<hr style="clear: both;"/>
|
||||
|
||||
<p><a href="https://forum.duniter.org">Toutes les questions techniques ont leur place sur le forum.</a></p>
|
||||
|
||||
<p><a href="https://git.p2p.legal/tuxmain/gmarche-rs">Code source</a> sous licence <a href="https://www.gnu.org/licenses/licenses.html#AGPL">GNU AGPL v3</a>. 🦀 Écrit en <a href="https://www.rust-lang.org">Rust</a>. Images de Attilax.<br/>
|
||||
CopyLeft 2020 Pascal Engélibert</p>
|
||||
|
||||
<p><a href="/">Accueil</a></p> – <a href="/admin/logout">Verrouiller</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,44 @@
|
|||
<!doctype html>
|
||||
<html lang="{{lang}}">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Administration | ĞMarché</title>
|
||||
<link rel="stylesheet" href="/static/style1.css"/>
|
||||
<link rel="shortcut icon" href="/static/icon.png"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="center">
|
||||
<a href="/"><img id="banner" alt="ĞMarché" src="/static/banner.jpg"/></a>
|
||||
|
||||
<h1>Administration – ĞMarché</h1>
|
||||
|
||||
<h2>Authentification</h2>
|
||||
|
||||
{{#if errors}}
|
||||
<div id="errors">
|
||||
<span>Oups, il y a un problème :</span>
|
||||
<ul>
|
||||
{{#each errors}}
|
||||
<li>{{this.text}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<form action="/admin/login" method="post">
|
||||
<label for="f_psw">Mot de passe :</label>
|
||||
<input type="password" id="f_psw" name="psw"/>
|
||||
<input type="submit" value="S'authentifier"/>
|
||||
</form>
|
||||
|
||||
<hr style="clear: both;"/>
|
||||
|
||||
<p><a href="https://forum.duniter.org">Toutes les questions techniques ont leur place sur le forum.</a></p>
|
||||
|
||||
<p><a href="https://git.p2p.legal/tuxmain/gmarche-rs">Code source</a> sous licence <a href="https://www.gnu.org/licenses/licenses.html#AGPL">GNU AGPL v3</a>. 🦀 Écrit en <a href="https://www.rust-lang.org">Rust</a>. Images de Attilax.<br/>
|
||||
CopyLeft 2020 Pascal Engélibert</p>
|
||||
|
||||
<p><a href="/">Accueil</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -85,6 +85,8 @@
|
|||
|
||||
<p><a href="https://git.p2p.legal/tuxmain/gmarche-rs">Code source</a> sous licence <a href="https://www.gnu.org/licenses/licenses.html#AGPL">GNU AGPL v3</a>. 🦀 Écrit en <a href="https://www.rust-lang.org">Rust</a>. Images de Attilax.<br/>
|
||||
CopyLeft 2020 Pascal Engélibert</p>
|
||||
|
||||
<p><a href="/admin">Administration</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in New Issue