From 8341e64dfdcca906798bfc2d00c94974091177ad Mon Sep 17 00:00:00 2001 From: Awstin Date: Thu, 19 Dec 2024 07:32:10 -0500 Subject: [PATCH] Added the new link form and processing --- Cargo.lock | 149 ++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 8 +-- src/auth.rs | 9 ++- src/database/article.rs | 9 ++- src/database/link.rs | 10 ++- src/html/admin.rs | 60 +++++++++++++--- src/html/garden.rs | 3 +- src/html/mod.rs | 9 +++ src/html/root.rs | 13 ++-- templates/admin.html | 34 +++++++-- templates/signup.html | 2 +- 11 files changed, 261 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0abd391..56b07b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,6 +9,7 @@ dependencies = [ "askama", "axum", "bb8", + "chrono", "clap", "cookie", "futures-util", @@ -18,7 +19,6 @@ dependencies = [ "rand_core", "serde", "sqlx", - "time", "tokio", "tower", "tower-http", @@ -69,6 +69,21 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.14" @@ -310,6 +325,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -334,6 +355,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.52.5", +] + [[package]] name = "clap" version = "4.5.13" @@ -396,6 +432,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -463,7 +505,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", - "serde", ] [[package]] @@ -821,6 +862,29 @@ dependencies = [ "want", ] +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.5.0" @@ -862,6 +926,16 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "js-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1640,6 +1714,7 @@ dependencies = [ "atoi", "byteorder", "bytes", + "chrono", "crc", "crossbeam-queue", "either", @@ -1665,7 +1740,6 @@ dependencies = [ "smallvec", "sqlformat", "thiserror", - "time", "tokio", "tokio-stream", "tracing", @@ -1723,6 +1797,7 @@ dependencies = [ "bitflags 2.5.0", "byteorder", "bytes", + "chrono", "crc", "digest", "dotenvy", @@ -1750,7 +1825,6 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror", - "time", "tracing", "whoami", ] @@ -1765,6 +1839,7 @@ dependencies = [ "base64", "bitflags 2.5.0", "byteorder", + "chrono", "crc", "dotenvy", "etcetera", @@ -1789,7 +1864,6 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror", - "time", "tracing", "whoami", ] @@ -1801,6 +1875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" dependencies = [ "atoi", + "chrono", "flume", "futures-channel", "futures-core", @@ -1812,7 +1887,6 @@ dependencies = [ "percent-encoding", "serde", "sqlx-core", - "time", "tracing", "url", "urlencoding", @@ -2248,6 +2322,60 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" +[[package]] +name = "wasm-bindgen" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.60", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + [[package]] name = "webpki-roots" version = "0.25.4" @@ -2286,6 +2414,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index a4c4e2d..b2b3f96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" askama = "0.12.1" axum = "0.6" bb8 = "0.8.3" +chrono = { version = "0.4.38", features = ["alloc", "serde"] } clap = { version = "4.5.13", features = ["derive"] } cookie = "0.18.1" futures-util = "0.3.30" @@ -18,12 +19,11 @@ rand_chacha = "0.3.1" rand_core = "0.6.4" serde = { version = "1.0.197", features = ["derive"] } sqlx = { version = "0.7.4", features = [ - "runtime-tokio-rustls", - "postgres", - "time", + "chrono", "macros", + "postgres", + "runtime-tokio-rustls", ] } -time = { version = "0.3.36", features = ["macros", "serde"] } tokio = { version = "1.35.0", features = ["full"] } tower = "0.4.13" tower-http = { version = "0.4.4", features = ["fs"] } diff --git a/src/auth.rs b/src/auth.rs index f3e1bf3..6847b53 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -79,10 +79,7 @@ impl AuthState { .unwrap(); if let Some((id, admin)) = user { - *store = Some(UserInfo { - user_id: id, - admin - }); + *store = Some(UserInfo { user_id: id, admin }); } } store.as_ref() @@ -141,7 +138,9 @@ pub async fn post_signup( return Err(error_page(&SignupError::PasswordsDoNotMatch)); } - let user_id = create_user(&signup.username, &signup.password, &pool).await.unwrap(); + let user_id = create_user(&signup.username, &signup.password, &pool) + .await + .unwrap(); let session_token = new_session(&pool, random, user_id).await; diff --git a/src/database/article.rs b/src/database/article.rs index cc0b158..11f17c6 100644 --- a/src/database/article.rs +++ b/src/database/article.rs @@ -7,7 +7,7 @@ use std::{ fs::{self, metadata}, path::PathBuf, }; -use time::{macros::format_description, Date}; +use chrono::NaiveDate; #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] pub struct Article { @@ -17,7 +17,7 @@ pub struct Article { pub content: String, pub previous: Option, pub next: Option, - pub date: Date, + pub date: NaiveDate, pub description: Option, } @@ -30,7 +30,7 @@ impl Article { let mut title: Option = None; let mut previous: Option = None; let mut next: Option = None; - let mut date: Option = None; + let mut date: Option = None; let mut description: Option = None; let mut lines: Vec = super::read_lines(file_name); lines.reverse(); @@ -45,9 +45,8 @@ impl Article { } else if line.contains("next: ") { next = Some(line.clone().replace("next: ", "")); } else if line.contains("date: ") { - let format = format_description!("[year]-[month]-[day]"); date = Some( - Date::parse(&line.clone().replace("date: ", ""), format).expect("not a date"), + NaiveDate::parse_from_str(&line.clone().replace("date: ", ""), "%Y-%m-%d").expect("not a date"), ); } else if line.contains("description: ") { description = Some(line.clone().replace("description: ", "")); diff --git a/src/database/link.rs b/src/database/link.rs index 5b9f971..4f4bae6 100644 --- a/src/database/link.rs +++ b/src/database/link.rs @@ -1,9 +1,9 @@ use crate::database::PsqlData; +use chrono::NaiveDate; use futures_util::TryStreamExt; use serde::{Deserialize, Serialize}; use sqlx::{self, postgres::PgPool, Pool, Postgres}; use std::{error::Error, path::Path}; -use time::{macros::format_description, Date}; #[derive(Debug, Serialize, Deserialize, PartialEq, PartialOrd, Clone, sqlx::Type)] #[sqlx(type_name = "link_type", rename_all = "lowercase")] @@ -20,7 +20,7 @@ pub struct Link { pub title: String, pub author: String, pub link_type: LinkType, - pub date_added: Date, + pub date_added: NaiveDate, } impl Link { @@ -30,7 +30,7 @@ impl Link { let mut title: Option = None; let mut author: Option = None; let mut link_type: Option = None; - let mut date_added: Option = None; + let mut date_added: Option = None; while lines.len() > 0 { let line: String = lines.pop().expect("Something went terribly wrong here"); if line.contains("url: ") { @@ -45,10 +45,8 @@ impl Link { _ => LinkType::ARTICLE, }); } else if line.contains("date_added: ") { - let format = format_description!("[year]-[month]-[day]"); date_added = Some( - Date::parse(&line.clone().replace("date_added: ", ""), format) - .expect("not a date"), + NaiveDate::parse_from_str(&line.clone().replace("date: ", ""), "%Y-%m-%d").expect("not a date"), ); } else if line.contains("description: ") { description = Some(line.clone().replace("description: ", "")); diff --git a/src/html/admin.rs b/src/html/admin.rs index 0925320..6870eee 100644 --- a/src/html/admin.rs +++ b/src/html/admin.rs @@ -1,20 +1,33 @@ +use core::panic; + use axum::{ response::{IntoResponse, Redirect, Response}, - routing::{get, Router}, - Extension, + routing::{get, post, Router}, + Extension, Form, +}; +use chrono::Local; +use sqlx::PgPool; + +use crate::{ + auth::{AuthState, UserInfo}, + database::{ + link::{Link, LinkType}, + PsqlData, + }, }; -use crate::auth::{AuthState, UserInfo}; - -use super::templates::{AdminTemplate, HtmlTemplate}; +use super::{ + templates::{AdminTemplate, HtmlTemplate}, + NewLink, +}; pub fn get_router() -> Router { - Router::new().route("/", get(get_admin)) + Router::new() + .route("/", get(get_admin)) + .route("/new_link", post(new_link)) } -pub async fn get_admin( - Extension(mut current_user): Extension, -) -> Response { +pub async fn get_admin(Extension(mut current_user): Extension) -> Response { let user_info: UserInfo = current_user.get_user().await.unwrap().clone(); if !user_info.admin { return Redirect::to("/").into_response(); @@ -22,6 +35,35 @@ pub async fn get_admin( HtmlTemplate(AdminTemplate {}).into_response() } +pub async fn new_link( + Extension(mut current_user): Extension, + Extension(pool): Extension, + Form(new_item): Form, +) -> Response { + let user_info: UserInfo = current_user.get_user().await.unwrap().clone(); + if !user_info.admin { + return Redirect::to("/").into_response(); + } + + let new_link: Link = Link { + id: 0, + url: new_item.url, + title: new_item.title, + author: new_item.author, + link_type: match &*new_item.link_type { + "article" => LinkType::ARTICLE, + "blog" => LinkType::BLOG, + _ => panic!("Not a proper link type"), + }, + description: get_trimmed_string(new_item.description), + date_added: Local::now().date_naive(), + }; + + let _ = new_link.insert(&pool).await; + + Redirect::to("/admin").into_response() +} + fn get_trimmed_string(input: String) -> Option { if input.trim().is_empty() { None diff --git a/src/html/garden.rs b/src/html/garden.rs index a89c2f1..3542d15 100644 --- a/src/html/garden.rs +++ b/src/html/garden.rs @@ -4,7 +4,8 @@ use axum::{ }; use super::templates::{ - ArchServerTemplate, BooksTemplate, CookingTemplate, CreationTemplate, EdgeDetectionTemplate, GardenTemplate, HtmlTemplate, TakTemplate, TechnologyTemplate, TimeTemplate + ArchServerTemplate, BooksTemplate, CookingTemplate, CreationTemplate, EdgeDetectionTemplate, + GardenTemplate, HtmlTemplate, TakTemplate, TechnologyTemplate, TimeTemplate, }; pub fn get_router() -> Router { diff --git a/src/html/mod.rs b/src/html/mod.rs index c8b2e78..753a20e 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -18,3 +18,12 @@ pub struct Signup { pub password: String, pub confirm_password: String, } + +#[derive(Deserialize)] +pub struct NewLink { + pub url: String, + pub description: String, + pub title: String, + pub author: String, + pub link_type: String, +} diff --git a/src/html/root.rs b/src/html/root.rs index 2495bf9..e66e79c 100644 --- a/src/html/root.rs +++ b/src/html/root.rs @@ -1,4 +1,4 @@ -use std:: sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex}; use axum::{ http::{Response, StatusCode}, @@ -22,9 +22,14 @@ use crate::{ }; use super::{ - admin, blog::{self, get_articles_date_sorted}, garden, templates::{ - AboutTemplate, AiTemplate, BlogrollTemplate, ContactTemplate, GiftsTemplate, HomeTemplate, HtmlTemplate, InterestsTemplate, LinksPageTemplate, LoginTemplate, NowTemplate, ResumeTemplate, SignupTemplate, UsesTemplate, WorkTemplate - } + admin, + blog::{self, get_articles_date_sorted}, + garden, + templates::{ + AboutTemplate, AiTemplate, BlogrollTemplate, ContactTemplate, GiftsTemplate, HomeTemplate, + HtmlTemplate, InterestsTemplate, LinksPageTemplate, LoginTemplate, NowTemplate, + ResumeTemplate, SignupTemplate, UsesTemplate, WorkTemplate, + }, }; pub fn get_router(pool: PgPool) -> Router { diff --git a/templates/admin.html b/templates/admin.html index e5b804f..7b6c19b 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -4,9 +4,35 @@ {% block content %}

Admin

- + +
+

New Link

+
+

+ + +

+

+ + +

+

+ + +

+

+ + +

+

+ +
+ +

+
-

- My admin page -

{% endblock %} diff --git a/templates/signup.html b/templates/signup.html index 136ef2d..c5fdc92 100644 --- a/templates/signup.html +++ b/templates/signup.html @@ -23,7 +23,7 @@

- +