From a2f70c318ff1efa667be7166d347f95530ddd5b1 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Tue, 23 Jul 2024 21:51:56 +0100 Subject: [PATCH 01/42] auth: Fix auth token getting leaked to console Remove a forgotten debug print that leaked auth tokens to the console to check how they got saved and restored to the database. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/auth.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14afd09..d10f706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -578,7 +578,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fabula_votes_server" -version = "1.1.0" +version = "1.1.1" dependencies = [ "argon2", "blake2", diff --git a/Cargo.toml b/Cargo.toml index 57936af..e316357 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "fabula_votes_server" license = "MPL-2.0" readme = "README.md" authors = ["trotFunky"] -version = "1.1.0" +version = "1.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/auth.rs b/src/auth.rs index 1902291..ac909f0 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -56,7 +56,7 @@ pub async fn get_user(week: u8, db: &mut Connection, cookies: &CookieJar<'_> Vec::::new() } }; - tokens.iter().find(|auth_token| {println!("Token : {:?}\nCookie : {:?}", auth_token.token, token_str); auth_token.token.eq(&token_str)}).is_some() + tokens.iter().find(|auth_token| {auth_token.token.eq(&token_str)}).is_some() } else { id_str = String::new(); false From dc00e22dbaeeee8d961ed29f4b734e6a53e5757f Mon Sep 17 00:00:00 2001 From: trotFunky Date: Tue, 23 Jul 2024 21:41:42 +0100 Subject: [PATCH 02/42] vote_chart: Remove log of received datasets Another debug print that I forgot for the release. --- static_files/vote_chart.js | 1 - 1 file changed, 1 deletion(-) diff --git a/static_files/vote_chart.js b/static_files/vote_chart.js index 50df871..7bdae87 100644 --- a/static_files/vote_chart.js +++ b/static_files/vote_chart.js @@ -27,7 +27,6 @@ async function main() { data: vote_data[player], }) } - console.log(datasets) } catch (error) { console.error("Failed to parse vote data : \n\t" + error.message); return; From b6f3a49e9f304e1752d50cc6d49677e6cc136d29 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Tue, 23 Jul 2024 21:47:18 +0100 Subject: [PATCH 03/42] vote: Reset the truth counter to 1 if the key changes In order to fill the missing truths with 0, a counter follows the next expected truth number. If it suddenly drops down, we changed player and it should reset as well. However, as not all players are voted for on all truths, we might change players but get a higher truth, which was not taken into account and could miss all the zeroes at the beggining for this player. Reset the counter if we change players. --- src/vote.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vote.rs b/src/vote.rs index 395c06c..09239f6 100644 --- a/src/vote.rs +++ b/src/vote.rs @@ -126,7 +126,9 @@ pub async fn fetch_vote_data(week: u8, mut db: Connection) -> Opti let votes_for_player: &mut Vec = match vote_data.entry(raw_vote.votes_for) { Entry::Occupied(existing) => {existing.into_mut()} - Entry::Vacant(vacant) => {vacant.insert(Vec::::new())} + Entry::Vacant(vacant) => { + next_truth_number = 1; // We changed user, reset to 1. + vacant.insert(Vec::::new())} }; // Fill up missing spaces if we are missing any. From 8547312a78642e827f041dadc331ee476d6ff0cb Mon Sep 17 00:00:00 2001 From: trotFunky Date: Tue, 23 Jul 2024 22:14:18 +0100 Subject: [PATCH 04/42] README: Update todo, fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc5d83a..cb8a569 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ A list of things that could be implemented/added to the application, some of the - [ ] Being able to change from one week to the next - [ ] Create new weeks for the admin - [ ] Proper week redirection - - [ ] Add introduction to the weekly truths + - [x] Add introduction to the weekly truths - [ ] Bundle static assets in the binary - - [ ] Move the databse queries to their own functions + - [ ] Move the database queries to their own functions - [ ] Cache those results - [ ] Centralize Markdown parsing ? - [ ] Use fairings for the different elements ? From 982a7ffd655a746a3edf82cecff82031b674d2e8 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Wed, 24 Jul 2024 15:23:52 +0100 Subject: [PATCH 05/42] vote_chart: sort parsed votes The SQL query retrieving the votes is deterministicly sorted, but goes through a HashMap, for ease of processing and transfer, which does not maintaing order. Sort the resulting object in the Javascript to keep a consistent order in the graph. --- src/vote.rs | 2 ++ static_files/vote_chart.js | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/vote.rs b/src/vote.rs index 09239f6..d4e5d42 100644 --- a/src/vote.rs +++ b/src/vote.rs @@ -115,6 +115,8 @@ pub async fn fetch_vote_data(week: u8, mut db: Connection) -> Opti } + // The hash map makes storing and retrieving the data really easy, *but* + // it does lose the order of the original array (which is sorted via the SQL). let mut vote_data = HashMap::>::new(); let mut next_truth_number = 1; for raw_vote in raw_votes { diff --git a/static_files/vote_chart.js b/static_files/vote_chart.js index 7bdae87..45b3ab2 100644 --- a/static_files/vote_chart.js +++ b/static_files/vote_chart.js @@ -32,11 +32,15 @@ async function main() { return; } + // Sort by label to maintain the same graph order, as it goes through a hash map in the backend. + datasets.sort((a, b) => a.label > b.label) + const chart_canvas = document.getElementById("vote_chart") let chart function create_chart(keys, data) { let main_axis; let aspect_ratio; + // TODO: Move to the event, to check and not re-create for no reason. if (window.innerWidth > window.innerHeight) { main_axis = 'x' aspect_ratio = 2 From 8fd8ce8220657b61cdbec4f080fbec5db2e88c3b Mon Sep 17 00:00:00 2001 From: trotFunky Date: Wed, 24 Jul 2024 16:27:43 +0100 Subject: [PATCH 06/42] vote_chart: Remove test code This was written for testing the chart before plugging in to the database, remove it now that is not useful anymore. --- static_files/vote_chart.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/static_files/vote_chart.js b/static_files/vote_chart.js index 45b3ab2..5bc5e54 100644 --- a/static_files/vote_chart.js +++ b/static_files/vote_chart.js @@ -1,14 +1,4 @@ -// const names = ["Bystus", "Dory", "Fen", "Lucky", "Nico", "Peran", "trot"] -// -// -// let data = []; -// for (let i = 0; i < 7; i++) { -// data.push({ -// parsing: true, -// label: names[i], -// data: Array.from(keys, () => Math.round(Math.random()*1.33))}) -// } async function main() { const vote_response = await fetch(document.URL+"/votes"); if (!vote_response.ok) { From d0843d600e0d62e40887711883f112e86a8aa5a4 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Wed, 24 Jul 2024 16:56:08 +0100 Subject: [PATCH 07/42] vote_chart: Control the graph ratio switch The media query used to switch the ratio of the graph would only fire when switching from landscape to portrait, or the other way around. This makes controlling the point where the graph switches to vertical is only possible at this exact point. Introduce a limit aspect-ratio that controls the change and use it for the MediaQuery as well. Make sure we don't delete/recreate the chart for no reason as well. --- static_files/vote_chart.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/static_files/vote_chart.js b/static_files/vote_chart.js index 5bc5e54..fe93e11 100644 --- a/static_files/vote_chart.js +++ b/static_files/vote_chart.js @@ -1,3 +1,4 @@ +const limit_ratio = 1.3 async function main() { const vote_response = await fetch(document.URL+"/votes"); @@ -27,18 +28,32 @@ async function main() { const chart_canvas = document.getElementById("vote_chart") let chart + let previous_orientation function create_chart(keys, data) { let main_axis; let aspect_ratio; - // TODO: Move to the event, to check and not re-create for no reason. - if (window.innerWidth > window.innerHeight) { + let orientation + + if (window.innerWidth / window.innerHeight > limit_ratio) { + orientation = "landscape" main_axis = 'x' aspect_ratio = 2 } else { + orientation = "portrait" main_axis = 'y' aspect_ratio = 0.5 } + // Don't re-create the chart for no reason. + if (orientation === previous_orientation) { + console.log("bijour") + return; + } else { + console.log("badour") + } + + previous_orientation = orientation + if ( chart ) { chart.destroy() } @@ -69,7 +84,7 @@ async function main() { create_chart(keys, datasets) } - const orientation_query = matchMedia("screen and (orientation:portrait)"); + const orientation_query = matchMedia(`(aspect-ratio < ${limit_ratio})`); orientation_query.onchange = update_chart_ratio create_chart(keys, datasets) From 4c89a0783d2e1fd8af2ede21a2231877f84f2097 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Wed, 24 Jul 2024 18:08:13 +0100 Subject: [PATCH 08/42] vote_chart: Add title to the graph --- static_files/vote_chart.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/static_files/vote_chart.js b/static_files/vote_chart.js index fe93e11..8dd6869 100644 --- a/static_files/vote_chart.js +++ b/static_files/vote_chart.js @@ -75,6 +75,13 @@ async function main() { y: { stacked: true } + }, + plugins: { + title: { + display: true, + position: 'bottom', + text: 'Répartition des suppositions' + } } } }) From f74ed20e80f9f92a687d118e79b50e470cb6ff0f Mon Sep 17 00:00:00 2001 From: trotFunky Date: Wed, 24 Jul 2024 18:11:37 +0100 Subject: [PATCH 09/42] vote_chart: Add custom colors I didn't like the default colors, so introduce a new set of them and set them to the datasets. Do it after the sort, otherwise the colors wouldn't stay consistent. --- static_files/vote_chart.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/static_files/vote_chart.js b/static_files/vote_chart.js index 8dd6869..09850d4 100644 --- a/static_files/vote_chart.js +++ b/static_files/vote_chart.js @@ -1,5 +1,5 @@ const limit_ratio = 1.3 - +const colors = ['#b6b8fc', '#b6f4fc', '#fcb6cc', '#e0fcb6', '#fcdcb6', '#b6fcc8', '#f0b6fc'] async function main() { const vote_response = await fetch(document.URL+"/votes"); if (!vote_response.ok) { @@ -23,8 +23,12 @@ async function main() { return; } + // Sort by label to maintain the same graph order, as it goes through a hash map in the backend. datasets.sort((a, b) => a.label > b.label) + for (let i = 0; i < datasets.length; i++) { + datasets[i].backgroundColor = colors[i % colors.length] + } const chart_canvas = document.getElementById("vote_chart") let chart From f7e1218f210bbb92399861eef2086ef7185278f4 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Thu, 25 Jul 2024 16:54:19 +0100 Subject: [PATCH 10/42] truths: Change truth creation URL As we will be able to create a new week, /new to /new_truth to differentiate it from the week creation URL. --- src/truth.rs | 2 +- templates/index.html.tera | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/truth.rs b/src/truth.rs index dd4c0ea..ae96101 100644 --- a/src/truth.rs +++ b/src/truth.rs @@ -53,7 +53,7 @@ pub async fn edit_truth(week: u8, truth_number: u8, form: Form, Redirect::to(uri!("/")) } -#[post("//new", data="
")] +#[post("//new_truth", data="")] pub async fn create_truth(week: u8, form: Form, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { let user = auth::get_user(week, &mut db, cookies).await; diff --git a/templates/index.html.tera b/templates/index.html.tera index ae99a96..9c8f302 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -91,7 +91,7 @@ {% if user.is_admin == true %}

Nouvelle vérité

- + {% include "truth_editor" %}
From 2b3dd28fed2bcec21815009ecd0628c4019fa8ec Mon Sep 17 00:00:00 2001 From: trotFunky Date: Thu, 25 Jul 2024 18:32:53 +0100 Subject: [PATCH 11/42] style: Fix edit box clipping the graph It looks like the width of the element is calculated *inside* the padding, so the outer width is really width+2*padding. This leads to the edit box going outside of the truth column and clipping the graph. Compute the width to take the padding into account. --- static_files/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static_files/style.css b/static_files/style.css index 3de7065..2978081 100644 --- a/static_files/style.css +++ b/static_files/style.css @@ -24,7 +24,7 @@ } .editor { - width: 100%; + width: calc(100% - 1.25em); /* The width is calculated *inside* the padding, so adjust for it. */ height: 6eM; font-size: large; padding: 0.5em; From 207ce6c1d220682415b5ff1e8d83799932f2962f Mon Sep 17 00:00:00 2001 From: trotFunky Date: Thu, 25 Jul 2024 23:29:36 +0100 Subject: [PATCH 12/42] templates: Check vote against truth id, not number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I made a choice to only log confirmed votes : there is no blank vote in the database. This means that when fetching a user's vote, if they have not voted for everyone there will be votes missing. As this is sent to the templating engine via a Vector, the ordering of the votes will be incorrect : all existing votes will follow each other, and there will be missing votes at the end. Update the select logic in the truth template to account for that by checking the truth_id directly, rather than via the index of the array. (O(N²)...) Remove 'has_vote' as this is not useful anymore. --- templates/index.html.tera | 9 +-------- templates/truth.html.tera | 12 +++++++----- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/templates/index.html.tera b/templates/index.html.tera index 9c8f302..f3c3c42 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -12,13 +12,6 @@ -{# Check if the user has a vote in advance, for readability #} -{% if user.logged_in == true and user.has_week_vote == true%} - {% set has_vote = true %} -{% else %} - {% set has_vote = false %} -{% endif -%} -

{{ title }}

@@ -78,7 +71,7 @@ {% if user.logged_in == true and user.is_admin == false %}
+ + {% endif %}
{{ week_data.rendered_text | safe }} {%- if user.is_admin == true -%} From a0b79a17ea0a583c6773db43b9dbc1b29b334aa9 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Fri, 26 Jul 2024 01:08:30 +0100 Subject: [PATCH 17/42] Redirects: properly redirect to the current week Previously, most redirects targeted the root of the application. This was okay for the first part of development where only one week would be active, but would be annoying when using multiple weeks. Change those redirects to call week::week. Change the login path to be dependant on the current week as well, so it can be correctly redirected. --- README.md | 2 +- src/auth.rs | 16 ++++++++-------- src/truth.rs | 12 ++++++------ src/vote.rs | 6 +++--- src/week.rs | 6 +++--- templates/index.html.tera | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index ac48cb6..2b6d940 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A list of things that could be implemented/added to the application, some of the - [x] Being able to change from one week to the next - [x] Create new weeks for the admin - - [ ] Proper week redirection + - [x] Proper week redirection - [ ] Correctly handle non-existing week number - [x] Add introduction to the weekly truths - [ ] Bundle static assets in the binary diff --git a/src/auth.rs b/src/auth.rs index 1fd62fa..7f6b251 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -9,7 +9,7 @@ use argon2::{Argon2, PasswordHash, PasswordVerifier}; use blake2::{Blake2b512, Digest}; use blake2::digest::FixedOutput; use crate::database_records::{AuthTokens, PlayerLoginInfo, Vote}; -use crate::database; +use crate::{database, week}; use database::Db; // TODO: Make FromRequest guard https://api.rocket.rs/v0.5/rocket/request/trait.FromRequest and split admin @@ -126,8 +126,8 @@ pub struct AuthForm { password: String } -#[post("/login", data="
")] -pub async fn login(form: Form, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { +#[post("//login", data="")] +pub async fn login(week: u8, form: Form, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { let user_search: Result = sqlx::query_as("SELECT id, is_admin, name, pwd_hash FROM Players WHERE name == $1") .bind(&form.name) .fetch_one(&mut **db) @@ -136,7 +136,7 @@ pub async fn login(form: Form, mut db: Connection, cookies: &Cooki if user_search.is_err() { error!("Login failed : invalid user {:?}, err: {:?}", form.name, user_search.err()); cookies.add(("toast_error", "Impossible de se connecter !")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } let new_user = user_search.unwrap(); @@ -144,7 +144,7 @@ pub async fn login(form: Form, mut db: Connection, cookies: &Cooki if password_hash_parse.is_err() { error!("Login failed : could not parse password hash {:?}", password_hash_parse.err()); cookies.add(("toast_error", "Impossible de se connecter !")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } let password_hash = password_hash_parse.unwrap(); @@ -168,7 +168,7 @@ pub async fn login(form: Form, mut db: Connection, cookies: &Cooki Err(error) => { error!("Login failed : coult not store auth token in database : {error}"); cookies.add(("toast_error", "Impossible de se connecter !")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } } @@ -178,11 +178,11 @@ pub async fn login(form: Form, mut db: Connection, cookies: &Cooki Err(err) => { error!("Login failed : invalid password for {:?}\nError : {err}", new_user.name); cookies.add(("toast_error", "Impossible de se connecter !")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } } - Redirect::to(uri!("/")) + Redirect::to(uri!(week::week(week))) } pub fn bypass_auth_debug(cookies: &CookieJar<'_>) { diff --git a/src/truth.rs b/src/truth.rs index ae96101..861449c 100644 --- a/src/truth.rs +++ b/src/truth.rs @@ -6,7 +6,7 @@ use rocket_db_pools::{sqlx, Connection}; use pulldown_cmark::{Parser, Options}; use sqlx::Row; -use crate::{auth, database}; +use crate::{auth, database, week}; #[derive(FromForm)] pub struct TruthUpdateForm { @@ -20,7 +20,7 @@ pub async fn edit_truth(week: u8, truth_number: u8, form: Form, 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 vérité.")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } let mut options = Options::empty(); @@ -50,7 +50,7 @@ pub async fn edit_truth(week: u8, truth_number: u8, form: Form, } }; - Redirect::to(uri!("/")) + Redirect::to(uri!(week::week(week))) } #[post("//new_truth", data="")] @@ -59,7 +59,7 @@ pub async fn create_truth(week: u8, form: Form, let user = auth::get_user(week, &mut db, cookies).await; if !user.is_admin { cookies.add(("toast_error", "Vous n'avez pas la permission d'ajouter de vérité.")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } let truth_number: u8 = match sqlx::query("SELECT max(number) from Truths WHERE week == $1;") @@ -76,7 +76,7 @@ pub async fn create_truth(week: u8, form: Form, if truth_number == 0 { error!("Error while getting max truth number."); cookies.add(("toast_error", "Erreur lors de l'ajout de la vérité...")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } let mut options = Options::empty(); @@ -108,5 +108,5 @@ pub async fn create_truth(week: u8, form: Form, debug!("Truth was successfully added"); - Redirect::to(uri!("/")) + Redirect::to(uri!(week::week(week))) } diff --git a/src/vote.rs b/src/vote.rs index 831068c..f3becde 100644 --- a/src/vote.rs +++ b/src/vote.rs @@ -10,7 +10,7 @@ use rocket::serde::json::Json; use rocket_db_pools::{sqlx, Connection}; -use crate::{auth, database}; +use crate::{auth, database, week}; use crate::database_records::{Vote, VotingData}; #[derive(FromForm)] @@ -25,7 +25,7 @@ pub async fn vote(week: u8, form: Form, if !user.logged_in { cookies.add(("toast_error", "Vous n'avez pas la permission de changer de vote.")); - return Redirect::to(uri!("/")); + return Redirect::to(uri!(week::week(week))); } let filtered_votes = form.truth_votes.iter().filter_map( @@ -85,7 +85,7 @@ pub async fn vote(week: u8, form: Form, debug!("Vote successful") } - Redirect::to(uri!("/")) + Redirect::to(uri!(week::week(week))) } #[derive(Serialize, Deserialize)] diff --git a/src/week.rs b/src/week.rs index 6e6de1a..1eb52db 100644 --- a/src/week.rs +++ b/src/week.rs @@ -22,7 +22,7 @@ pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<' .fetch_all(&mut **db).await { Ok(v) => v, Err(error) => { - println!("Some error while getting players : {error}"); + error!("Some error while getting players : {error}"); Vec::::new() } } @@ -85,7 +85,7 @@ pub async fn update_week(week: u8, raw_intro: Form, 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!("/")); + return Redirect::to(uri!(week(week))); } let mut options = Options::empty(); @@ -113,7 +113,7 @@ pub async fn update_week(week: u8, raw_intro: Form, } }; - Redirect::to(uri!("/")) + Redirect::to(uri!(week(week))) } #[post("//set_last")] diff --git a/templates/index.html.tera b/templates/index.html.tera index cd11ae4..c2f3afa 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -42,7 +42,7 @@ {% if user.logged_in == true %}

Connecté en tant que {{ user.name }}

{% else %} - + From 5ec38ee44f20fa61d89876be465969525eb6f01e Mon Sep 17 00:00:00 2001 From: trotFunky Date: Fri, 26 Jul 2024 01:37:17 +0100 Subject: [PATCH 18/42] v1.2.0: Update production version Main changes are the week handling, proper redirections, a bunch of fixes and small adjustments, not displaying the graph until all votes and the week changed. --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d10f706..5636714 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -578,7 +578,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fabula_votes_server" -version = "1.1.1" +version = "1.2.0" dependencies = [ "argon2", "blake2", diff --git a/Cargo.toml b/Cargo.toml index e316357..c900b9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "fabula_votes_server" license = "MPL-2.0" readme = "README.md" authors = ["trotFunky"] -version = "1.1.1" +version = "1.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From 4e1b13dc85ac0be1c9d71edb6e83e1a623c3680a Mon Sep 17 00:00:00 2001 From: trotFunky Date: Fri, 26 Jul 2024 11:29:24 +0100 Subject: [PATCH 19/42] vote: Fix logic to hide graph if week is active The goal is to not display the graph until the active week has been changed, but the logic retuned early if it wasn't. Simplify the query and check directly if the current week is the last one, if so do not show the graph. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/vote.rs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5636714..df623d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -578,7 +578,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fabula_votes_server" -version = "1.2.0" +version = "1.2.1" dependencies = [ "argon2", "blake2", diff --git a/Cargo.toml b/Cargo.toml index c900b9a..2ec545f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "fabula_votes_server" license = "MPL-2.0" readme = "README.md" authors = ["trotFunky"] -version = "1.2.0" +version = "1.2.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/vote.rs b/src/vote.rs index f3becde..6795167 100644 --- a/src/vote.rs +++ b/src/vote.rs @@ -113,8 +113,7 @@ pub async fn fetch_vote_data(week: u8, mut db: Connection) -> Opti let vote_count = raw_votes.iter().fold(0, |count, votes| {count + votes.votes}); // Only show the graph if we have all the votes and this is not the last week. // FIXME: Make the 42 not hardcoded - if vote_count < 42 || week != sqlx::query_scalar("SELECT number from Weeks WHERE number == $1 AND is_last_week == 1;") - .bind(week) + if vote_count < 42 || week == sqlx::query_scalar("SELECT number from Weeks WHERE is_last_week == 1;") .fetch_optional(&mut **db) .await.unwrap_or(Some(0)).unwrap_or(0) { return None; From ba98c3be841b0188f970753e18f16000af49ef03 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Fri, 26 Jul 2024 17:55:39 +0100 Subject: [PATCH 20/42] index: Remove the form if all votes were cast Currently, if all votes are cast and the week is locked the selections are disabled but the form and button still exist and might cause confusion. Remove them if all votes are cast and we are not on the last week anymore. --- templates/index.html.tera | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/templates/index.html.tera b/templates/index.html.tera index c2f3afa..d6edfa3 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -36,6 +36,9 @@ {% set next_arrow_chara = '⟹' %} {% endif %} +{# Remove the form if all votes are locked, to reduce confusion. #} +{% set lock_truth_form = user.votes | length + 1 == truths | length and week_data.is_last_week != true %} +

{{ title }}

@@ -76,7 +79,7 @@ {% endif %}
- {% if user.logged_in == true and user.is_admin == false %} + {% if user.logged_in == true and user.is_admin == false and not lock_truth_form %}
{% endif %} @@ -101,7 +104,7 @@ {% endif %} {% endfor %} - {% if user.logged_in == true and user.is_admin == false %} + {% if user.logged_in == true and user.is_admin == false and not lock_truth_form %}
+
{% else %}
diff --git a/templates/truth.html.tera b/templates/weeks/truth.html.tera similarity index 100% rename from templates/truth.html.tera rename to templates/weeks/truth.html.tera diff --git a/templates/truth_editor.html.tera b/templates/weeks/truth_editor.html.tera similarity index 100% rename from templates/truth_editor.html.tera rename to templates/weeks/truth_editor.html.tera From b1f37a4e4af611502b66218f125c6f4cd0b4dd94 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Sat, 27 Jul 2024 23:16:19 +0100 Subject: [PATCH 29/42] templates: Make the index a class The index is a full HTML page with some boilerplate that would be needed in all pages deviating from the truth list, specifically the head and general structure. Make the core structure a base template, rebuild the week index page inheriting from it. Change which template is used by the route accordingly. --- src/week.rs | 4 +- static_files/style.css | 2 +- templates/base_page.html.tera | 36 ++++++++ templates/index.html.tera | 142 -------------------------------- templates/weeks/index.html.tera | 120 +++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 145 deletions(-) create mode 100644 templates/base_page.html.tera delete mode 100644 templates/index.html.tera create mode 100644 templates/weeks/index.html.tera diff --git a/src/week.rs b/src/week.rs index 8744ce2..5168b1c 100644 --- a/src/week.rs +++ b/src/week.rs @@ -53,7 +53,7 @@ pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<' } }; - Template::render("index", context! { + Template::render("weeks/index", context! { week_data: week_data, truths: truths, user: user, @@ -70,7 +70,7 @@ pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<' } }; - Template::render("index", context! { + Template::render("weeks/index", context! { week_data: week_data, truths: truths, user: user, diff --git a/static_files/style.css b/static_files/style.css index edc39a7..ddb3d5c 100644 --- a/static_files/style.css +++ b/static_files/style.css @@ -5,7 +5,7 @@ margin-right: 2em; } -.page_body { +.truth_page_body { display: flex; flex-direction: row; justify-content: space-between; diff --git a/templates/base_page.html.tera b/templates/base_page.html.tera new file mode 100644 index 0000000..42f0895 --- /dev/null +++ b/templates/base_page.html.tera @@ -0,0 +1,36 @@ + + +{% set title = "Vérités Fabula Ultima" %} + + + {{ title }} + + + {% block scripts %} + {% endblock %} + + + +{% block top_bar %} +
+

{{ title }}

+ {% if user.logged_in == true %} + + {% else %} + + {% endif %} +
+{% endblock %} + +{% block body %} +{% endblock %} + + + diff --git a/templates/index.html.tera b/templates/index.html.tera deleted file mode 100644 index 2e7a831..0000000 --- a/templates/index.html.tera +++ /dev/null @@ -1,142 +0,0 @@ - - -{% set title = "Vérités Fabula Ultima" %} - - - {{ title }} - - - {% if user.logged_in == true and not user.is_admin %} - - {% endif %} - - - - -{#{% import "week_change_arrows" as week_macro %}#} -{# For some reason the import does not work ? Figure it out at some point... #} -{%- macro display(display_character, to, enabled) -%} - {%- set class = "week_change" -%} - {%- if enabled == true %} - {% set target = ("href=/" ~ to) %} - {%- else -%} - {% set class = class ~ " week_change_hidden" -%} - {% set target = "" %} - {%- endif -%} - {%- if enabled == true -%}{{- display_character -}}{%- endif -%} -{%- endmacro display -%} - - -{% set back_arrow_enabled = week_data.number > 1 %} -{% set next_arrow_enabled = (week_data.is_last_week != true or user.is_admin == true) %} -{% set next_arrow_href = (week_data.number + 1) %} -{% if user.is_admin == true %} - {% set next_arrow_href = next_arrow_href ~ "/create" %} - {% set next_arrow_chara = '⥅' %} -{% else %} - {% set next_arrow_chara = '⟹' %} -{% endif %} - -{# Remove the form if all votes are locked, to reduce confusion. #} -{% set lock_truth_form = user.votes | length + 1 == truths | length and week_data.is_last_week != true %} - - -
-

{{ title }}

- {% if user.logged_in == true %} - - {% else %} - - {% endif %} -
- -

{{- self::display(display_character='⟸', to=(week_data.number - 1), enabled=back_arrow_enabled) }} - Semaine {{ week_data.number }} - {{- self::display(display_character=next_arrow_chara, to=next_arrow_href, enabled=next_arrow_enabled) -}}

-
-
- {% if user.is_admin == true and week_data.is_last_week != true %} -
- -
- {% endif %} -
- {{ week_data.rendered_text | safe }} - {%- if user.is_admin == true -%} -
-
- - -
- {% endif %} -
- {% if user.logged_in == true and user.is_admin == false and not lock_truth_form %} -
- {% endif %} - - {# Truths start at 1 but the array starts at 0 #} - {% set index_delta = 1 %} - {% for truth in truths %} - {# - The truths are in an ordered array, but one of them might be the user's. - In this case, we need to stop the array index from incrementing if the current - truth is the user's, as they cannot have voted for themselves, leading to one - less votes than there are truths. - #} - {%- if truth.author_id == user.id -%} - {%- set_global index_delta = 2 -%} - {% endif %} - {% set truth_index = truth.number - index_delta %} - - {% if user.is_admin == true %} - {% include "weeks/editable_truth" %} - {% else %} - {% include "weeks/truth" %} - {% endif %} - {% endfor %} - - {% if user.logged_in == true and user.is_admin == false and not lock_truth_form %} -
- -
- {% endif %} - - {# If admin, show an additional box for creating a new Truth. #} - {% if user.is_admin == true %} -
-

Nouvelle vérité

-
- {% include "weeks/truth_editor" %} -
-
- {% endif %} -
- -
-
- -
-
-
- - - diff --git a/templates/weeks/index.html.tera b/templates/weeks/index.html.tera new file mode 100644 index 0000000..ddf8c70 --- /dev/null +++ b/templates/weeks/index.html.tera @@ -0,0 +1,120 @@ +{% extends "base_page" %} + +{% block scripts %} + {% if user.logged_in == true and not user.is_admin %} + + {% endif %} + + +{% endblock %} + +{#{% import "week_change_arrows" as week_macro %}#} +{# For some reason the import does not work ? Figure it out at some point... #} +{%- macro display(display_character, to, enabled) -%} + {%- set class = "week_change" -%} + {%- if enabled == true %} + {% set target = ("href=/" ~ to) %} + {%- else -%} + {% set class = class ~ " week_change_hidden" -%} + {% set target = "" %} + {%- endif -%} + {%- if enabled == true -%}{{- display_character -}}{%- endif -%} +{%- endmacro display -%} + +{# Remove the form if all votes are locked, to reduce confusion. #} +{% set lock_truth_form = user.votes | length + 1 == truths | length and week_data.is_last_week != true %} + +{% block body %} + + {# Apparently needs to be inside the block ? #} + {% set back_arrow_enabled = week_data.number > 1 %} + {% set next_arrow_enabled = (week_data.is_last_week != true or user.is_admin == true) %} + {% set next_arrow_href = (week_data.number + 1) %} + {% if user.is_admin == true %} + {% set next_arrow_href = next_arrow_href ~ "/create" %} + {% set next_arrow_chara = '⥅' %} + {% else %} + {% set next_arrow_chara = '⟹' %} + {% endif %} + +

{{- self::display(display_character='⟸', to=(week_data.number - 1), enabled=back_arrow_enabled) }} + Semaine {{ week_data.number }} + {{- self::display(display_character=next_arrow_chara, to=next_arrow_href, enabled=next_arrow_enabled) -}}

+
+
+ {% if user.is_admin == true and week_data.is_last_week != true %} +
+ +
+ {% endif %} +
+ {{ week_data.rendered_text | safe }} + {%- if user.is_admin == true -%} +
+
+ + +
+ {% endif %} +
+ {% if user.logged_in == true and user.is_admin == false and not lock_truth_form %} +
+ {% endif %} + + {# Truths start at 1 but the array starts at 0 #} + {% set index_delta = 1 %} + {% for truth in truths %} + {# + The truths are in an ordered array, but one of them might be the user's. + In this case, we need to stop the array index from incrementing if the current + truth is the user's, as they cannot have voted for themselves, leading to one + less votes than there are truths. + #} + {%- if truth.author_id == user.id -%} + {%- set_global index_delta = 2 -%} + {% endif %} + {% set truth_index = truth.number - index_delta %} + + {% if user.is_admin == true %} + {% include "weeks/editable_truth" %} + {% else %} + {% include "weeks/truth" %} + {% endif %} + {% endfor %} + + {% if user.logged_in == true and user.is_admin == false and not lock_truth_form %} +
+ +
+ {% endif %} + + {# If admin, show an additional box for creating a new Truth. #} + {% if user.is_admin == true %} +
+

Nouvelle vérité

+
+ {% include "weeks/truth_editor" %} +
+
+ {% endif %} +
+ +
+
+ +
+
+
+{% endblock %} From 1419bb6d51a0e1c3e2dd623b954b15b4c0d9b324 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Sat, 27 Jul 2024 23:20:20 +0100 Subject: [PATCH 30/42] tempates/base: Change language, update title Now that we have the name of the world, we can show it in the title. The base I used supposed an english language page, which is incorrect here. Set language as French. --- templates/base_page.html.tera | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/base_page.html.tera b/templates/base_page.html.tera index 42f0895..f56242b 100644 --- a/templates/base_page.html.tera +++ b/templates/base_page.html.tera @@ -1,6 +1,6 @@ - -{% set title = "Vérités Fabula Ultima" %} + +{% set title = "Vérités Nova Borealis" %} {{ title }} From 1b4a934398c355fffe22a13ac00ca73b11063797 Mon Sep 17 00:00:00 2001 From: trotFunky Date: Sun, 28 Jul 2024 14:36:52 +0100 Subject: [PATCH 31/42] auth: Split off vote data from the user Now that the application is going to have multiple pages, vote data makes no sense to keep with the user. The user struct will be used everywhere to check for authentication, which is not the case for previous votes. Create a new struct and function in src/vote.rs to retrieve existing votes and use them in places where user.votes was used previously. Remove vote-related code from src/auth.rs and the week number dependence that it required. --- README.md | 1 + src/auth.rs | 23 ++--------------------- src/truth.rs | 4 ++-- src/vote.rs | 31 ++++++++++++++++++++++++++++--- src/week.rs | 15 ++++++++++----- templates/weeks/index.html.tera | 4 ++-- templates/weeks/truth.html.tera | 4 ++-- 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index e289d5b..949ac31 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ A list of things that could be implemented/added to the application, some of the - [x] Use fairings for the different elements - [ ] Use guards for User calls ? - [ ] Use SQLite Row ID for User IDs rather than regular IDs, for randomness ? + - [x] Split user from vote data # Dependencies diff --git a/src/auth.rs b/src/auth.rs index 34c0bec..672b79d 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -9,7 +9,7 @@ use argon2::{Argon2, PasswordHash, PasswordVerifier}; use blake2::{Blake2b512, Digest}; use blake2::digest::FixedOutput; use rocket::fairing::AdHoc; -use crate::database_records::{AuthTokens, PlayerLoginInfo, Vote}; +use crate::database_records::{AuthTokens, PlayerLoginInfo}; use crate::{database, week}; use database::Db; @@ -21,11 +21,9 @@ pub struct User { pub is_admin: bool, pub id: u16, pub name: String, - pub has_week_vote: bool, - pub votes: Vec } -pub async fn get_user(week: u8, db: &mut Connection, cookies: &CookieJar<'_>) -> User { +pub async fn get_user(db: &mut Connection, cookies: &CookieJar<'_>) -> User { let auth_token: Option = match cookies.get_private("auth_token") { Some(cookie) => Some(cookie.value().to_string()), None => None @@ -87,27 +85,12 @@ pub async fn get_user(week: u8, db: &mut Connection, cookies: &CookieJar<'_> (String::new(), false) }; - // TODO: Move to src/vote.rs - let votes: Vec = if logged_in && !is_admin { - sqlx::query_as("SELECT Votes.* FROM Votes JOIN Truths ON Votes.truth_id == Truths.id AND Truths.week == $1 WHERE voter_id == $2 ORDER BY Truths.number;") - .bind(week) - .bind(&id_str) - .fetch_all(&mut ***db).await.unwrap_or_else(|error| { - error!("Error while getting votes : {error}"); - Vec::::new() - }) - } else { - Vec::::new() - }; - if logged_in { User { logged_in, is_admin, id: id_str.parse::().unwrap(), name, - has_week_vote: if votes.is_empty() { false } else { true }, - votes } } else { User { @@ -115,8 +98,6 @@ pub async fn get_user(week: u8, db: &mut Connection, cookies: &CookieJar<'_> is_admin: false, id: 0, name, - has_week_vote: false, - votes } } } diff --git a/src/truth.rs b/src/truth.rs index b9df46a..f3b6add 100644 --- a/src/truth.rs +++ b/src/truth.rs @@ -18,7 +18,7 @@ pub struct TruthUpdateForm { #[post("//edit/", data="
")] pub async fn edit_truth(week: u8, truth_number: u8, form: Form, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { - let user = auth::get_user(week, &mut db, cookies).await; + let user = auth::get_user(&mut db, cookies).await; if !user.is_admin { cookies.add(("toast_error", "Vous n'avez pas la permission de changer la vérité.")); return Redirect::to(uri!(week::week(week))); @@ -57,7 +57,7 @@ pub async fn edit_truth(week: u8, truth_number: u8, form: Form, #[post("//new_truth", data="")] pub async fn create_truth(week: u8, form: Form, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { - let user = auth::get_user(week, &mut db, cookies).await; + let user = auth::get_user(&mut db, cookies).await; if !user.is_admin { cookies.add(("toast_error", "Vous n'avez pas la permission d'ajouter de vérité.")); return Redirect::to(uri!(week::week(week))); diff --git a/src/vote.rs b/src/vote.rs index ff1e555..550707c 100644 --- a/src/vote.rs +++ b/src/vote.rs @@ -12,6 +12,29 @@ use rocket_db_pools::{sqlx, Connection}; use crate::{auth, database, week}; use crate::database_records::{Vote, VotingData}; +#[derive(Serialize, Deserialize)] +#[serde(crate = "rocket::serde")] +pub struct WeeklyUserVotes { + pub has_week_vote: bool, + pub votes: Vec +} + +pub async fn get_weekly_user_votes(week: u8, user: &auth::User, db: &mut Connection) -> WeeklyUserVotes { + let votes: Vec = if user.logged_in && !user.is_admin { + sqlx::query_as("SELECT Votes.* FROM Votes JOIN Truths ON Votes.truth_id == Truths.id AND Truths.week == $1 WHERE voter_id == $2 ORDER BY Truths.number;") + .bind(week) + .bind(user.id) + .fetch_all(&mut ***db).await.unwrap_or_else(|error| { + error!("Error while getting votes : {error}"); + Vec::::new() + }) + } else { + Vec::::new() + }; + + WeeklyUserVotes {has_week_vote: if votes.is_empty() { false } else { true }, votes} +} + #[derive(FromForm)] pub struct VoteForm { truth_votes: HashMap @@ -20,7 +43,7 @@ pub struct VoteForm { #[post("//vote", data="")] pub async fn vote(week: u8, form: Form, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { - let user = auth::get_user(week, &mut db, cookies).await; + let user = auth::get_user(&mut db, cookies).await; if !user.logged_in { cookies.add(("toast_error", "Vous n'avez pas la permission de changer de vote.")); @@ -37,9 +60,11 @@ pub async fn vote(week: u8, form: Form, } ); + let existing_votes = get_weekly_user_votes(week, &user, &mut db).await; + let mut had_error = false; for (truth_id, voted_id) in filtered_votes { - match user.votes.iter().find(|vote: &&Vote| {vote.truth_id == *truth_id}) { + match existing_votes.votes.iter().find(|vote: &&Vote| {vote.truth_id == *truth_id}) { Some(vote) => { if *voted_id == vote.voted_id { continue; @@ -97,7 +122,7 @@ pub struct VoteData { // TODO: Cache vote count ? Maintain in state ? #[get("//votes", format = "application/json")] pub async fn fetch_vote_data(week: u8, mut db: Connection, cookies: &CookieJar<'_>) -> Option> { - let user = auth::get_user(week, &mut db, cookies).await; + let user = auth::get_user(&mut db, cookies).await; let raw_votes: Vec = sqlx::query_as(" SELECT Players.name as votes_for, Truths.number as truth_number, count(*) as votes FROM Votes JOIN Players ON Votes.voted_id == Players.id diff --git a/src/week.rs b/src/week.rs index 5168b1c..06bbbb6 100644 --- a/src/week.rs +++ b/src/week.rs @@ -7,14 +7,15 @@ 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, vote}; use crate::auth::User; use crate::database::Db; use crate::database_records::{DisplayTruth, Player, Truth, Week}; +use crate::vote::WeeklyUserVotes; #[get("/")] pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<'_>) -> Template { - let user: User = auth::get_user(week_number, &mut db, cookies).await; + let user: User = auth::get_user(&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") @@ -41,6 +42,8 @@ pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<' } }; + let vote_data: WeeklyUserVotes = vote::get_weekly_user_votes(week_number,&user, &mut db).await; + // FIXME : This is fucking *trash* but fucking hell mate if user.is_admin { let truths: Vec = match sqlx::query_as("SELECT * FROM Truths WHERE week == $1 ORDER BY number") @@ -58,6 +61,7 @@ pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<' truths: truths, user: user, other_players: other_players, + vote_data: vote_data }) } else { let truths: Vec = match sqlx::query_as("SELECT id, number, author_id, rendered_text FROM Truths WHERE week == $1 ORDER BY number") @@ -75,6 +79,7 @@ pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<' truths: truths, user: user, other_players: other_players, + vote_data: vote_data }) } } @@ -82,7 +87,7 @@ pub async fn week(week_number: u8, mut db: Connection, cookies: &CookieJar<' #[post("//edit", data="")] pub async fn update_week(week: u8, raw_intro: Form, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { - let user = auth::get_user(week, &mut db, cookies).await; + let user = auth::get_user(&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))); @@ -118,7 +123,7 @@ pub async fn update_week(week: u8, raw_intro: Form, #[post("//set_last")] pub async fn set_last_week(week: u8, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { - let user = auth::get_user(week, &mut db, cookies).await; + let user = auth::get_user(&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))); @@ -173,7 +178,7 @@ pub async fn set_last_week(week: u8, mut db: Connection, cookies: &CookieJar #[get("//create")] pub async fn create_week(week: u8, mut db: Connection, cookies: &CookieJar<'_>) -> Redirect { - let user = auth::get_user(week, &mut db, cookies).await; + let user = auth::get_user(&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))); diff --git a/templates/weeks/index.html.tera b/templates/weeks/index.html.tera index ddf8c70..b3527d5 100644 --- a/templates/weeks/index.html.tera +++ b/templates/weeks/index.html.tera @@ -22,7 +22,7 @@ {%- endmacro display -%} {# Remove the form if all votes are locked, to reduce confusion. #} -{% set lock_truth_form = user.votes | length + 1 == truths | length and week_data.is_last_week != true %} +{% set lock_truth_form = vote_data.votes | length + 1 == truths | length and week_data.is_last_week != true %} {% block body %} @@ -91,7 +91,7 @@ {% if user.logged_in == true and user.is_admin == false and not lock_truth_form %}
- - {% else %} - - {% endif %} +
+

{{ title }}

+ +
+
+ {% block top_bar_side %} +
+ {% if user.logged_in == true %} + + {% else %} + + {% endif %} +
+ {% endblock %} +
{% endblock %} diff --git a/templates/tags/filtered_truths.html.tera b/templates/tags/filtered_truths.html.tera new file mode 100644 index 0000000..ad2ffb9 --- /dev/null +++ b/templates/tags/filtered_truths.html.tera @@ -0,0 +1,28 @@ +{% extends "base_page" %} + +{% block top_bar_side %} +{% endblock %} + +{% block body %} + {% if tags | length == 0 %} +

Ensemble des vérités à ce jour

+ {% elif tags | length == 1 %} +

Vérités correponsdantes au thème

+ {% else %} +

Vérités correponsdantes aux thèmes

+ {% endif %} + +
+ {% for tag in tags %} + {{ tag.name }} + {% endfor %} +
+ + {% for truth in truths %} +
+

Semaine {{ truth.week }} - Vérité {{ truth.number }}

+

{{ truth.rendered_text | safe }}

+
+ {% endfor %} +{% endblock %} diff --git a/templates/tags/index.html.tera b/templates/tags/index.html.tera new file mode 100644 index 0000000..5e423d4 --- /dev/null +++ b/templates/tags/index.html.tera @@ -0,0 +1,42 @@ +{% extends "base_page" %} + +{% block top_bar_side %} +{% endblock %} + +{% block body %} +

Liste des thèmes de Vérité

+ +
+ {% for tag in tags %} +
+ +
+ {% endfor %} +
+ + + {% if user.is_admin %} +
+ +

Éditer les thèmes

+ +
+ {% for tag in tags %} +
+ + + + +
+ {% endfor %} +
+ +
+
+ + +
+ +
+ {% endif %} +{% endblock %} diff --git a/templates/weeks/editable_truth.tera b/templates/weeks/editable_truth.tera index 501302a..3c2c968 100644 --- a/templates/weeks/editable_truth.tera +++ b/templates/weeks/editable_truth.tera @@ -1,8 +1,30 @@

Vérité {{ truth.number }}

{{ truth.rendered_text | safe }}

+
+ {% for tag in truth.tags %} +
+ +
+ + {{ tag.name }} + + {% endfor %} +

-
+ {% include "weeks/truth_editor" %}
+
+ + +
diff --git a/templates/weeks/truth.html.tera b/templates/weeks/truth.html.tera index ca52998..5a420e6 100644 --- a/templates/weeks/truth.html.tera +++ b/templates/weeks/truth.html.tera @@ -7,6 +7,12 @@

Vérité {{ truth.number }}

{{ truth.rendered_text | safe }}

+
+
+ {% for tag in truth.tags %} + {{ tag.name }} + {% endfor %} +
{% if user.logged_in %}