From 951372a60aa45259770e16e3c723d4bc20aee38e Mon Sep 17 00:00:00 2001 From: SadlyNotSappho Date: Tue, 20 Feb 2024 11:56:18 -0800 Subject: [PATCH] start implementing images --- Cargo.lock | 10 ++++++ Cargo.toml | 1 + imagesplan.txt | 14 ++++++++ src/main.rs | 6 ++++ src/tables.rs | 87 +++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 imagesplan.txt diff --git a/Cargo.lock b/Cargo.lock index 7c0c67d..be3df87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -525,6 +525,7 @@ dependencies = [ "rocket_db_pools", "sha256", "sqlx", + "uuid", ] [[package]] @@ -2425,6 +2426,15 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +dependencies = [ + "getrandom", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 620b85d..f0b0cf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,5 @@ rocket = {version="0.5.0",features=["secrets","json"]} rocket_db_pools = {version="0.1.0",features=["sqlx_postgres"]} sha256 = "1.5.0" sqlx = { version = "0.7.3", features = ["macros", "postgres"] } +uuid = { version = "1.7.0", features = ["v4"] } # rocket_sync_db_pools = { version = "0.1.0", features = ["diesel_postgres_pool", "diesel"] } diff --git a/imagesplan.txt b/imagesplan.txt new file mode 100644 index 0000000..59c3fa6 --- /dev/null +++ b/imagesplan.txt @@ -0,0 +1,14 @@ +GET /images/uuid.filetype + -> returns the image with the correct filetype - uuid.png would return the image in png format, etc + +GET /images/by-user {user: "username"} + -> gets all of the images made by {user}, if you are {user}, unless you have admin. + +POST /images/create {image: "image data"} + -> returns the uuid of the image, which it saves to the folder and database + +DELETE /images/uuid + -> 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 773dbf6..0411f32 100644 --- a/src/main.rs +++ b/src/main.rs @@ -347,6 +347,12 @@ async fn migrate(rocket: Rocket) -> Rocket { )) .await; + let _ = conn.execute(sqlx::query( + "ALTER TABLE images + DELETE COLUMN IF EXISTS image" + )) + .await; + rocket } diff --git a/src/tables.rs b/src/tables.rs index 963bfe3..46f2c26 100644 --- a/src/tables.rs +++ b/src/tables.rs @@ -1,6 +1,7 @@ use base64::{engine::general_purpose, Engine}; use rand::{RngCore, SeedableRng}; use regex::Regex; +use rocket::fs::TempFile; use rocket::http::Cookie; use rocket_db_pools::sqlx::Executor; use rocket_db_pools::Connection; @@ -236,5 +237,89 @@ pub struct Image { pub id: i32, pub uuid: String, pub owner_name: String, - pub image: String, +} + +impl Image { + pub async fn create(db: &mut Connection, mut image: TempFile<'_>, user: User) -> Status { + let uuid = uuid::Uuid::new_v4().to_string(); + + // this is bad. see any of maia arson crimew's articles as to why. + image.persist_to(format!("/images/{uuid}.png")).await.unwrap(); + + match db + .execute( + sqlx::query( + r#" + INSERT INTO images (uuid, owner_name) + VALUES ($1, $2,); + "#, + ) + .bind(uuid) + .bind(user.username), + ) + .await + { + Ok(_) => Status { + status: StatusTypes::Success, + data: "Created image successfully.".to_string() + }, + Err(why) => { + eprintln!("Couldn't create database entry: {why:?}"); + Status { + status: StatusTypes::Faliure, + data: "Couldn't create image.".to_string() + } + } + } + } + pub async fn get_by_uuid(db: &mut Connection, uuid: &String) -> Result { + match db + .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"), + }), + Err(_) => Err("Couldn't get image.".to_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 + { + 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"), + }) + } + Ok(res) + }, + Err(_) => Err("Couldn't get image.".to_string()), + } + } + pub async fn delete(db: &mut Connection, uuid: &String) -> Status { + match db.execute(sqlx::query("DELETE FROM images WHERE uuid = $1").bind(uuid)).await { + Ok(rows_gone) => { + eprintln!("Deleted {rows_gone:?} rows."); + Status { + status: StatusTypes::Success, + data: "Successfully deleted the image.".to_string() + } + }, + Err(why) => { + eprintln!("Couldn't remove database entry: {why:?}"); + Status { + status: StatusTypes::Faliure, + data: "Couldn't delete the image.".to_string() + } + } + } + } }