diff --git a/imagesplan.txt b/imagesplan.txt deleted file mode 100644 index b8f9058..0000000 --- a/imagesplan.txt +++ /dev/null @@ -1,14 +0,0 @@ -GET /images/uuid.filetype DONE - -> returns the image with the correct filetype - uuid.png would return the image in png format, etc - -GET /images/by-user/username DONE - -> gets all of the images made by {username}, if you are {username}, or if you have admin. - -POST /images/create {image: "image data"} DONE - -> returns the uuid of the image, which it saves to the folder and database - -DELETE /images/uuid DONE - -> if you're the owner of the image or an admin, deletes the image. returns basic success/faliure - -images are stored in /images/uuid.png. Image::get_by_uuid(uuid) just gets the image from the folder, verifies that it is an image, and returns it. Image::get_by_username(username) gets all database images from the database and returns the uuids. the client is responsible for getting the images. - diff --git a/src/main.rs b/src/main.rs index e01053d..6df4299 100644 --- a/src/main.rs +++ b/src/main.rs @@ -117,6 +117,12 @@ async fn migrate(rocket: Rocket) -> Rocket { ADD COLUMN IF NOT EXISTS text_id TEXT NOT NULL UNIQUE", )) .await; + let _ = conn + .execute(sqlx::query( + "ALTER TABLE posts + ADD COLUMN IF NOT EXISTS author STRING NOT NULL", + )) + .await; let _ = conn .execute(sqlx::query( "ALTER TABLE posts diff --git a/src/routes/posts.rs b/src/routes/posts.rs index c3a51eb..1c17664 100644 --- a/src/routes/posts.rs +++ b/src/routes/posts.rs @@ -1,13 +1,14 @@ /* * POST /posts: uses json request body to get the post info and, y'know, create it -* GET /posts/: figures out what type of id is, gets post via that, returns it -* UPDATE /posts/: figures out what type of id is, uses json request body to update +* TODO GET /posts/: figures out what type of id is, gets post via that, returns it +* TODO UPDATE /posts/: figures out what type of id is, uses json request body to update * specific data about the post -* DELETE /posts/: you can figure out what this one does +* TODO DELETE /posts/: you can figure out what this one does * -* GET /posts: gets all posts, maybe json request body for args? +* TODO GET /posts: gets all posts, maybe json request body for args? */ +use crate::tables::posts::Post; use crate::tables::{users::LoginStatus, users::User, Db}; use rocket::http::CookieJar; use rocket::http::Status; @@ -16,6 +17,7 @@ use rocket::response::status; use rocket::serde::json::Json; use rocket::serde::Deserialize; use rocket_db_pools::Connection; +use uuid::Uuid; #[derive(Deserialize)] #[serde(crate = "rocket::serde")] @@ -23,6 +25,7 @@ pub struct PostCreateInfo { pub title: String, pub text_id: String, pub body: String, + pub auto_pubilsh: bool, } #[post("/posts", data = "")] @@ -33,12 +36,41 @@ pub async fn create( ) -> status::Custom { match User::login_status(&mut db, cookies).await { LoginStatus::LoggedIn(user) => { - // if post with same text id exists, fail - // make sure user has perms to do this first tho - // and uhhhhh - // yeah thats it idk - // TODO: implement all that - status::Custom(Status::NotImplemented, "Not implemented yet".to_string()) + match user.make_posts || user.admin { + true => { + // if post with same text id exists, fail + match Post::get_by_text_id(&mut db, &info.text_id).await { + Some(_) => status::Custom( + Status::Forbidden, + "A post already exists with this text id.".to_string(), + ), + None => { + // create post + match Post::create( + &mut db, + &info.title, + &info.body, + info.auto_pubilsh, + Uuid::new_v4().to_string(), + &info.text_id, + user.username, + ) + .await + { + Some(_) => status::Custom(Status::Ok, "Created.".to_string()), + None => status::Custom( + Status::InternalServerError, + "Couldn't create post.".to_string(), + ), + } + } + } + } + false => status::Custom( + Status::Unauthorized, + "You don't have the permissions to do this".to_string(), + ), + } } LoginStatus::InvalidToken => { status::Custom(Status::Unauthorized, "Invalid login token".to_string()) diff --git a/src/tables/posts.rs b/src/tables/posts.rs index 5d77927..69d0a79 100644 --- a/src/tables/posts.rs +++ b/src/tables/posts.rs @@ -17,32 +17,35 @@ pub struct Post { } impl Post { 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 \n\n![trans flag image](https://sadlynotsappho.dev/pfp.png)*/ + db: &mut Connection, + title: &String, /*ex: Why Trans People Deserve All Your Money*/ + body: &String, /*ex: # Because we're cooler than you \n\n![trans flag image](https://sadlynotsappho.dev/pfp.png)*/ published: bool, uuid: String, - text_id: String, /*ex: why-trans-people-deserve-all-your-money */ - ) { + text_id: &String, /*ex: why-trans-people-deserve-all-your-money */ + author: String + ) -> Option<()> { match db - .fetch_all( + .execute( sqlx::query( r#" - INSERT INTO posts (title, body, published, uuid, text_id) - VALUES ($1, $2, $3, $4, $5); + INSERT INTO posts (title, body, published, uuid, text_id, author) + VALUES ($1, $2, $3, $4, $5, $6); "#, ) .bind(title) .bind(body) .bind(published) .bind(uuid) - .bind(text_id), + .bind(text_id) + .bind(author), ) .await { - Ok(_) => (), + Ok(_) => Some(()), Err(why) => { eprintln!("Couldn't create database entry: {why:?}"); + None } } } @@ -58,7 +61,7 @@ impl Post { title: res.get::("title"), body: res.get::("body"), published: res.get::("published"), - timestamp: res.get::("timestamp") + timestamp: res.get::("timestamp"), } } pub async fn get_by_uuid(mut db: Connection, uuid: String) -> Post { @@ -73,22 +76,27 @@ impl Post { title: res.get::("title"), body: res.get::("body"), published: res.get::("published"), - timestamp: res.get::("timestamp") + timestamp: res.get::("timestamp"), } } - pub async fn get_by_text_id(mut db: Connection, text_id: String) -> Post { - let res = db + pub async fn get_by_text_id(db: &mut Connection, text_id: &String) -> Option { + match 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"), - timestamp: res.get::("timestamp") + { + Ok(res) => Some(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"), + timestamp: res.get::("timestamp"), + }), + Err(why) => { + eprintln!("{why:?}"); + None + } } }