From bfb63afa7e996f7d920788dbe123c5353f271a85 Mon Sep 17 00:00:00 2001 From: SadlyNotSappho Date: Fri, 29 Mar 2024 11:39:44 -0700 Subject: [PATCH] start working on posts --- Cargo.lock | 16 +++ Cargo.toml | 1 + src/main.rs | 7 ++ src/tables.rs | 295 ++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 275 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f91df14..49dc624 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -597,6 +597,7 @@ version = "0.1.0" dependencies = [ "base64", "image", + "markdown", "rand", "rand_hc", "regex", @@ -1095,6 +1096,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "markdown" +version = "1.0.0-alpha.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0f0025e8c0d89b84d6dc63e859475e40e8e82ab1a08be0a93ad5731513a508" +dependencies = [ + "unicode-id", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2589,6 +2599,12 @@ version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +[[package]] +name = "unicode-id" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" + [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index 8945372..38b046b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] base64 = "0.21.7" image = "0.24.8" +markdown = "1.0.0-alpha.16" rand = "0.8.5" rand_hc = "0.3.2" regex = "1.10.3" diff --git a/src/main.rs b/src/main.rs index e405ff1..84abd17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -626,6 +626,13 @@ async fn migrate(rocket: Rocket) -> Rocket { )) .await; + let _ = conn + .execute(sqlx::query( + "ALTER TABLE posts + ADD COLUMN IF NOT EXISTS uuid TEXT NOT NULL UNIQUE, + ADD COLUMN IF NOT EXISTS text_id TEXT NOT NULL UNIQUE", + )) + .await; rocket } diff --git a/src/tables.rs b/src/tables.rs index 82f649b..c10e589 100644 --- a/src/tables.rs +++ b/src/tables.rs @@ -17,23 +17,34 @@ pub struct Db(PgPool); #[derive(FromRow)] pub struct Post { pub id: i32, + pub uuid: String, + pub text_id: String, pub title: String, pub body: String, pub published: bool, } impl Post { - pub async fn create(mut db: Connection, title: String, body: String, published: bool) { + pub async fn create( + mut db: Connection, + title: String, /*ex: Why Trans People Deserve All Your Money*/ + body: String, /*ex: # Because we're cooler than you */ + published: bool, + uuid: String, + text_id: String, /*ex: why-trans-people-deserve-all-your-money */ + ) { match db .fetch_all( sqlx::query( r#" - INSERT INTO posts (title, body, published) - VALUES ($1, $2, $3); + INSERT INTO posts (title, body, published, uuid, text_id) + VALUES ($1, $2, $3, $4, $5); "#, ) .bind(title) .bind(body) - .bind(published), + .bind(published) + .bind(uuid) + .bind(text_id), ) .await { @@ -50,12 +61,204 @@ impl Post { .unwrap(); Post { id: res.get::("id"), + uuid: res.get::("uuid"), + text_id: res.get::("text_id"), title: res.get::("title"), body: res.get::("body"), published: res.get::("published"), } } + pub async fn get_by_uuid(mut db: Connection, uuid: String) -> Post { + let res = db + .fetch_one(sqlx::query("SELECT * FROM posts WHERE uuid = $1;").bind(uuid)) + .await + .unwrap(); + Post { + id: res.get::("id"), + uuid: res.get::("uuid"), + text_id: res.get::("text_id"), + title: res.get::("title"), + body: res.get::("body"), + published: res.get::("published"), + } + } + pub async fn get_by_text_id(mut db: Connection, text_id: String) -> Post { + let res = db + .fetch_one(sqlx::query("SELECT * FROM posts WHERE text_id = $1;").bind(text_id)) + .await + .unwrap(); + Post { + id: res.get::("id"), + uuid: res.get::("uuid"), + text_id: res.get::("text_id"), + title: res.get::("title"), + body: res.get::("body"), + published: res.get::("published"), + } + } + + pub async fn edit_body( + mut db: Connection, + id: i32, + new_body: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET body = $1 WHERE id = $2;") + .bind(new_body) + .bind(id), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } + pub async fn edit_body_by_uuid( + mut db: Connection, + uuid: String, + new_body: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET body = $1 WHERE uuid = $2;") + .bind(new_body) + .bind(uuid), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } + pub async fn edit_body_by_text_id( + mut db: Connection, + text_id: String, + new_body: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET body = $1 WHERE text_id = $2;") + .bind(new_body) + .bind(text_id), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } + pub async fn edit_title( + mut db: Connection, + id: i32, + new_title: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET title = $1 WHERE id = $2;") + .bind(new_title) + .bind(id), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } + pub async fn edit_title_by_uuid( + mut db: Connection, + uuid: String, + new_title: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET title = $1 WHERE uuid = $2;") + .bind(new_title) + .bind(uuid), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } + pub async fn edit_title_by_text_id( + mut db: Connection, + text_id: String, + new_title: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET body = $1 WHERE text_id = $2;") + .bind(new_title) + .bind(text_id), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } + pub async fn edit_text_id( + mut db: Connection, + id: i32, + new_text_id: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET text_id = $1 WHERE id = $2;") + .bind(new_text_id) + .bind(id), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } + pub async fn edit_text_id_by_uuid( + mut db: Connection, + uuid: String, + new_text_id: String, + ) -> Result<(), String> { + match db + .execute( + sqlx::query("UPDATE posts SET text_id = $1 WHERE uuid = $2;") + .bind(new_text_id) + .bind(uuid), + ) + .await + { + Ok(_) => Ok(()), + Err(why) => { + eprintln!("{why:?}"); + Err("Couldn't update post".to_string()) + } + } + } } + #[derive(FromRow, Debug)] pub struct User { pub id: i32, @@ -70,15 +273,19 @@ pub struct User { pub enum LoginStatus { InvalidToken, NotLoggedIn, - LoggedIn(User) + LoggedIn(User), } impl User { - pub async fn create(db: &mut Connection, username: &String, password: &String) -> Result { + pub async fn create( + db: &mut Connection, + username: &String, + password: &String, + ) -> Result { match Regex::new(r"[^A-Za-z0-9_]") { Ok(r) => { match r.captures(username) { - Some(_) => + Some(_) => Err("The username contains invalid characters. Only letters, numbers, and underscores are allowed.".to_string()) , None => { @@ -98,7 +305,7 @@ impl User { .bind(sha256::digest(password)), ).await { - Ok(_) => + Ok(_) => Ok("Created user.".to_string()) , Err(why) => { @@ -112,7 +319,7 @@ impl User { } Err(why) => { eprintln!("Couldn't compile name regex: {why:?}"); - Err("Couldn't compile name regex.".to_string()) + Err("Couldn't compile name regex.".to_string()) } } } @@ -226,17 +433,11 @@ impl User { pub async fn login_status(db: &mut Connection, cookies: &CookieJar<'_>) -> LoginStatus { match cookies.get_private("token") { - Some(t) => { - match User::get_by_token(db, t).await { - Some(user) => { - LoginStatus::LoggedIn(user) - }, - None => { - LoginStatus::InvalidToken - } - } + Some(t) => match User::get_by_token(db, t).await { + Some(user) => LoginStatus::LoggedIn(user), + None => LoginStatus::InvalidToken, }, - None => LoginStatus::NotLoggedIn + None => LoginStatus::NotLoggedIn, } } } @@ -262,12 +463,10 @@ impl Image { ) .await { - Ok(_) => - Ok(()) - , + Ok(_) => Ok(()), Err(why) => { eprintln!("Couldn't create database entry: {why:?}"); - Err("Couldn't create image.".to_string()) + Err("Couldn't create image.".to_string()) } } } @@ -276,26 +475,31 @@ impl Image { .fetch_one(sqlx::query("SELECT * FROM images WHERE uuid = $1;").bind(uuid)) .await { - Ok(img) => Ok(Image { - id: img.get::("id"), - uuid: img.get::("uuid"), - owner_name: img.get::("owner_name"), - }), + Ok(img) => Ok(Image { + id: img.get::("id"), + uuid: img.get::("uuid"), + owner_name: img.get::("owner_name"), + }), Err(_) => Err("Couldn't get image.".to_string()), } } - pub async fn is_owned_by(db: &mut Connection, uuid: &String, username: &String) -> Result { + pub async fn is_owned_by( + db: &mut Connection, + uuid: &String, + username: &String, + ) -> Result { match Image::get_by_uuid(db, uuid).await { - Ok(img) => { - Ok(&img.owner_name == username) - }, + Ok(img) => Ok(&img.owner_name == username), Err(why) => { eprintln!("{why:?}"); Err("couldn't get image".to_string()) } - } + } } - pub async fn get_by_username(db: &mut Connection, owner_name: &String) -> Result, String> { + pub async fn get_by_username( + db: &mut Connection, + owner_name: &String, + ) -> Result, String> { match db .fetch_all(sqlx::query("SELECT * FROM images WHERE owner_name = $1;").bind(owner_name)) .await @@ -303,27 +507,30 @@ impl Image { Ok(imgs) => { let mut res = vec![]; for img in imgs { - res.push(Image { - id: img.get::("id"), - uuid: img.get::("uuid"), - owner_name: img.get::("owner_name"), - }) + res.push(Image { + id: img.get::("id"), + uuid: img.get::("uuid"), + owner_name: img.get::("owner_name"), + }) } Ok(res) - }, + } Err(_) => Err("Couldn't get image.".to_string()), } } pub async fn delete(db: &mut Connection, uuid: &String) -> Result<(), ()> { - match db.execute(sqlx::query("DELETE FROM images WHERE uuid = $1").bind(uuid)).await { + match db + .execute(sqlx::query("DELETE FROM images WHERE uuid = $1").bind(uuid)) + .await + { Ok(rows_gone) => { eprintln!("Deleted {rows_gone:?} rows."); - Ok(()) - }, + Ok(()) + } Err(why) => { eprintln!("Couldn't remove database entry: {why:?}"); Err(()) - } + } } } }