User Authentication and Other fixes #1
@@ -1,39 +1,41 @@
|
||||
use axum::{
|
||||
extract::{Extension, Path},
|
||||
http::{HeaderValue, Method, StatusCode},
|
||||
response::IntoResponse,
|
||||
routing::{get,post,get_service},
|
||||
routing::{get, get_service, post},
|
||||
Json, Router,
|
||||
extract::{Extension, Path},
|
||||
};
|
||||
use clap::Parser;
|
||||
use image;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||
use std::str::FromStr;
|
||||
use std::io;
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::services::ServeDir;
|
||||
use tower_http::cors::{Any,CorsLayer};
|
||||
use tower_http::trace::TraceLayer;
|
||||
use booksman_search::BookMeili;
|
||||
use booksman_search;
|
||||
use booksman_orm::{
|
||||
sea_orm::{Database, DatabaseConnection},
|
||||
Mutation as MutationCore, Query as QueryCore
|
||||
// BookAndMeta,
|
||||
Mutation as MutationCore,
|
||||
Query as QueryCore, // BookAndMeta,
|
||||
};
|
||||
use booksman_search;
|
||||
use booksman_search::BookMeili;
|
||||
use clap::Parser;
|
||||
use image;
|
||||
use meilisearch_sdk::client::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||
use std::str::FromStr;
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use tower_http::services::ServeDir;
|
||||
use tower_http::trace::TraceLayer;
|
||||
//use itertools::Itertools;
|
||||
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn,user};
|
||||
use std::env;
|
||||
use migration::{Migrator, MigratorTrait};
|
||||
use chrono::Local;
|
||||
use ::entity::entities::{
|
||||
book, book_author, book_isbn, book_person, book_place, book_subject, book_time, user,
|
||||
};
|
||||
use axum_login::{
|
||||
axum_sessions::{async_session::MemoryStore as SessionMemoryStore, SessionLayer},
|
||||
AuthLayer, RequireAuthorizationLayer,
|
||||
};
|
||||
use chrono::Local;
|
||||
use migration::{Migrator, MigratorTrait};
|
||||
use rand::Rng;
|
||||
use std::env;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
struct BookUI {
|
||||
@@ -83,7 +85,6 @@ struct Books {
|
||||
docs: Vec<Docs>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
struct PaginatedBookUIList {
|
||||
num_pages: u32,
|
||||
@@ -142,7 +143,6 @@ pub struct Cover {
|
||||
pub medium: String,
|
||||
}
|
||||
|
||||
|
||||
impl Books {
|
||||
fn set_all_cover_urls(&mut self) {
|
||||
for book in self.docs.iter_mut() {
|
||||
@@ -157,31 +157,38 @@ impl Books {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl BookUI {
|
||||
async fn set_descriptions(&mut self) {
|
||||
|
||||
if self.open_library_key.is_some() {
|
||||
if !(self.open_library_key.as_ref().unwrap().is_empty()) {
|
||||
let query = format!("https://openlibrary.org/{}.json", self.open_library_key.as_ref().unwrap().clone());
|
||||
let query = format!(
|
||||
"https://openlibrary.org/{}.json",
|
||||
self.open_library_key.as_ref().unwrap().clone()
|
||||
);
|
||||
let res = reqwest::get(query).await.expect("Unable to request");
|
||||
let resjson = res.json::<BookPageOL>().await.expect("Unable to return value");
|
||||
let resjson = res
|
||||
.json::<BookPageOL>()
|
||||
.await
|
||||
.expect("Unable to return value");
|
||||
let description = resjson.description;
|
||||
|
||||
if !description.is_none() {
|
||||
if let DescriptionOL::DescriptionString(desc_string) = description.clone().unwrap() {
|
||||
if let DescriptionOL::DescriptionString(desc_string) =
|
||||
description.clone().unwrap()
|
||||
{
|
||||
self.description = Some(desc_string);
|
||||
}
|
||||
if let DescriptionOL::DescriptionValueString(desc_val) = description.clone().unwrap() {
|
||||
if let DescriptionOL::DescriptionValueString(desc_val) =
|
||||
description.clone().unwrap()
|
||||
{
|
||||
self.description = Some(desc_val.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async fn handle_error(_err: io::Error) -> impl IntoResponse {
|
||||
@@ -209,7 +216,8 @@ struct Opt {
|
||||
static_dir: String,
|
||||
}
|
||||
|
||||
type AuthContext = axum_login::extractors::AuthContext<booksman_orm::AxumUser, booksman_orm::AxumUserStore>;
|
||||
type AuthContext =
|
||||
axum_login::extractors::AuthContext<booksman_orm::AxumUser, booksman_orm::AxumUserStore>;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
@@ -222,7 +230,6 @@ pub async fn main() {
|
||||
// enable console logging
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
|
||||
dotenvy::dotenv().ok();
|
||||
let images_dir = env::var("IMAGES_DIR").expect("IMAGES_DIR is not set in .env file");
|
||||
let cors_url = env::var("CORS_URL").expect("CORS_URL is not set in .env file");
|
||||
@@ -238,17 +245,15 @@ pub async fn main() {
|
||||
// Apply all pending migrations
|
||||
Migrator::up(&conn, None).await.unwrap();
|
||||
|
||||
|
||||
let session_store = SessionMemoryStore::new();
|
||||
let session_layer = SessionLayer::new(session_store, &secret).with_secure(false);
|
||||
|
||||
|
||||
let user_store = booksman_orm::AxumUserStore::new(&conn);
|
||||
let auth_layer: AuthLayer<booksman_orm::AxumUserStore, booksman_orm::AxumUser> = AuthLayer::new(user_store, &secret);
|
||||
let auth_layer: AuthLayer<booksman_orm::AxumUserStore, booksman_orm::AxumUser> =
|
||||
AuthLayer::new(user_store, &secret);
|
||||
|
||||
let meili_client = Client::new(meili_url, meili_key);
|
||||
|
||||
|
||||
let app = Router::new()
|
||||
.route("/api/create_by_isbn", get(create_by_isbn))
|
||||
.route("/api/create", post(create_book))
|
||||
@@ -263,8 +268,14 @@ pub async fn main() {
|
||||
.route("/api/login", post(login_handler))
|
||||
.route("/api/register", post(register_handler))
|
||||
.route("/api/logout", post(logout_handler))
|
||||
.nest_service("/images", get_service(ServeDir::new(images_dir)).handle_error(handle_error))
|
||||
.nest_service("/assets", get_service(ServeDir::new(opt.static_dir)).handle_error(handle_error))
|
||||
.nest_service(
|
||||
"/images",
|
||||
get_service(ServeDir::new(images_dir)).handle_error(handle_error),
|
||||
)
|
||||
.nest_service(
|
||||
"/assets",
|
||||
get_service(ServeDir::new(opt.static_dir)).handle_error(handle_error),
|
||||
)
|
||||
// .merge(SpaRouter::new("/assets", opt.static_dir))
|
||||
.layer(auth_layer)
|
||||
.layer(session_layer)
|
||||
@@ -297,26 +308,26 @@ pub async fn main() {
|
||||
.expect("Unable to start server");
|
||||
}
|
||||
|
||||
|
||||
//#[axum_macros::debug_handler]
|
||||
async fn register_handler(Extension(ref conn): Extension<DatabaseConnection>,
|
||||
Json(user_sent): Json<booksman_orm::AxumUser>) -> impl IntoResponse {
|
||||
async fn register_handler(
|
||||
Extension(ref conn): Extension<DatabaseConnection>,
|
||||
Json(user_sent): Json<booksman_orm::AxumUser>,
|
||||
) -> impl IntoResponse {
|
||||
// add to db
|
||||
let user: user::Model = user::Model {
|
||||
id: user_sent.id,
|
||||
user_name: Some(user_sent.clone().name),
|
||||
password_hash: user_sent.clone().password_hash,
|
||||
};
|
||||
let _created_user = MutationCore::create_user(conn, user).await.expect("Failed to create user");
|
||||
let _created_user = MutationCore::create_user(conn, user)
|
||||
.await
|
||||
.expect("Failed to create user");
|
||||
return "success";
|
||||
}
|
||||
|
||||
|
||||
async fn list_users(
|
||||
Extension(ref conn): Extension<DatabaseConnection>,
|
||||
) -> impl IntoResponse {
|
||||
|
||||
let usersmodels : Vec<user::Model> = QueryCore::list_all_users(&conn).await.unwrap_or(Vec::new());
|
||||
async fn list_users(Extension(ref conn): Extension<DatabaseConnection>) -> impl IntoResponse {
|
||||
let usersmodels: Vec<user::Model> =
|
||||
QueryCore::list_all_users(&conn).await.unwrap_or(Vec::new());
|
||||
let mut users: Vec<booksman_orm::AxumUser> = Vec::new();
|
||||
for usermodel in usersmodels.iter() {
|
||||
let user = booksman_orm::AxumUser {
|
||||
@@ -328,13 +339,20 @@ async fn list_users(
|
||||
}
|
||||
return Json(users);
|
||||
}
|
||||
async fn login_handler(mut auth: AuthContext, Extension(ref conn): Extension<DatabaseConnection>, Json(user_sent): Json<booksman_orm::AxumUser>) -> impl IntoResponse {
|
||||
let userdb : user::Model = QueryCore::find_userid_by_name(conn, user_sent.name.clone()).await.unwrap().unwrap();
|
||||
async fn login_handler(
|
||||
mut auth: AuthContext,
|
||||
Extension(ref conn): Extension<DatabaseConnection>,
|
||||
Json(user_sent): Json<booksman_orm::AxumUser>,
|
||||
) -> impl IntoResponse {
|
||||
let userdb: user::Model = QueryCore::find_userid_by_name(conn, user_sent.name.clone())
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let userid = userdb.id;
|
||||
let corrected_user = booksman_orm::AxumUser {
|
||||
id: userid,
|
||||
name: user_sent.name.clone(),
|
||||
password_hash: user_sent.password_hash.clone()
|
||||
password_hash: user_sent.password_hash.clone(),
|
||||
};
|
||||
auth.login(&corrected_user).await.unwrap();
|
||||
return "success";
|
||||
@@ -354,7 +372,6 @@ async fn authentication_check(
|
||||
return Json(true);
|
||||
}
|
||||
|
||||
|
||||
//https://openlibrary.org/api/books?bibkeys=ISBN:9780980200447&jscmd=data&format=json
|
||||
async fn create_by_isbn(
|
||||
Extension(ref conn): Extension<DatabaseConnection>,
|
||||
@@ -362,67 +379,142 @@ async fn create_by_isbn(
|
||||
Extension(user): Extension<booksman_orm::AxumUser>,
|
||||
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
|
||||
) -> impl IntoResponse {
|
||||
|
||||
dotenvy::dotenv().ok();
|
||||
let images_dir = env::var("IMAGES_DIR").expect("IMAGES_DIR is not set in .env file");
|
||||
let userid = user.id;
|
||||
|
||||
print!("Get items with query params: {:?}\n", params);
|
||||
let isbns = params.get("isbns").unwrap();
|
||||
let splitisbns : Vec<String> = isbns.split(",").map(|s| format!("ISBN:{}",s.to_string())).collect();
|
||||
let splitisbns: Vec<String> = isbns
|
||||
.split(",")
|
||||
.map(|s| format!("ISBN:{}", s.to_string()))
|
||||
.collect();
|
||||
let joinedisbns = splitisbns.join(",");
|
||||
let query = format!("https://openlibrary.org/api/books?bibkeys={}&jscmd=data&format=json", joinedisbns);
|
||||
let query = format!(
|
||||
"https://openlibrary.org/api/books?bibkeys={}&jscmd=data&format=json",
|
||||
joinedisbns
|
||||
);
|
||||
let res = reqwest::get(query).await.expect("Unable to request");
|
||||
let resjson: BooksManyISBN = res.json::<BooksManyISBN>().await.expect("Unable to return value");
|
||||
let resjson: BooksManyISBN = res
|
||||
.json::<BooksManyISBN>()
|
||||
.await
|
||||
.expect("Unable to return value");
|
||||
for isbnstring in splitisbns.iter() {
|
||||
let bookfound = resjson.book_items.get(isbnstring);
|
||||
if !bookfound.clone().is_none() {
|
||||
let mut cover_id = "".to_string();
|
||||
if !bookfound.unwrap().cover.is_none() {
|
||||
let coverurl = bookfound.clone().unwrap().cover.clone().unwrap().medium.clone();
|
||||
let img_bytes = reqwest::get(coverurl.clone()).await.unwrap().bytes().await.unwrap();
|
||||
let coverurl = bookfound
|
||||
.clone()
|
||||
.unwrap()
|
||||
.cover
|
||||
.clone()
|
||||
.unwrap()
|
||||
.medium
|
||||
.clone();
|
||||
let img_bytes = reqwest::get(coverurl.clone())
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
let image = image::load_from_memory(&img_bytes).unwrap();
|
||||
let temp_cover = coverurl.clone();
|
||||
let img_id = temp_cover.split("/").last().unwrap();
|
||||
image.save(format!("{}/{}",images_dir,img_id)).expect("Failed to save image");
|
||||
image
|
||||
.save(format!("{}/{}", images_dir, img_id))
|
||||
.expect("Failed to save image");
|
||||
cover_id = img_id.to_string();
|
||||
|
||||
}
|
||||
let mut goodread_id = "".to_string();
|
||||
if !bookfound.unwrap().identifiers.is_none() {
|
||||
let goodread_identifier = bookfound.clone().unwrap().identifiers.clone().unwrap().goodreads;
|
||||
let goodread_identifier = bookfound
|
||||
.clone()
|
||||
.unwrap()
|
||||
.identifiers
|
||||
.clone()
|
||||
.unwrap()
|
||||
.goodreads;
|
||||
if !goodread_identifier.is_none() {
|
||||
goodread_id = goodread_identifier.unwrap().get(0).unwrap().to_string()
|
||||
}
|
||||
}
|
||||
//let mut authors_name = Some(vec!["".to_string()]);
|
||||
//if !bookfound.unwrap().authors.is_none() {
|
||||
let authors_name = Some(bookfound.clone().unwrap().authors.iter().map(|s| s.name.clone()).collect());
|
||||
let authors_name = Some(
|
||||
bookfound
|
||||
.clone()
|
||||
.unwrap()
|
||||
.authors
|
||||
.iter()
|
||||
.map(|s| s.name.clone())
|
||||
.collect(),
|
||||
);
|
||||
//} else {
|
||||
// authors_name = None
|
||||
//}
|
||||
let persons: Option<Vec<String>>;
|
||||
//= Some(vec!["".to_string()]);
|
||||
if !bookfound.unwrap().subject_people.is_none() {
|
||||
persons = Some(bookfound.clone().unwrap().subject_people.clone().unwrap().iter().map(|s| s.name.clone()).collect());
|
||||
persons = Some(
|
||||
bookfound
|
||||
.clone()
|
||||
.unwrap()
|
||||
.subject_people
|
||||
.clone()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|s| s.name.clone())
|
||||
.collect(),
|
||||
);
|
||||
} else {
|
||||
persons = None;
|
||||
}
|
||||
let places: Option<Vec<String>>;
|
||||
if !bookfound.unwrap().subject_places.is_none() {
|
||||
places = Some(bookfound.clone().unwrap().subject_places.clone().unwrap().iter().map(|s| s.name.clone()).collect());
|
||||
places = Some(
|
||||
bookfound
|
||||
.clone()
|
||||
.unwrap()
|
||||
.subject_places
|
||||
.clone()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|s| s.name.clone())
|
||||
.collect(),
|
||||
);
|
||||
} else {
|
||||
places = None;
|
||||
}
|
||||
let subjects: Option<Vec<String>>;
|
||||
if !bookfound.unwrap().subjects.is_none() {
|
||||
subjects = Some(bookfound.clone().unwrap().subjects.clone().unwrap().iter().map(|s| s.name.clone()).collect());
|
||||
subjects = Some(
|
||||
bookfound
|
||||
.clone()
|
||||
.unwrap()
|
||||
.subjects
|
||||
.clone()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|s| s.name.clone())
|
||||
.collect(),
|
||||
);
|
||||
} else {
|
||||
subjects = None;
|
||||
}
|
||||
let times: Option<Vec<String>>;
|
||||
if !bookfound.unwrap().subject_times.is_none() {
|
||||
times = Some(bookfound.clone().unwrap().subject_times.clone().unwrap().iter().map(|s| s.name.clone()).collect());
|
||||
times = Some(
|
||||
bookfound
|
||||
.clone()
|
||||
.unwrap()
|
||||
.subject_times
|
||||
.clone()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|s| s.name.clone())
|
||||
.collect(),
|
||||
);
|
||||
} else {
|
||||
times = None;
|
||||
}
|
||||
@@ -446,7 +538,7 @@ async fn create_by_isbn(
|
||||
place: places,
|
||||
subject: subjects,
|
||||
time: times,
|
||||
isbn: Some(vec![isbnstring.split("ISBN:").last().unwrap().to_string()])
|
||||
isbn: Some(vec![isbnstring.split("ISBN:").last().unwrap().to_string()]),
|
||||
};
|
||||
doc_sent.set_descriptions().await;
|
||||
let book: book::Model = book::Model {
|
||||
@@ -488,7 +580,6 @@ async fn create_by_isbn(
|
||||
MutationCore::create_book_person(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for place in doc_sent.place.as_ref().unwrap().iter() {
|
||||
let record: book_place::Model = book_place::Model {
|
||||
@@ -499,7 +590,6 @@ async fn create_by_isbn(
|
||||
MutationCore::create_book_place(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for subject in doc_sent.subject.as_ref().unwrap().iter() {
|
||||
let record: book_subject::Model = book_subject::Model {
|
||||
@@ -510,7 +600,6 @@ async fn create_by_isbn(
|
||||
MutationCore::create_book_subject(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for time in doc_sent.time.as_ref().unwrap().iter() {
|
||||
let record: book_time::Model = book_time::Model {
|
||||
@@ -521,7 +610,6 @@ async fn create_by_isbn(
|
||||
MutationCore::create_book_time(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for isbn in doc_sent.isbn.as_ref().unwrap().iter() {
|
||||
let record: book_isbn::Model = book_isbn::Model {
|
||||
@@ -532,7 +620,6 @@ async fn create_by_isbn(
|
||||
MutationCore::create_book_isbn(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
let book_meili = BookMeili {
|
||||
id: doc_sent.id,
|
||||
@@ -563,7 +650,6 @@ async fn create_by_isbn(
|
||||
return "Done";
|
||||
}
|
||||
|
||||
|
||||
async fn search_openlibrary(
|
||||
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
|
||||
) -> impl IntoResponse {
|
||||
@@ -583,8 +669,7 @@ let mut vec = Vec::with_capacity(12);
|
||||
if doc.id_goodreads.is_some() {
|
||||
goodread = doc.id_goodreads.unwrap().get(0).unwrap().to_string();
|
||||
}
|
||||
vec.push(
|
||||
BookUI{
|
||||
vec.push(BookUI {
|
||||
id: -((i + 1) as i32),
|
||||
open_library_key: Some(doc.key),
|
||||
title: doc.title,
|
||||
@@ -603,9 +688,8 @@ let mut vec = Vec::with_capacity(12);
|
||||
place: doc.place,
|
||||
subject: doc.subject,
|
||||
time: doc.time,
|
||||
isbn: doc.isbn
|
||||
}
|
||||
);
|
||||
isbn: doc.isbn,
|
||||
});
|
||||
}
|
||||
return Json(vec);
|
||||
}
|
||||
@@ -628,8 +712,6 @@ async fn list_book(
|
||||
Extension(ref conn): Extension<DatabaseConnection>,
|
||||
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
|
||||
) -> impl IntoResponse {
|
||||
|
||||
|
||||
dotenvy::dotenv().ok();
|
||||
let backend_url = env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file");
|
||||
|
||||
@@ -665,25 +747,66 @@ let mut resbooks: Vec<BookUI> = Vec::with_capacity(per_page);
|
||||
time_added: bookandmeta.clone().book.time_added,
|
||||
rating: bookandmeta.clone().book.rating,
|
||||
comments: bookandmeta.clone().book.comments,
|
||||
author_name: Some(bookandmeta.clone().authors.into_iter().map(|u| u.author_name).collect() ),
|
||||
person: Some(bookandmeta.clone().persons.into_iter().map(|u| u.person).collect()),
|
||||
place: Some(bookandmeta.clone().places.into_iter().map(|u| u.place).collect()),
|
||||
subject: Some(bookandmeta.clone().subjects.into_iter().map(|u| u.subject).collect()),
|
||||
time: Some(bookandmeta.clone().times.into_iter().map(|u| u.time).collect()),
|
||||
isbn: Some(bookandmeta.clone().isbns.into_iter().map(|u| u.isbn).collect()),
|
||||
author_name: Some(
|
||||
bookandmeta
|
||||
.clone()
|
||||
.authors
|
||||
.into_iter()
|
||||
.map(|u| u.author_name)
|
||||
.collect(),
|
||||
),
|
||||
person: Some(
|
||||
bookandmeta
|
||||
.clone()
|
||||
.persons
|
||||
.into_iter()
|
||||
.map(|u| u.person)
|
||||
.collect(),
|
||||
),
|
||||
place: Some(
|
||||
bookandmeta
|
||||
.clone()
|
||||
.places
|
||||
.into_iter()
|
||||
.map(|u| u.place)
|
||||
.collect(),
|
||||
),
|
||||
subject: Some(
|
||||
bookandmeta
|
||||
.clone()
|
||||
.subjects
|
||||
.into_iter()
|
||||
.map(|u| u.subject)
|
||||
.collect(),
|
||||
),
|
||||
time: Some(
|
||||
bookandmeta
|
||||
.clone()
|
||||
.times
|
||||
.into_iter()
|
||||
.map(|u| u.time)
|
||||
.collect(),
|
||||
),
|
||||
isbn: Some(
|
||||
bookandmeta
|
||||
.clone()
|
||||
.isbns
|
||||
.into_iter()
|
||||
.map(|u| u.isbn)
|
||||
.collect(),
|
||||
),
|
||||
};
|
||||
resbooks.push(bookui);
|
||||
}
|
||||
|
||||
let res = PaginatedBookUIList {
|
||||
num_pages: books.1 as u32,
|
||||
books: resbooks
|
||||
books: resbooks,
|
||||
};
|
||||
return Json(res);
|
||||
// "success"
|
||||
}
|
||||
|
||||
|
||||
async fn list_search_book(
|
||||
Extension(ref meili_client): Extension<Client>,
|
||||
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
|
||||
@@ -695,7 +818,6 @@ async fn list_search_book(
|
||||
dotenvy::dotenv().ok();
|
||||
let backend_url = env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file");
|
||||
|
||||
|
||||
let books = booksman_search::search_book(search, page, userid, meili_client)
|
||||
.await
|
||||
.expect("could not list books");
|
||||
@@ -735,13 +857,12 @@ let mut resbooks: Vec<BookUI> = Vec::with_capacity(12);
|
||||
|
||||
let res = PaginatedBookUIList {
|
||||
num_pages: (books.1 / 12 + 1) as u32,
|
||||
books: resbooks
|
||||
books: resbooks,
|
||||
};
|
||||
return Json(res);
|
||||
// "success"
|
||||
}
|
||||
|
||||
|
||||
async fn create_book(
|
||||
Extension(ref conn): Extension<DatabaseConnection>,
|
||||
Extension(ref meili_client): Extension<Client>,
|
||||
@@ -765,11 +886,22 @@ async fn create_book(
|
||||
|
||||
if !doc_sent.cover.is_none() {
|
||||
if !doc_sent.cover.clone().unwrap().is_empty() {
|
||||
let img_bytes = reqwest::get(cover.unwrap()).await.unwrap().bytes().await.unwrap();
|
||||
let img_bytes = reqwest::get(cover.unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
let image = image::load_from_memory(&img_bytes).unwrap();
|
||||
let temp_cover = doc_sent.cover.clone().unwrap();
|
||||
let img_id = format!("{}{}",Local::now().format("%Y-%m-%d-%H-%M-%S"),temp_cover.split("/").last().unwrap());
|
||||
image.save(format!("{}/{}",images_dir,img_id)).expect("Failed to save image");
|
||||
let img_id = format!(
|
||||
"{}{}",
|
||||
Local::now().format("%Y-%m-%d-%H-%M-%S"),
|
||||
temp_cover.split("/").last().unwrap()
|
||||
);
|
||||
image
|
||||
.save(format!("{}/{}", images_dir, img_id))
|
||||
.expect("Failed to save image");
|
||||
cover = Some(img_id.to_string());
|
||||
}
|
||||
}
|
||||
@@ -794,7 +926,12 @@ async fn create_book(
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
for author_name in doc_sent.author_name.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for author_name in doc_sent
|
||||
.author_name
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_author::Model = book_author::Model {
|
||||
id: 1,
|
||||
book_id: (created_book.last_insert_id),
|
||||
@@ -804,7 +941,12 @@ async fn create_book(
|
||||
.await
|
||||
.expect("could not create book");
|
||||
}
|
||||
for person in doc_sent.person.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for person in doc_sent
|
||||
.person
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_person::Model = book_person::Model {
|
||||
id: 1,
|
||||
book_id: (created_book.last_insert_id),
|
||||
@@ -813,9 +955,13 @@ async fn create_book(
|
||||
MutationCore::create_book_person(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for place in doc_sent.place.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for place in doc_sent
|
||||
.place
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_place::Model = book_place::Model {
|
||||
id: 1,
|
||||
book_id: (created_book.last_insert_id),
|
||||
@@ -824,9 +970,13 @@ async fn create_book(
|
||||
MutationCore::create_book_place(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for subject in doc_sent.subject.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for subject in doc_sent
|
||||
.subject
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_subject::Model = book_subject::Model {
|
||||
id: 1,
|
||||
book_id: (created_book.last_insert_id),
|
||||
@@ -835,9 +985,13 @@ async fn create_book(
|
||||
MutationCore::create_book_subject(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for time in doc_sent.time.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for time in doc_sent
|
||||
.time
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_time::Model = book_time::Model {
|
||||
id: 1,
|
||||
book_id: (created_book.last_insert_id),
|
||||
@@ -846,9 +1000,13 @@ async fn create_book(
|
||||
MutationCore::create_book_time(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for isbn in doc_sent.isbn.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for isbn in doc_sent
|
||||
.isbn
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_isbn::Model = book_isbn::Model {
|
||||
id: 1,
|
||||
book_id: (created_book.last_insert_id),
|
||||
@@ -857,7 +1015,6 @@ async fn create_book(
|
||||
MutationCore::create_book_isbn(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
let book_meili = BookMeili {
|
||||
id: doc_sent.id,
|
||||
@@ -882,12 +1039,9 @@ async fn create_book(
|
||||
};
|
||||
booksman_search::create_or_update_book(book_meili, userid, meili_client).await;
|
||||
|
||||
|
||||
"success"
|
||||
}
|
||||
|
||||
|
||||
|
||||
async fn update_book(
|
||||
Extension(ref conn): Extension<DatabaseConnection>,
|
||||
Extension(ref meili_client): Extension<Client>,
|
||||
@@ -905,14 +1059,33 @@ let mut cover = doc_sent.cover.clone();
|
||||
if !doc_sent.cover.is_none() {
|
||||
if !doc_sent.cover.clone().unwrap().is_empty() {
|
||||
if doc_sent.cover.clone().unwrap().contains(&backend_url) {
|
||||
cover = Some(doc_sent.cover.clone().unwrap().split("/").last().unwrap().to_string());
|
||||
}
|
||||
else {
|
||||
let img_bytes = reqwest::get(cover.unwrap()).await.unwrap().bytes().await.unwrap();
|
||||
cover = Some(
|
||||
doc_sent
|
||||
.cover
|
||||
.clone()
|
||||
.unwrap()
|
||||
.split("/")
|
||||
.last()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
);
|
||||
} else {
|
||||
let img_bytes = reqwest::get(cover.unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
.bytes()
|
||||
.await
|
||||
.unwrap();
|
||||
let image = image::load_from_memory(&img_bytes).unwrap();
|
||||
let temp_cover = doc_sent.cover.clone().unwrap();
|
||||
let img_id = format!("{}{}",Local::now().format("%Y-%m-%d-%H-%M-%S"),temp_cover.split("/").last().unwrap());
|
||||
image.save(format!("{}/{}",images_dir,img_id)).expect("Failed to save image");
|
||||
let img_id = format!(
|
||||
"{}{}",
|
||||
Local::now().format("%Y-%m-%d-%H-%M-%S"),
|
||||
temp_cover.split("/").last().unwrap()
|
||||
);
|
||||
image
|
||||
.save(format!("{}/{}", images_dir, img_id))
|
||||
.expect("Failed to save image");
|
||||
cover = Some(img_id.to_string());
|
||||
}
|
||||
}
|
||||
@@ -960,7 +1133,12 @@ let book: book::Model = book::Model{
|
||||
.await
|
||||
.expect("could not delete book isbns while updating");
|
||||
|
||||
for author_name in doc_sent.author_name.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for author_name in doc_sent
|
||||
.author_name
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_author::Model = book_author::Model {
|
||||
id: 1,
|
||||
book_id: doc_sent.id,
|
||||
@@ -970,7 +1148,12 @@ let book: book::Model = book::Model{
|
||||
.await
|
||||
.expect("could not create book");
|
||||
}
|
||||
for person in doc_sent.person.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for person in doc_sent
|
||||
.person
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_person::Model = book_person::Model {
|
||||
id: 1,
|
||||
book_id: doc_sent.id,
|
||||
@@ -979,9 +1162,13 @@ let book: book::Model = book::Model{
|
||||
MutationCore::create_book_person(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for place in doc_sent.place.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for place in doc_sent
|
||||
.place
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_place::Model = book_place::Model {
|
||||
id: 1,
|
||||
book_id: doc_sent.id,
|
||||
@@ -990,9 +1177,13 @@ let book: book::Model = book::Model{
|
||||
MutationCore::create_book_place(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for subject in doc_sent.subject.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for subject in doc_sent
|
||||
.subject
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_subject::Model = book_subject::Model {
|
||||
id: 1,
|
||||
book_id: doc_sent.id,
|
||||
@@ -1001,9 +1192,13 @@ let book: book::Model = book::Model{
|
||||
MutationCore::create_book_subject(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for time in doc_sent.time.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for time in doc_sent
|
||||
.time
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_time::Model = book_time::Model {
|
||||
id: 1,
|
||||
book_id: doc_sent.id,
|
||||
@@ -1012,9 +1207,13 @@ let book: book::Model = book::Model{
|
||||
MutationCore::create_book_time(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
for isbn in doc_sent.isbn.as_ref().unwrap_or(&vec!["".to_string()]).iter() {
|
||||
for isbn in doc_sent
|
||||
.isbn
|
||||
.as_ref()
|
||||
.unwrap_or(&vec!["".to_string()])
|
||||
.iter()
|
||||
{
|
||||
let record: book_isbn::Model = book_isbn::Model {
|
||||
id: 1,
|
||||
book_id: doc_sent.id,
|
||||
@@ -1023,7 +1222,6 @@ let book: book::Model = book::Model{
|
||||
MutationCore::create_book_isbn(conn, record)
|
||||
.await
|
||||
.expect("could not create book");
|
||||
|
||||
}
|
||||
|
||||
let book_meili = BookMeili {
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
pub mod entities;
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ impl MigrationTrait for Migration {
|
||||
// Replace the sample below with your own migration scripts
|
||||
//todo!();
|
||||
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
@@ -23,12 +22,17 @@ impl MigrationTrait for Migration {
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(ColumnDef::new(User::UserName).string().unique_key().not_null())
|
||||
.col(
|
||||
ColumnDef::new(User::UserName)
|
||||
.string()
|
||||
.unique_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(User::PasswordHash).string().not_null())
|
||||
.to_owned(),
|
||||
)
|
||||
.await.expect("Migration failed");
|
||||
|
||||
.await
|
||||
.expect("Migration failed");
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
@@ -65,7 +69,8 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await.expect("Migration failed");
|
||||
.await
|
||||
.expect("Migration failed");
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
@@ -91,7 +96,8 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await.expect("Migration failed");
|
||||
.await
|
||||
.expect("Migration failed");
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
@@ -117,7 +123,8 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await.expect("Migration failed");
|
||||
.await
|
||||
.expect("Migration failed");
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
@@ -143,7 +150,8 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await.expect("Migration failed");
|
||||
.await
|
||||
.expect("Migration failed");
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
@@ -169,7 +177,8 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await.expect("Migration failed");
|
||||
.await
|
||||
.expect("Migration failed");
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
@@ -195,7 +204,8 @@ impl MigrationTrait for Migration {
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await.expect("Migration failed");
|
||||
.await
|
||||
.expect("Migration failed");
|
||||
|
||||
manager
|
||||
.create_table(
|
||||
@@ -230,22 +240,28 @@ impl MigrationTrait for Migration {
|
||||
|
||||
manager
|
||||
.drop_table(Table::drop().table(Book::Table).to_owned())
|
||||
.await.expect("Drop failed");
|
||||
.await
|
||||
.expect("Drop failed");
|
||||
manager
|
||||
.drop_table(Table::drop().table(BookAuthor::Table).to_owned())
|
||||
.await.expect("Drop failed");
|
||||
.await
|
||||
.expect("Drop failed");
|
||||
manager
|
||||
.drop_table(Table::drop().table(BookPerson::Table).to_owned())
|
||||
.await.expect("Drop failed");
|
||||
.await
|
||||
.expect("Drop failed");
|
||||
manager
|
||||
.drop_table(Table::drop().table(BookPlace::Table).to_owned())
|
||||
.await.expect("Drop failed");
|
||||
.await
|
||||
.expect("Drop failed");
|
||||
manager
|
||||
.drop_table(Table::drop().table(BookSubject::Table).to_owned())
|
||||
.await.expect("Drop failed");
|
||||
.await
|
||||
.expect("Drop failed");
|
||||
manager
|
||||
.drop_table(Table::drop().table(BookTime::Table).to_owned())
|
||||
.await.expect("Drop failed");
|
||||
.await
|
||||
.expect("Drop failed");
|
||||
manager
|
||||
.drop_table(Table::drop().table(BookISBN::Table).to_owned())
|
||||
.await
|
||||
@@ -275,7 +291,7 @@ enum Book {
|
||||
TimeAdded,
|
||||
Rating,
|
||||
Comments,
|
||||
UserId
|
||||
UserId,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
//use ::entity::entities::prelude::Book;
|
||||
//use ::entity::entities::{prelude::*, *};
|
||||
use ::entity::entities::user::Entity as User;
|
||||
use ::entity::entities::book::Entity as Book;
|
||||
use ::entity::entities::user::Entity as User;
|
||||
//, book_author::Entity as Author, book_person::Entity as Person, book_place::Entity as Place, book_subject::Entity as Subject, book_time::Entity as Time, book_isbn::Entity as ISBN};
|
||||
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn,user};
|
||||
use ::entity::entities::{
|
||||
book, book_author, book_isbn, book_person, book_place, book_subject, book_time, user,
|
||||
};
|
||||
use sea_orm::*;
|
||||
//use ::entity::entities::prelude::Book;
|
||||
|
||||
@@ -137,7 +139,6 @@ impl Mutation {
|
||||
id: i32,
|
||||
form_data: book::Model,
|
||||
) -> Result<book::Model, DbErr> {
|
||||
|
||||
let book: book::ActiveModel = Book::find_by_id(id)
|
||||
.one(db)
|
||||
.await?
|
||||
@@ -159,7 +160,9 @@ impl Mutation {
|
||||
rating: Set(form_data.rating.to_owned()),
|
||||
comments: Set(form_data.comments.to_owned()),
|
||||
user_id: Set(form_data.user_id.to_owned()),
|
||||
}.update(db).await
|
||||
}
|
||||
.update(db)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_book(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||
@@ -172,53 +175,48 @@ impl Mutation {
|
||||
book.delete(db).await
|
||||
}
|
||||
|
||||
|
||||
pub async fn delete_book_author(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||
book_author::Entity::delete_many().filter(
|
||||
Condition::any()
|
||||
.add(book_author::Column::BookId.eq(id))
|
||||
).exec(db).await
|
||||
book_author::Entity::delete_many()
|
||||
.filter(Condition::any().add(book_author::Column::BookId.eq(id)))
|
||||
.exec(db)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_book_person(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||
book_person::Entity::delete_many().filter(
|
||||
Condition::any()
|
||||
.add(book_person::Column::BookId.eq(id))
|
||||
).exec(db).await
|
||||
book_person::Entity::delete_many()
|
||||
.filter(Condition::any().add(book_person::Column::BookId.eq(id)))
|
||||
.exec(db)
|
||||
.await
|
||||
}
|
||||
|
||||
|
||||
pub async fn delete_book_place(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||
book_place::Entity::delete_many().filter(
|
||||
Condition::any()
|
||||
.add(book_place::Column::BookId.eq(id))
|
||||
).exec(db).await
|
||||
book_place::Entity::delete_many()
|
||||
.filter(Condition::any().add(book_place::Column::BookId.eq(id)))
|
||||
.exec(db)
|
||||
.await
|
||||
}
|
||||
|
||||
|
||||
pub async fn delete_book_subject(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||
book_subject::Entity::delete_many().filter(
|
||||
Condition::any()
|
||||
.add(book_subject::Column::BookId.eq(id))
|
||||
).exec(db).await
|
||||
book_subject::Entity::delete_many()
|
||||
.filter(Condition::any().add(book_subject::Column::BookId.eq(id)))
|
||||
.exec(db)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_book_time(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||
book_time::Entity::delete_many().filter(
|
||||
Condition::any()
|
||||
.add(book_time::Column::BookId.eq(id))
|
||||
).exec(db).await
|
||||
book_time::Entity::delete_many()
|
||||
.filter(Condition::any().add(book_time::Column::BookId.eq(id)))
|
||||
.exec(db)
|
||||
.await
|
||||
}
|
||||
|
||||
|
||||
pub async fn delete_book_isbn(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
|
||||
book_isbn::Entity::delete_many().filter(
|
||||
Condition::any()
|
||||
.add(book_isbn::Column::BookId.eq(id))
|
||||
).exec(db).await
|
||||
book_isbn::Entity::delete_many()
|
||||
.filter(Condition::any().add(book_isbn::Column::BookId.eq(id)))
|
||||
.exec(db)
|
||||
.await
|
||||
}
|
||||
|
||||
|
||||
pub async fn delete_all_books(db: &DbConn) -> Result<DeleteResult, DbErr> {
|
||||
Book::delete_many().exec(db).await
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ use ::entity::entities::book::Entity as Book;
|
||||
use ::entity::entities::user::Entity as User;
|
||||
|
||||
//, book_author::Entity as Author, book_person::Entity as Person, book_place::Entity as Place, book_subject::Entity as Subject, book_time::Entity as Time, book_isbn::Entity as ISBN};
|
||||
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn,user};
|
||||
use ::entity::entities::{
|
||||
book, book_author, book_isbn, book_person, book_place, book_subject, book_time, user,
|
||||
};
|
||||
//use ::entity::entities::{prelude::*, *};
|
||||
use sea_orm::*;
|
||||
//use sea_query::Expr;
|
||||
@@ -26,12 +28,16 @@ impl Query {
|
||||
Book::find_by_id(id).one(db).await
|
||||
}
|
||||
|
||||
|
||||
pub async fn find_userid_by_name(db: &DbConn, name: String) -> Result<Option<user::Model>, DbErr> {
|
||||
User::find().filter(user::Column::UserName.eq(name)).one(db).await
|
||||
pub async fn find_userid_by_name(
|
||||
db: &DbConn,
|
||||
name: String,
|
||||
) -> Result<Option<user::Model>, DbErr> {
|
||||
User::find()
|
||||
.filter(user::Column::UserName.eq(name))
|
||||
.one(db)
|
||||
.await
|
||||
}
|
||||
|
||||
|
||||
pub async fn find_user_by_id(db: &DbConn, id: i32) -> Result<Option<user::Model>, DbErr> {
|
||||
User::find_by_id(id).one(db).await
|
||||
}
|
||||
@@ -62,14 +68,14 @@ impl Query {
|
||||
.order_by_desc(book::Column::Id)
|
||||
.paginate(db, posts_per_page);
|
||||
let num_pages = paginator.num_pages().await?;
|
||||
return paginator.fetch_page(page - 1).await.map(|p| (p, num_pages))
|
||||
return paginator.fetch_page(page - 1).await.map(|p| (p, num_pages));
|
||||
} else {
|
||||
let paginator = Book::find()
|
||||
.filter(book::Column::UserId.eq(userid))
|
||||
.order_by_asc(book::Column::Id)
|
||||
.paginate(db, posts_per_page);
|
||||
let num_pages = paginator.num_pages().await?;
|
||||
return paginator.fetch_page(page - 1).await.map(|p| (p, num_pages))
|
||||
return paginator.fetch_page(page - 1).await.map(|p| (p, num_pages));
|
||||
}
|
||||
|
||||
// Fetch paginated posts
|
||||
@@ -83,17 +89,30 @@ pub async fn find_books_plus_meta_in_page(
|
||||
sort: String,
|
||||
) -> Result<(Vec<BookAndMetaV2>, u64), DbErr> {
|
||||
// Setup paginator
|
||||
let books = Self::find_books_in_page(db,page.try_into().unwrap(),posts_per_page.try_into().unwrap(),userid, sort).await?;
|
||||
let books = Self::find_books_in_page(
|
||||
db,
|
||||
page.try_into().unwrap(),
|
||||
posts_per_page.try_into().unwrap(),
|
||||
userid,
|
||||
sort,
|
||||
)
|
||||
.await?;
|
||||
let book_ids: Vec<i32> = books.0.clone().into_iter().map(|b| b.id).collect();
|
||||
println!("SIZE IS {} and {:?}", book_ids.len(), book_ids);
|
||||
let mut resbooks: Vec<BookAndMetaV2> = Vec::with_capacity(book_ids.len());
|
||||
for book in books.0.iter() {
|
||||
let bauthors: Vec<book_author::Model> = book.find_related(book_author::Entity).all(db).await?;
|
||||
let bpersons: Vec<book_person::Model> = book.find_related(book_person::Entity).all(db).await?;
|
||||
let bplaces: Vec<book_place::Model> = book.find_related(book_place::Entity).all(db).await?;
|
||||
let bsubjects: Vec<book_subject::Model> = book.find_related(book_subject::Entity).all(db).await?;
|
||||
let btimes: Vec<book_time::Model> = book.find_related(book_time::Entity).all(db).await?;
|
||||
let bisbns: Vec<book_isbn::Model> = book.find_related(book_isbn::Entity).all(db).await?;
|
||||
let bauthors: Vec<book_author::Model> =
|
||||
book.find_related(book_author::Entity).all(db).await?;
|
||||
let bpersons: Vec<book_person::Model> =
|
||||
book.find_related(book_person::Entity).all(db).await?;
|
||||
let bplaces: Vec<book_place::Model> =
|
||||
book.find_related(book_place::Entity).all(db).await?;
|
||||
let bsubjects: Vec<book_subject::Model> =
|
||||
book.find_related(book_subject::Entity).all(db).await?;
|
||||
let btimes: Vec<book_time::Model> =
|
||||
book.find_related(book_time::Entity).all(db).await?;
|
||||
let bisbns: Vec<book_isbn::Model> =
|
||||
book.find_related(book_isbn::Entity).all(db).await?;
|
||||
|
||||
let bookandmeta = BookAndMetaV2 {
|
||||
book: (book.clone()),
|
||||
@@ -102,14 +121,11 @@ pub async fn find_books_plus_meta_in_page(
|
||||
places: bplaces,
|
||||
subjects: bsubjects,
|
||||
times: btimes,
|
||||
isbns: bisbns
|
||||
isbns: bisbns,
|
||||
};
|
||||
resbooks.push(bookandmeta);
|
||||
|
||||
}
|
||||
|
||||
Ok((resbooks, books.1))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use sea_orm::*;
|
||||
use crate::Query;
|
||||
use axum::async_trait;
|
||||
use axum_login::{secrecy::SecretVec, AuthUser, UserStore};
|
||||
use crate::Query;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use sea_orm::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AxumUser {
|
||||
@@ -59,4 +58,3 @@ Role: PartialOrd + PartialEq + Clone + Send + Sync + 'static,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use meilisearch_sdk::client::*;
|
||||
use meilisearch_sdk::search::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct BookMeili {
|
||||
@@ -29,31 +29,33 @@ pub async fn create_or_update_book(book: BookMeili, userid: i32, client: &Client
|
||||
// An index is where the documents are stored.
|
||||
let books = client.index(format!("books{}", userid));
|
||||
// Add some movies in the index. If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
|
||||
books.add_or_replace(&[
|
||||
book
|
||||
], Some("id")).await.unwrap();
|
||||
books.add_or_replace(&[book], Some("id")).await.unwrap();
|
||||
}
|
||||
|
||||
|
||||
pub async fn delete_book(bookid: i32, userid: i32, client: &Client) {
|
||||
// An index is where the documents are stored.
|
||||
let books = client.index(format!("books{}", userid));
|
||||
books.delete_document(bookid).await.unwrap();
|
||||
}
|
||||
|
||||
|
||||
pub async fn search_book(search: &str, page: usize, userid: i32, client: &Client) -> Result<(Vec<BookMeili>, usize), meilisearch_sdk::errors::Error> {
|
||||
pub async fn search_book(
|
||||
search: &str,
|
||||
page: usize,
|
||||
userid: i32,
|
||||
client: &Client,
|
||||
) -> Result<(Vec<BookMeili>, usize), meilisearch_sdk::errors::Error> {
|
||||
// An index is where the documents are stored.
|
||||
let books = client.index(format!("books{}", userid));
|
||||
let results : SearchResults<BookMeili> = books.search().with_query(search).with_offset((page-1)*12)
|
||||
.execute::<BookMeili>().await.unwrap();
|
||||
let results: SearchResults<BookMeili> = books
|
||||
.search()
|
||||
.with_query(search)
|
||||
.with_offset((page - 1) * 12)
|
||||
.execute::<BookMeili>()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let formatted_results : Vec<BookMeili> = (results.hits).iter().map(|r| r.result.clone()).collect();
|
||||
let formatted_results: Vec<BookMeili> =
|
||||
(results.hits).iter().map(|r| r.result.clone()).collect();
|
||||
//.iter()s.map(|r| r.formatted_result.unwrap()).collect();
|
||||
return Ok((formatted_results, results.estimated_total_hits));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
fn main() {
|
||||
booksman_api::main();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user