Instead of adding all routes manually in the Launch function for Rocket, implement fairings for all the different files that adds the routing to the rocket in a self-contained manner.
218 lines
7.9 KiB
Rust
218 lines
7.9 KiB
Rust
use pulldown_cmark::{Options, Parser};
|
|
use rocket::fairing::AdHoc;
|
|
use rocket::form::Form;
|
|
use rocket::http::CookieJar;
|
|
use rocket::response::Redirect;
|
|
|
|
use rocket_db_pools::{sqlx, Connection};
|
|
use rocket_dyn_templates::{context, Template};
|
|
use sqlx::{Acquire, Executor};
|
|
use crate::auth;
|
|
use crate::auth::User;
|
|
use crate::database::Db;
|
|
use crate::database_records::{DisplayTruth, Player, Truth, Week};
|
|
|
|
#[get("/<week_number>")]
|
|
pub async fn week(week_number: u8, mut db: Connection<Db>, cookies: &CookieJar<'_>) -> Template {
|
|
let user: User = auth::get_user(week_number, &mut db, cookies).await;
|
|
|
|
let other_players = if user.logged_in {
|
|
match sqlx::query_as("SELECT id, name FROM Players WHERE id <> $1 AND is_admin == 0 ORDER BY name")
|
|
.bind(user.id)
|
|
.fetch_all(&mut **db).await {
|
|
Ok(v) => v,
|
|
Err(error) => {
|
|
error!("Some error while getting players : {error}");
|
|
Vec::<Player>::new()
|
|
}
|
|
}
|
|
} else {
|
|
Vec::<Player>::new()
|
|
};
|
|
|
|
let week_data: Week = match sqlx::query_as("SELECT number, is_last_week, rendered_text, raw_text FROM Weeks WHERE number == $1")
|
|
.bind(week_number)
|
|
.fetch_one(&mut **db)
|
|
.await {
|
|
Ok(week) => week,
|
|
Err(error) => {
|
|
error!("Error while retrieving week data : {error}");
|
|
Week {number: 0, is_last_week: true, rendered_text: "".to_string(), raw_text: "".to_string() }
|
|
}
|
|
};
|
|
|
|
// FIXME : This is fucking *trash* but fucking hell mate
|
|
if user.is_admin {
|
|
let truths: Vec<Truth> = match sqlx::query_as("SELECT * FROM Truths WHERE week == $1 ORDER BY number")
|
|
.bind(week_number)
|
|
.fetch_all(&mut **db).await {
|
|
Ok(v) => v,
|
|
Err(error) => {
|
|
error!("Error while getting truths : {error}");
|
|
Vec::<Truth>::new()
|
|
}
|
|
};
|
|
|
|
Template::render("index", context! {
|
|
week_data: week_data,
|
|
truths: truths,
|
|
user: user,
|
|
other_players: other_players,
|
|
})
|
|
} else {
|
|
let truths: Vec<DisplayTruth> = match sqlx::query_as("SELECT id, number, author_id, rendered_text FROM Truths WHERE week == $1 ORDER BY number")
|
|
.bind(week_number)
|
|
.fetch_all(&mut **db).await {
|
|
Ok(v) => v,
|
|
Err(error) => {
|
|
error!("Error while getting truths : {error}");
|
|
Vec::<DisplayTruth>::new()
|
|
}
|
|
};
|
|
|
|
Template::render("index", context! {
|
|
week_data: week_data,
|
|
truths: truths,
|
|
user: user,
|
|
other_players: other_players,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[post("/<week>/edit", data="<raw_intro>")]
|
|
pub async fn update_week(week: u8, raw_intro: Form<String>,
|
|
mut db: Connection<Db>, cookies: &CookieJar<'_>) -> Redirect {
|
|
let user = auth::get_user(week, &mut db, cookies).await;
|
|
if !user.is_admin {
|
|
cookies.add(("toast_error", "Vous n'avez pas la permission de changer la semaine."));
|
|
return Redirect::to(uri!(week(week)));
|
|
}
|
|
|
|
let mut options = Options::empty();
|
|
options.insert(Options::ENABLE_STRIKETHROUGH);
|
|
options.insert(Options::ENABLE_FOOTNOTES);
|
|
options.insert(Options::ENABLE_MATH);
|
|
options.insert(Options::ENABLE_TABLES);
|
|
let markdown_parser = Parser::new_ext(raw_intro.as_str(), options);
|
|
|
|
let mut rendered_markdown = String::new();
|
|
pulldown_cmark::html::push_html(&mut rendered_markdown, markdown_parser);
|
|
|
|
match sqlx::query("UPDATE Weeks SET raw_text = $1, rendered_text = $2 WHERE number == $3;")
|
|
.bind(&raw_intro.as_str())
|
|
.bind(rendered_markdown)
|
|
.bind(week)
|
|
.fetch_optional(&mut **db)
|
|
.await {
|
|
Ok(_) => {
|
|
debug!("Week successfully updated")
|
|
}
|
|
Err(error) => {
|
|
error!("Error while updating week {week} data : {error}");
|
|
cookies.add(("toast_error", "Il y a eu un problème lors du changement de la semaine"));
|
|
}
|
|
};
|
|
|
|
Redirect::to(uri!(week(week)))
|
|
}
|
|
|
|
#[post("/<week>/set_last")]
|
|
pub async fn set_last_week(week: u8, mut db: Connection<Db>, cookies: &CookieJar<'_>) -> Redirect {
|
|
let user = auth::get_user(week, &mut db, cookies).await;
|
|
if !user.is_admin {
|
|
cookies.add(("toast_error", "Vous n'avez pas la permission de changer la semaine."));
|
|
return Redirect::to(uri!(week(week)));
|
|
}
|
|
|
|
let add_error_cookie = ||
|
|
cookies.add(("toast_error", "Erreur lors du changement d'état de la semaine."));
|
|
|
|
let db_transaction_connection = db.begin().await;
|
|
if db_transaction_connection.is_err() {
|
|
error!("Could not start database transaction for last week change : {:?}", db_transaction_connection.unwrap_err());
|
|
add_error_cookie();
|
|
return Redirect::to(uri!(week(week)));
|
|
}
|
|
let mut db_transaction = db_transaction_connection.unwrap();
|
|
|
|
// Remove the last flag from other weeks, if set.
|
|
match db_transaction.execute("UPDATE Weeks SET is_last_week = 0 WHERE is_last_week == 1;")
|
|
.await {
|
|
Ok(_) => debug!("Succesfully cleared is_last_week"),
|
|
Err(error) => {
|
|
error!("Failed to clear last week status : {error}");
|
|
add_error_cookie();
|
|
return Redirect::to(uri!(week(week)));
|
|
}
|
|
};
|
|
|
|
// We should set one week, if not there's something wrong : rollback.
|
|
if match sqlx::query("UPDATE Weeks SET is_last_week = 1 WHERE number == $1;")
|
|
.bind(week)
|
|
.execute(&mut *db_transaction)
|
|
.await {
|
|
Ok(result) => result.rows_affected(),
|
|
Err(error) => {
|
|
error!("Error while setting last week status : {error}");
|
|
0
|
|
}
|
|
} == 1 {
|
|
db_transaction.commit().await.unwrap_or_else(|error| {
|
|
error!("Error while committing week is last transaction : {error}");
|
|
add_error_cookie();
|
|
})
|
|
} else {
|
|
db_transaction.rollback().await.unwrap_or_else(|error| {
|
|
error!("Error while rolling back week is last transaction : {error}");
|
|
add_error_cookie();
|
|
})
|
|
}
|
|
|
|
Redirect::to(uri!(week(week)))
|
|
}
|
|
|
|
#[get("/<week>/create")]
|
|
pub async fn create_week(week: u8, mut db: Connection<Db>, cookies: &CookieJar<'_>) -> Redirect {
|
|
let user = auth::get_user(week, &mut db, cookies).await;
|
|
if !user.is_admin {
|
|
cookies.add(("toast_error", "Vous n'avez pas la permission de changer la semaine."));
|
|
return Redirect::to(uri!(week(week - 1)));
|
|
}
|
|
|
|
let week_check: Result<Option<u8>, sqlx::Error> = sqlx::query_scalar("SELECT number from Weeks WHERE number == $1;")
|
|
.bind(week)
|
|
.fetch_optional(&mut **db)
|
|
.await;
|
|
|
|
if week_check.is_err() {
|
|
error!("Error while checking week existence : {:?}", week_check.unwrap_err());
|
|
cookies.add(("toast_error", "Erreur en vérifiant que la semaine n'existe pas déjà"));
|
|
return Redirect::to(uri!(week(week - 1)));
|
|
}
|
|
|
|
if week_check.unwrap().is_some() {
|
|
debug!("Week {week} already exists, not creating.");
|
|
return Redirect::to(uri!(week(week)));
|
|
}
|
|
|
|
match sqlx::query("INSERT INTO Weeks (number, is_last_week, rendered_text, raw_text) VALUES ($1, 0, \"\", \"\");")
|
|
.bind(week)
|
|
.execute(&mut **db)
|
|
.await {
|
|
Ok(_) => {
|
|
debug!("Succesfully created new week {week}");
|
|
Redirect::to(uri!(week(week)))
|
|
},
|
|
Err(error) => {
|
|
error!("Error while creating new week {week} : {error}");
|
|
cookies.add(("toast_error", "Erreur en créant la nouvelle selmaine."));
|
|
Redirect::to(uri!(week(week - 1)))
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn stage() -> AdHoc {
|
|
AdHoc::on_ignite("Week stage", |rocket| async {
|
|
rocket.mount("/", routes![week, create_week, update_week, set_last_week])
|
|
})
|
|
}
|