diff --git a/src/main.rs b/src/main.rs index f927c1f..fcd2a89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -160,6 +160,7 @@ async fn run_server(db: Arc) { // Book API .routes(routes!(routes::book::get_book_by_ean)) .routes(routes!(routes::book::get_book_by_id)) + .routes(routes!(routes::book::create_book)) // Book Instance API .routes(routes!(routes::book_instance::get_book_instance_by_id)) .routes(routes!(routes::book_instance::create_book_instance)) diff --git a/src/routes/book.rs b/src/routes/book.rs index 6b350c6..bff6126 100644 --- a/src/routes/book.rs +++ b/src/routes/book.rs @@ -2,7 +2,8 @@ use std::sync::Arc; use axum::{extract::{Path, State}, Json}; use reqwest::{StatusCode}; -use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; +use sea_orm::{ActiveModelTrait, ActiveValue::{NotSet, Set}, ColumnTrait, EntityTrait, QueryFilter, TryIntoModel}; +use serde::{Deserialize, Serialize}; use utoipa::IntoParams; use crate::{entities::{book, prelude::{Book}}, utils::open_library}; @@ -85,3 +86,49 @@ pub async fn get_book_by_ean( } } } + +#[derive(Deserialize, Serialize, utoipa::ToSchema)] +pub struct BookCreateParams { + ean: String, + title: String, + author: String +} + +#[axum::debug_handler] +#[utoipa::path( + post, + path = "/book", + request_body = BookCreateParams, + security(("jwt" = [])), + responses( + (status = OK, body = book::Model, description = "Successfully saved book data"), + (status = CONFLICT, body = book::Model, description = "A book with the same EAN already exists. Replies with the data of the already saved book."), + ), + summary = "Manually add book data to the database", + description = "Should be used when needing to insert data for an EAN that doesn't already exist in the database and couldn't be fetched automatically, ie the /book/ean/{ean} endpoint returned a 404 NOT FOUND error", + tag = "book-api", +)] +pub async fn create_book( + State(state): State>, + Json(instance_payload): Json, +) -> (StatusCode, Json>) { + if let Some(book) = Book::find().filter(book::Column::Ean.eq(&instance_payload.ean)).one(state.db_conn.as_ref()).await.unwrap() { + return (StatusCode::CONFLICT, Json(Some(book))); + } + + let book = book::ActiveModel { + ean: Set(instance_payload.ean), + title: Set(instance_payload.title), + author: Set(instance_payload.author), + id: NotSet + }; + + let b = book.save(state.db_conn.as_ref()).await; + match b { + Err(e) => { + log::error!(target: "api", "Error while inserting new book: {:#?}", e); + (StatusCode::BAD_REQUEST, Json(None)) + }, + Ok(res) => (StatusCode::OK, Json(Some(res.try_into_model().expect("All fields should be set once the book is saved")))) + } +}