Fix browser console warning #1
4 changed files with 199 additions and 21 deletions
167
Cargo.lock
generated
167
Cargo.lock
generated
|
@ -17,6 +17,15 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -205,6 +214,41 @@ version = "0.8.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn 2.0.72",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.72",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
|
@ -399,6 +443,22 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-normalization",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.13"
|
version = "0.1.13"
|
||||||
|
@ -549,6 +609,7 @@ dependencies = [
|
||||||
"sled",
|
"sled",
|
||||||
"stylist",
|
"stylist",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"validator",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -699,6 +760,35 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
|
@ -819,6 +909,12 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylist"
|
name = "stylist"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
@ -924,6 +1020,21 @@ dependencies = [
|
||||||
"syn 2.0.72",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.39.1"
|
version = "1.39.1"
|
||||||
|
@ -998,12 +1109,68 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-normalization"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url"
|
||||||
|
version = "2.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"idna",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "validator"
|
||||||
|
version = "0.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db79c75af171630a3148bd3e6d7c4f42b6a9a014c2945bc5ed0020cbb8d9478e"
|
||||||
|
dependencies = [
|
||||||
|
"idna",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"url",
|
||||||
|
"validator_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "validator_derive"
|
||||||
|
version = "0.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55591299b7007f551ed1eb79a684af7672c19c3193fb9e0a31936987bb2438ec"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.72",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
|
@ -14,3 +14,4 @@ serde_json = "1.0.120"
|
||||||
sled = "0.34.7"
|
sled = "0.34.7"
|
||||||
stylist = "0.13.0"
|
stylist = "0.13.0"
|
||||||
tokio = { version = "1.39.1", features = ["net", "rt-multi-thread"] }
|
tokio = { version = "1.39.1", features = ["net", "rt-multi-thread"] }
|
||||||
|
validator = { version = "0.18.1", features = ["derive"] }
|
||||||
|
|
|
@ -88,5 +88,5 @@ pub async fn style() -> impl IntoResponse {
|
||||||
.get_style_str()
|
.get_style_str()
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
([("content-type", "style/css")], style)
|
([("content-type", "text/css")], style)
|
||||||
}
|
}
|
||||||
|
|
50
src/main.rs
50
src/main.rs
|
@ -13,10 +13,11 @@ use axum::{
|
||||||
};
|
};
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use common::{footer, head, header, style};
|
use common::{footer, head, header, style};
|
||||||
use maud::{html, Escaper, Markup, PreEscaped};
|
use maud::{html, Escaper, Markup, PreEscaped, DOCTYPE};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use store::Store;
|
use store::Store;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
use validator::{Validate, ValidationError};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
mod store;
|
mod store;
|
||||||
|
@ -50,6 +51,7 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
async fn home() -> Markup {
|
async fn home() -> Markup {
|
||||||
html!(
|
html!(
|
||||||
|
(DOCTYPE)
|
||||||
(head(""))
|
(head(""))
|
||||||
body {
|
body {
|
||||||
content {
|
content {
|
||||||
|
@ -71,6 +73,7 @@ async fn home() -> Markup {
|
||||||
async fn topics(State(state): State<MainState>) -> impl IntoResponse {
|
async fn topics(State(state): State<MainState>) -> impl IntoResponse {
|
||||||
let topics = state.store.read().unwrap().list().unwrap();
|
let topics = state.store.read().unwrap().list().unwrap();
|
||||||
html!(
|
html!(
|
||||||
|
(DOCTYPE)
|
||||||
(head("sujets"))
|
(head("sujets"))
|
||||||
body {
|
body {
|
||||||
content {
|
content {
|
||||||
|
@ -94,6 +97,7 @@ async fn topics(State(state): State<MainState>) -> impl IntoResponse {
|
||||||
async fn activity(State(state): State<MainState>) -> impl IntoResponse {
|
async fn activity(State(state): State<MainState>) -> impl IntoResponse {
|
||||||
let topics = state.store.read().unwrap().activity().unwrap();
|
let topics = state.store.read().unwrap().activity().unwrap();
|
||||||
html!(
|
html!(
|
||||||
|
(DOCTYPE)
|
||||||
(head("activité"))
|
(head("activité"))
|
||||||
body {
|
body {
|
||||||
content {
|
content {
|
||||||
|
@ -120,6 +124,7 @@ async fn topic(Path(name): Path<String>, State(state): State<MainState>) -> impl
|
||||||
};
|
};
|
||||||
|
|
||||||
html!(
|
html!(
|
||||||
|
(DOCTYPE)
|
||||||
(head(&name))
|
(head(&name))
|
||||||
body {
|
body {
|
||||||
content {
|
content {
|
||||||
|
@ -142,35 +147,38 @@ async fn topic(Path(name): Path<String>, State(state): State<MainState>) -> impl
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
|
||||||
struct PostContent {
|
struct PostContent {
|
||||||
|
#[validate(length(min = 1, max = 32), custom(function = "validate_topic"))]
|
||||||
topic: String,
|
topic: String,
|
||||||
|
#[validate(length(min = 10, max = 10_000))]
|
||||||
content: String,
|
content: String,
|
||||||
|
#[validate(length(min = 2, max = 32))]
|
||||||
author: String,
|
author: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn post(
|
fn validate_topic(topic: &str) -> Result<(), ValidationError> {
|
||||||
State(state): State<MainState>,
|
if topic.starts_with('_') || topic.ends_with('_') {
|
||||||
Form(PostContent {
|
return Err(ValidationError::new("Bad topic format."));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn post(State(state): State<MainState>, Form(post_content): Form<PostContent>) -> Response {
|
||||||
|
let mut store = state.store.write().unwrap();
|
||||||
|
let date = Utc::now().format("%d/%m/%Y");
|
||||||
|
|
||||||
|
if post_content.validate().is_err() {
|
||||||
|
return (StatusCode::BAD_REQUEST, "Bad input.").into_response();
|
||||||
|
}
|
||||||
|
|
||||||
|
let PostContent {
|
||||||
topic,
|
topic,
|
||||||
content,
|
content,
|
||||||
author,
|
author,
|
||||||
}): Form<PostContent>,
|
} = post_content;
|
||||||
) -> Response {
|
|
||||||
let mut store = state.store.write().unwrap();
|
|
||||||
let date = Utc::now().format("%d/%m/%Y");
|
|
||||||
let topic = sanithize_identifier(topic.trim());
|
|
||||||
let content = content.trim();
|
|
||||||
|
|
||||||
if content.len() < 10 || content.len() > 10_000 {
|
let topic = sanithize_identifier(&topic);
|
||||||
return (StatusCode::BAD_REQUEST, "Bad content.").into_response();
|
|
||||||
}
|
|
||||||
if author.len() > 2 || author.len() > 32 {
|
|
||||||
return (StatusCode::BAD_REQUEST, "Bad author.").into_response();
|
|
||||||
}
|
|
||||||
if topic.len() > 32 || topic.is_empty() || topic.starts_with('_') || topic.ends_with('_') {
|
|
||||||
return (StatusCode::BAD_REQUEST, "Bad topic.").into_response();
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = format!("{content}\n\t~{author}, {date}");
|
let content = format!("{content}\n\t~{author}, {date}");
|
||||||
store.insert(&topic, content).unwrap();
|
store.insert(&topic, content).unwrap();
|
||||||
|
@ -210,6 +218,7 @@ fn sanithize_identifier(input: &str) -> String {
|
||||||
|
|
||||||
async fn create() -> impl IntoResponse {
|
async fn create() -> impl IntoResponse {
|
||||||
html!(
|
html!(
|
||||||
|
(DOCTYPE)
|
||||||
(head("créer"))
|
(head("créer"))
|
||||||
body {
|
body {
|
||||||
content {
|
content {
|
||||||
|
@ -242,6 +251,7 @@ async fn create() -> impl IntoResponse {
|
||||||
fn error(message: impl ToString) -> Markup {
|
fn error(message: impl ToString) -> Markup {
|
||||||
let message = message.to_string();
|
let message = message.to_string();
|
||||||
html!(
|
html!(
|
||||||
|
(DOCTYPE)
|
||||||
(head("Failure"))
|
(head("Failure"))
|
||||||
body {
|
body {
|
||||||
content {
|
content {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue