From b4bb10c21757c5d96094c717c240ff4b46202960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Salazar?= Date: Wed, 22 Jan 2025 12:58:56 -0600 Subject: [PATCH 1/3] fix: Added upload_image admin route for image uploads --- src/endpoints/admin/mod.rs | 1 + src/endpoints/admin/upload_image.rs | 33 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/endpoints/admin/upload_image.rs diff --git a/src/endpoints/admin/mod.rs b/src/endpoints/admin/mod.rs index 97551e0..2cb37ae 100644 --- a/src/endpoints/admin/mod.rs +++ b/src/endpoints/admin/mod.rs @@ -11,4 +11,5 @@ pub mod quest; pub mod quest_boost; pub mod quiz; pub mod twitter; +pub mod upload_image; pub mod user; diff --git a/src/endpoints/admin/upload_image.rs b/src/endpoints/admin/upload_image.rs new file mode 100644 index 0000000..e50c65f --- /dev/null +++ b/src/endpoints/admin/upload_image.rs @@ -0,0 +1,33 @@ +use axum::{ + extract::{Multipart, Path}, + http::StatusCode, + response::IntoResponse, +}; +use axum_auto_routes::route; +use std::{fs::create_dir_all, path::Path as FilePath}; + +#[route(post, "/admin/upload_image/:image_name")] +pub async fn upload_image_handler( + Path(image_name): Path, + mut multipart: Multipart, +) -> impl IntoResponse { + let images_folder = "./images"; + if !FilePath::new(images_folder).exists() { + create_dir_all(images_folder).unwrap(); + } + + while let Some(field) = multipart.next_field().await.unwrap() { + if let Some(filename) = field.file_name() { + if filename.ends_with(".webp") { + let filepath = format!("{}/{}.webp", images_folder, image_name); + let data = field.bytes().await.unwrap(); + tokio::fs::write(filepath, data).await.unwrap(); + return StatusCode::OK.into_response(); + } else { + return (StatusCode::BAD_REQUEST, "Only .webp files are allowed").into_response(); + } + } + } + + (StatusCode::BAD_REQUEST, "No valid file provided").into_response() +} From 8754b0cd983d2eb85a44319b81b4a11f6bb1abd2 Mon Sep 17 00:00:00 2001 From: Sebastian Salazar Date: Fri, 24 Jan 2025 01:48:10 -0600 Subject: [PATCH 2/3] fix: fix the upload_image file and add dependencies to cargo toml --- Cargo.toml | 4 ++-- src/endpoints/admin/upload_image.rs | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0cc6254..da91926 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,11 +11,11 @@ starknet-id = { git = "https://github.com/starknet-id/starknet-id.rs.git", rev = serde_derive = "1.0.183" env_logger = "0.10.0" axum_auto_routes = { git = "https://github.com/Th0rgal/axum_auto_routes.git", rev = "4bcae49628a657ed4bdc1749dfd4f1221ffaffe7" } -axum = "0.6.17" +axum = { version = "0.6.17", features = ["multipart"] } toml = "0.5.10" serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0.96" -tokio = { version = "1.26.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.26.0", features = ["full", "macros", "rt-multi-thread"] } tower-http = { version = "0.4.0", features = ["cors"] } mongodb = "2.4.0" futures = "0.3.28" diff --git a/src/endpoints/admin/upload_image.rs b/src/endpoints/admin/upload_image.rs index e50c65f..567589a 100644 --- a/src/endpoints/admin/upload_image.rs +++ b/src/endpoints/admin/upload_image.rs @@ -2,11 +2,11 @@ use axum::{ extract::{Multipart, Path}, http::StatusCode, response::IntoResponse, + routing::post, + Router, }; -use axum_auto_routes::route; use std::{fs::create_dir_all, path::Path as FilePath}; -#[route(post, "/admin/upload_image/:image_name")] pub async fn upload_image_handler( Path(image_name): Path, mut multipart: Multipart, @@ -31,3 +31,8 @@ pub async fn upload_image_handler( (StatusCode::BAD_REQUEST, "No valid file provided").into_response() } + +pub fn admin_routes() -> Router { + Router::new().route("/admin/upload_image/:image_name", post(upload_image_handler)) +} + From 8351e065aa362d8cf695159815ef183038ff263f Mon Sep 17 00:00:00 2001 From: Nico <60229704+Marchand-Nicolas@users.noreply.github.com> Date: Fri, 24 Jan 2025 11:50:31 -0100 Subject: [PATCH 3/3] fix route impl --- src/endpoints/admin/upload_image.rs | 49 +++++++++++++++++++---------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/endpoints/admin/upload_image.rs b/src/endpoints/admin/upload_image.rs index 567589a..25968c7 100644 --- a/src/endpoints/admin/upload_image.rs +++ b/src/endpoints/admin/upload_image.rs @@ -1,38 +1,55 @@ +use crate::middleware::auth::auth_middleware; +use crate::models::AppState; +use crate::utils::get_error; use axum::{ - extract::{Multipart, Path}, + extract::{Extension, Multipart, Path, State}, http::StatusCode, - response::IntoResponse, - routing::post, - Router, + response::{IntoResponse, Json}, }; +use axum_auto_routes::route; +use serde_json::json; +use std::sync::Arc; use std::{fs::create_dir_all, path::Path as FilePath}; +#[route(post, "/admin/images/upload/:image_name", auth_middleware)] pub async fn upload_image_handler( + State(state): State>, + Extension(sub): Extension, // Example if sub is needed for authorization Path(image_name): Path, mut multipart: Multipart, ) -> impl IntoResponse { let images_folder = "./images"; if !FilePath::new(images_folder).exists() { - create_dir_all(images_folder).unwrap(); + if let Err(e) = create_dir_all(images_folder) { + return get_error(format!("Failed to create images folder: {}", e)); + } } - while let Some(field) = multipart.next_field().await.unwrap() { + while let Some(field) = multipart.next_field().await.unwrap_or_else(|_| None) { if let Some(filename) = field.file_name() { if filename.ends_with(".webp") { let filepath = format!("{}/{}.webp", images_folder, image_name); - let data = field.bytes().await.unwrap(); - tokio::fs::write(filepath, data).await.unwrap(); - return StatusCode::OK.into_response(); + let data = match field.bytes().await { + Ok(data) => data, + Err(e) => { + return get_error(format!("Failed to read file data: {}", e)); + } + }; + + if let Err(e) = tokio::fs::write(&filepath, data).await { + return get_error(format!("Failed to write file: {}", e)); + } + + return ( + StatusCode::OK, + Json(json!({"message": "File uploaded successfully"})), + ) + .into_response(); } else { - return (StatusCode::BAD_REQUEST, "Only .webp files are allowed").into_response(); + return get_error("Only .webp files are allowed".to_string()); } } } - (StatusCode::BAD_REQUEST, "No valid file provided").into_response() + get_error("No valid file provided".to_string()) } - -pub fn admin_routes() -> Router { - Router::new().route("/admin/upload_image/:image_name", post(upload_image_handler)) -} -