add posting

This commit is contained in:
JOLIMAITRE Matthieu 2024-07-25 08:48:56 +02:00
parent e5cb7f3d69
commit 4537fc379c
2 changed files with 58 additions and 9 deletions

View file

@ -1,12 +1,15 @@
use std::fmt::Write;
use std::sync::{Arc, RwLock};
use std::{
fmt::Write,
sync::{Arc, RwLock},
};
use anyhow::Result;
use axum::{
extract::{Path, State},
response::IntoResponse,
http::StatusCode,
response::{IntoResponse, Redirect, Response},
routing::get,
Json, Router,
Form, Json, Router,
};
use chrono::prelude::*;
use common::{footer, head, header, style};
@ -33,6 +36,7 @@ async fn main() -> Result<()> {
.route("/style.css", get(style))
.route("/topics", get(topics).post(post))
.route("/topic/:name", get(topic))
.route("/create", get(create))
.route("/activity", get(activity))
.route("/", get(home))
.with_state(state);
@ -147,18 +151,30 @@ struct PostContent {
async fn post(
State(state): State<MainState>,
Json(PostContent {
Form(PostContent {
topic,
content,
author,
}): Json<PostContent>,
) -> impl IntoResponse {
}): Form<PostContent>,
) -> Response {
let mut store = state.store.write().unwrap();
let date = Utc::now().format("%d/%m/%Y");
let topic = sanithize_identifier(&topic);
let topic = sanithize_identifier(topic.trim());
let content = content.trim();
if content.len() < 10 || content.len() > 10_000 {
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}");
store.insert(&topic, content).unwrap();
Redirect::to("/activity").into_response()
}
fn sanithize_identifier(input: &str) -> String {
@ -177,6 +193,7 @@ fn sanithize_identifier(input: &str) -> String {
('ö', 'o'),
('û', 'u'),
('ü', 'u'),
(' ', '_'),
];
text.chars()
.map(|c| {
@ -187,10 +204,41 @@ fn sanithize_identifier(input: &str) -> String {
}
c
})
.filter(char::is_ascii)
.filter(|c| c.is_ascii_lowercase() || *c == '_')
.collect()
}
async fn create() -> impl IntoResponse {
html!(
(head("créer"))
body {
content {
(header())
main {
h2 { "Créer" }
form id = "create" action = "/topics" method = "post" {
label for = "topic" { "Sujet" }
input type = "text" name = "topic";
br;
label for = "author" { "Auteur" }
input type = "text" name = "author";
br;
label for = "content" { "Contenu" }
textarea form = "create" name = "content" { }
br;
input type = "submit";
}
}
(footer())
}
}
)
}
fn error(message: impl ToString) -> Markup {
let message = message.to_string();
html!(