summaryrefslogtreecommitdiff
path: root/dichroism/src/handlers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'dichroism/src/handlers.rs')
-rw-r--r--dichroism/src/handlers.rs99
1 files changed, 61 insertions, 38 deletions
diff --git a/dichroism/src/handlers.rs b/dichroism/src/handlers.rs
index 5d678f5..43c11d2 100644
--- a/dichroism/src/handlers.rs
+++ b/dichroism/src/handlers.rs
@@ -1,9 +1,11 @@
use crate::dtos::*;
use crate::image_service;
use crate::models::Product;
-use crate::repo;
+use crate::repo::{photo_set_repo, product_repo};
use crate::types::DbPool;
+use actix_multipart::Multipart;
use actix_web::{get, patch, post, web, Error, HttpResponse, Responder};
+use futures::{StreamExt, TryStreamExt};
fn to_internal_error(e: impl std::error::Error) -> HttpResponse {
eprintln!("{}", e);
@@ -18,7 +20,7 @@ async fn hello() -> impl Responder {
#[get("/products")]
async fn get_products(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
let conn = pool.get().map_err(to_internal_error)?;
- let products: Vec<ProductGet> = web::block(move || repo::find_all(&conn))
+ let products: Vec<ProductGet> = web::block(move || product_repo::find_all(&conn))
.await
.map_err(to_internal_error)?
.into_iter()
@@ -30,43 +32,33 @@ async fn get_products(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
#[patch("/products")]
async fn patch_product(
pool: web::Data<DbPool>,
- patch: web::Json<ProductPatch>,
+ web::Json(patch): web::Json<ProductPatch>,
) -> Result<HttpResponse, Error> {
- let patch = patch.into_inner();
let id = patch.id;
+ // get product referenced by patch
let conn = pool.get().map_err(to_internal_error)?;
- let mut product = web::block(move || repo::find(&conn, id))
+ let mut product = web::block(move || product_repo::find(&conn, id))
.await
.map_err(to_internal_error)?
.ok_or_else(|| HttpResponse::NotFound().finish())?;
- if let Some(data_uri) = patch.photo_data {
- // create new photo_set
- let photo_set = web::block(move || image_service::generate_photo_set(&data_uri))
- .await
- .map_err(|e| {
- eprintln!("{}", e.to_string());
- HttpResponse::InternalServerError().body(e.to_string())
- })?;
+ // get photo set referenced by patch
+ if let Some(id) = patch.photo_set {
let conn = pool.get().map_err(to_internal_error)?;
- let photo_set = web::block(move || repo::store_photo_set(&conn, photo_set))
+ let photo_set = web::block(move || photo_set_repo::find(&conn, id))
.await
- .map_err(to_internal_error)?;
+ .map_err(to_internal_error)?
+ .ok_or_else(|| HttpResponse::NotFound().body("Photo set not found"))?;
product.photo_set = photo_set;
}
- // patch the rest of the product
- product.name = patch.name.unwrap_or(product.name);
- product.quantity = patch.quantity.unwrap_or(product.quantity);
- product.cents = patch.cents.unwrap_or(product.cents);
- product.description = patch.description.unwrap_or(product.description);
- product.featured = patch.featured.unwrap_or(product.featured);
- product.category = patch.category_path.unwrap_or(product.category);
+ // update product fields
+ patch.patch(&mut product);
// store the updated product
let conn = pool.get().map_err(to_internal_error)?;
- let product = web::block(move || repo::store_product(&conn, product))
+ let product = web::block(move || product_repo::store(&conn, product))
.await
.map_err(to_internal_error)?;
@@ -76,24 +68,17 @@ async fn patch_product(
#[post("/products")]
async fn post_product(
pool: web::Data<DbPool>,
- post: web::Json<ProductPost>,
+ web::Json(post): web::Json<ProductPost>,
) -> Result<HttpResponse, Error> {
- let post = post.into_inner();
- dbg!(&post);
-
- // create new photo_set
- let data_uri = post.photo_data;
- let photo_set = web::block(move || image_service::generate_photo_set(&data_uri))
- .await
- .map_err(|e| {
- eprintln!("{}", e.to_string());
- HttpResponse::InternalServerError().body(e.to_string())
- })?;
+ // find associated photo set
+ let photo_set = post.photo_set;
let conn = pool.get().map_err(to_internal_error)?;
- let photo_set = web::block(move || repo::store_photo_set(&conn, photo_set))
+ let photo_set = web::block(move || photo_set_repo::find(&conn, photo_set))
.await
- .map_err(to_internal_error)?;
+ .map_err(to_internal_error)?
+ .ok_or_else(|| HttpResponse::NotFound().body("Photo set not found."))?;
+ // create new product
let product = Product {
id: None,
name: post.name,
@@ -105,10 +90,48 @@ async fn post_product(
photo_set,
};
+ // store product
let conn = pool.get().map_err(to_internal_error)?;
- let product = web::block(move || repo::store_product(&conn, product))
+ let product = web::block(move || product_repo::store(&conn, product))
.await
.map_err(to_internal_error)?;
Ok(HttpResponse::Ok().json::<ProductGet>(product.into()))
}
+
+#[post("/photos")]
+async fn post_photo(
+ pool: web::Data<DbPool>,
+ mut payload: Multipart,
+) -> Result<HttpResponse, Error> {
+ let mut responses: Vec<PhotoSetGet> = Vec::new();
+
+ if let Ok(Some(mut field)) = payload.try_next().await {
+ // bail if a non-JPEG file was going to be uploaded
+ if field.content_type() != &mime::IMAGE_JPEG {
+ return Ok(HttpResponse::BadRequest().body("File must be a JPEG image."));
+ }
+
+ // grab all bytes
+ let mut data: Vec<u8> = Vec::new();
+ while let Some(chunk) = field.next().await {
+ let chunk = chunk?;
+ data.extend(chunk);
+ }
+
+ // create new photo_set
+ let photo_set = web::block(move || image_service::generate_photo_set(&data))
+ .await
+ .map_err(|e| {
+ eprintln!("{}", e.to_string());
+ HttpResponse::InternalServerError().body(e.to_string())
+ })?;
+ let conn = pool.get().map_err(to_internal_error)?;
+ let photo_set = web::block(move || photo_set_repo::store(&conn, photo_set))
+ .await
+ .map_err(to_internal_error)?;
+ responses.push(photo_set.into());
+ }
+
+ Ok(HttpResponse::Ok().json(responses))
+}