feat: book instance search API endpoint
This commit is contained in:
parent
44be2c83ba
commit
5d4ece3c34
3 changed files with 62 additions and 3 deletions
|
|
@ -184,6 +184,7 @@ async fn run_server(db: Arc<DatabaseConnection>, port: u16) {
|
||||||
.routes(routes!(routes::book_instance::bulk_create_book_instance))
|
.routes(routes!(routes::book_instance::bulk_create_book_instance))
|
||||||
.routes(routes!(routes::book_instance::get_bal_owner_book_instances))
|
.routes(routes!(routes::book_instance::get_bal_owner_book_instances))
|
||||||
.routes(routes!(routes::book_instance::get_bal_book_instances_by_ean))
|
.routes(routes!(routes::book_instance::get_bal_book_instances_by_ean))
|
||||||
|
.routes(routes!(routes::book_instance::search_bal_book_instances))
|
||||||
// Owner API
|
// Owner API
|
||||||
.routes(routes!(routes::owner::get_owner_by_id))
|
.routes(routes!(routes::owner::get_owner_by_id))
|
||||||
.routes(routes!(routes::owner::create_owner))
|
.routes(routes!(routes::owner::create_owner))
|
||||||
|
|
@ -230,6 +231,7 @@ async fn run_server(db: Arc<DatabaseConnection>, port: u16) {
|
||||||
.try_it_out_enabled(true)
|
.try_it_out_enabled(true)
|
||||||
.filter(true)
|
.filter(true)
|
||||||
.display_request_duration(true)
|
.display_request_duration(true)
|
||||||
|
.persist_authorization(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
let router = router.merge(swagger);
|
let router = router.merge(swagger);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::{entities::{bal, prelude::*}, routes::auth::Claims, AppState};
|
||||||
#[derive(IntoParams)]
|
#[derive(IntoParams)]
|
||||||
#[into_params(names("id"), parameter_in = Path)]
|
#[into_params(names("id"), parameter_in = Path)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct BalByIdParams(u32);
|
pub struct BalByIdParams(u32);
|
||||||
|
|
||||||
#[axum::debug_handler]
|
#[axum::debug_handler]
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::Arc;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use axum::{extract::{Path, State}, Json};
|
use axum::{extract::{Path, State}, Json};
|
||||||
use reqwest::{StatusCode};
|
use reqwest::{StatusCode};
|
||||||
|
|
@ -6,7 +6,7 @@ use sea_orm::{ActiveModelTrait, ActiveValue::{NotSet, Set}, ColumnTrait, EntityT
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use utoipa::IntoParams;
|
use utoipa::IntoParams;
|
||||||
|
|
||||||
use crate::{entities::{book, book_instance, prelude::*}, routes::auth::Claims, utils::auth::{user_is_bal_owner, user_is_book_instance_owner, user_is_owner_owner}, AppState};
|
use crate::{entities::{book, book_instance, prelude::*}, routes::{auth::Claims, bal}, utils::auth::{user_is_bal_owner, user_is_book_instance_owner, user_is_owner_owner}, AppState};
|
||||||
|
|
||||||
|
|
||||||
#[derive(IntoParams)]
|
#[derive(IntoParams)]
|
||||||
|
|
@ -329,3 +329,60 @@ pub async fn get_bal_book_instances_by_ean(
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(vec![]))
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(vec![]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, utoipa::ToSchema)]
|
||||||
|
pub struct BookInstanceSearchParams {
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, utoipa::ToSchema)]
|
||||||
|
pub struct BookInstanceSearchResults {
|
||||||
|
book_instances: Vec<book_instance::Model>,
|
||||||
|
books: HashMap<u32, book::Model>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[axum::debug_handler]
|
||||||
|
#[utoipa::path(
|
||||||
|
post,
|
||||||
|
path = "/bal/{id}/search",
|
||||||
|
params(bal::BalByIdParams),
|
||||||
|
request_body = BookInstanceSearchParams,
|
||||||
|
security(("jwt" = [])),
|
||||||
|
responses(
|
||||||
|
(status = OK, body = BookInstanceSearchResults, description = "Found book instances in the database"),
|
||||||
|
(status = FORBIDDEN, description = "You do not own the specified bal"),
|
||||||
|
),
|
||||||
|
summary = "Search a BAL for books instances",
|
||||||
|
description = "Lists all book instances that match the requested parameters in a bal",
|
||||||
|
tag = "book-instance-api",
|
||||||
|
)]
|
||||||
|
pub async fn search_bal_book_instances(
|
||||||
|
State(state): State<Arc<AppState>>,
|
||||||
|
claims: Claims,
|
||||||
|
Path(bal_id): Path<u32>,
|
||||||
|
Json(instance_payload): Json<BookInstanceSearchParams>,
|
||||||
|
) -> (StatusCode, Json<Option<BookInstanceSearchResults>>) {
|
||||||
|
if !user_is_bal_owner(claims.user_id, bal_id, state.db_conn.as_ref()).await {
|
||||||
|
return (StatusCode::FORBIDDEN, Json(None));
|
||||||
|
}
|
||||||
|
if let Ok(res) = BookInstance::find()
|
||||||
|
.filter(book_instance::Column::BalId.eq(bal_id))
|
||||||
|
.filter(book_instance::Column::Available.eq(true))
|
||||||
|
.join(JoinType::InnerJoin, book_instance::Relation::Book.def())
|
||||||
|
.filter(book::Column::Title.like(format!("%{}%", instance_payload.title)))
|
||||||
|
.all(state.db_conn.as_ref()).await
|
||||||
|
{
|
||||||
|
let mut book_id_map = HashMap::new();
|
||||||
|
for instance in &res {
|
||||||
|
if book_id_map.get(&instance.book_id).is_none() {
|
||||||
|
book_id_map.insert(instance.book_id, Book::find_by_id(instance.book_id).one(state.db_conn.as_ref()).await.unwrap().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(StatusCode::OK, Json(Some(BookInstanceSearchResults {
|
||||||
|
book_instances: res,
|
||||||
|
books: book_id_map
|
||||||
|
})))
|
||||||
|
} else {
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Reference in a new issue