User Authentication and Other fixes #1

Merged
vinod merged 30 commits from user-auth into main 2023-02-05 09:01:08 +00:00
9 changed files with 1760 additions and 1145 deletions
Showing only changes of commit 02963caa73 - Show all commits

View File

@@ -1,39 +1,41 @@
use axum::{ use axum::{
extract::{Extension, Path},
http::{HeaderValue, Method, StatusCode}, http::{HeaderValue, Method, StatusCode},
response::IntoResponse, response::IntoResponse,
routing::{get,post,get_service}, routing::{get, get_service, post},
Json, Router, 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::{ use booksman_orm::{
sea_orm::{Database, DatabaseConnection}, sea_orm::{Database, DatabaseConnection},
Mutation as MutationCore, Query as QueryCore Mutation as MutationCore,
// BookAndMeta, Query as QueryCore, // BookAndMeta,
}; };
use booksman_search;
use booksman_search::BookMeili;
use clap::Parser;
use image;
use meilisearch_sdk::client::Client; 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 itertools::Itertools;
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn,user}; use ::entity::entities::{
use std::env; book, book_author, book_isbn, book_person, book_place, book_subject, book_time, user,
use migration::{Migrator, MigratorTrait}; };
use chrono::Local;
use axum_login::{ use axum_login::{
axum_sessions::{async_session::MemoryStore as SessionMemoryStore, SessionLayer}, axum_sessions::{async_session::MemoryStore as SessionMemoryStore, SessionLayer},
AuthLayer, RequireAuthorizationLayer, AuthLayer, RequireAuthorizationLayer,
}; };
use chrono::Local;
use migration::{Migrator, MigratorTrait};
use rand::Rng; use rand::Rng;
use std::env;
#[derive(Deserialize, Serialize, Debug, Clone)] #[derive(Deserialize, Serialize, Debug, Clone)]
struct BookUI { struct BookUI {
@@ -83,7 +85,6 @@ struct Books {
docs: Vec<Docs>, docs: Vec<Docs>,
} }
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
struct PaginatedBookUIList { struct PaginatedBookUIList {
num_pages: u32, num_pages: u32,
@@ -142,7 +143,6 @@ pub struct Cover {
pub medium: String, pub medium: String,
} }
impl Books { impl Books {
fn set_all_cover_urls(&mut self) { fn set_all_cover_urls(&mut self) {
for book in self.docs.iter_mut() { for book in self.docs.iter_mut() {
@@ -157,31 +157,38 @@ impl Books {
} }
} }
} }
} }
impl BookUI { impl BookUI {
async fn set_descriptions(&mut self) { async fn set_descriptions(&mut self) {
if self.open_library_key.is_some() { if self.open_library_key.is_some() {
if !(self.open_library_key.as_ref().unwrap().is_empty()) { 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 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; let description = resjson.description;
if !description.is_none() { 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); 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); self.description = Some(desc_val.value);
} }
} }
} }
} }
} }
} }
async fn handle_error(_err: io::Error) -> impl IntoResponse { async fn handle_error(_err: io::Error) -> impl IntoResponse {
@@ -209,7 +216,8 @@ struct Opt {
static_dir: String, 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] #[tokio::main]
pub async fn main() { pub async fn main() {
@@ -222,7 +230,6 @@ pub async fn main() {
// enable console logging // enable console logging
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
dotenvy::dotenv().ok(); dotenvy::dotenv().ok();
let images_dir = env::var("IMAGES_DIR").expect("IMAGES_DIR is not set in .env file"); 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"); 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 // Apply all pending migrations
Migrator::up(&conn, None).await.unwrap(); Migrator::up(&conn, None).await.unwrap();
let session_store = SessionMemoryStore::new(); let session_store = SessionMemoryStore::new();
let session_layer = SessionLayer::new(session_store, &secret).with_secure(false); let session_layer = SessionLayer::new(session_store, &secret).with_secure(false);
let user_store = booksman_orm::AxumUserStore::new(&conn); 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 meili_client = Client::new(meili_url, meili_key);
let app = Router::new() let app = Router::new()
.route("/api/create_by_isbn", get(create_by_isbn)) .route("/api/create_by_isbn", get(create_by_isbn))
.route("/api/create", post(create_book)) .route("/api/create", post(create_book))
@@ -263,8 +268,14 @@ pub async fn main() {
.route("/api/login", post(login_handler)) .route("/api/login", post(login_handler))
.route("/api/register", post(register_handler)) .route("/api/register", post(register_handler))
.route("/api/logout", post(logout_handler)) .route("/api/logout", post(logout_handler))
.nest_service("/images", get_service(ServeDir::new(images_dir)).handle_error(handle_error)) .nest_service(
.nest_service("/assets", get_service(ServeDir::new(opt.static_dir)).handle_error(handle_error)) "/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)) // .merge(SpaRouter::new("/assets", opt.static_dir))
.layer(auth_layer) .layer(auth_layer)
.layer(session_layer) .layer(session_layer)
@@ -297,26 +308,26 @@ pub async fn main() {
.expect("Unable to start server"); .expect("Unable to start server");
} }
//#[axum_macros::debug_handler] //#[axum_macros::debug_handler]
async fn register_handler(Extension(ref conn): Extension<DatabaseConnection>, async fn register_handler(
Json(user_sent): Json<booksman_orm::AxumUser>) -> impl IntoResponse { Extension(ref conn): Extension<DatabaseConnection>,
Json(user_sent): Json<booksman_orm::AxumUser>,
) -> impl IntoResponse {
// add to db // add to db
let user: user::Model = user::Model { let user: user::Model = user::Model {
id: user_sent.id, id: user_sent.id,
user_name: Some(user_sent.clone().name), user_name: Some(user_sent.clone().name),
password_hash: user_sent.clone().password_hash, 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"; return "success";
} }
async fn list_users(Extension(ref conn): Extension<DatabaseConnection>) -> impl IntoResponse {
async fn list_users( let usersmodels: Vec<user::Model> =
Extension(ref conn): Extension<DatabaseConnection>, QueryCore::list_all_users(&conn).await.unwrap_or(Vec::new());
) -> 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(); let mut users: Vec<booksman_orm::AxumUser> = Vec::new();
for usermodel in usersmodels.iter() { for usermodel in usersmodels.iter() {
let user = booksman_orm::AxumUser { let user = booksman_orm::AxumUser {
@@ -328,13 +339,20 @@ async fn list_users(
} }
return Json(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 { async fn login_handler(
let userdb : user::Model = QueryCore::find_userid_by_name(conn, user_sent.name.clone()).await.unwrap().unwrap(); 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 userid = userdb.id;
let corrected_user = booksman_orm::AxumUser { let corrected_user = booksman_orm::AxumUser {
id: userid, id: userid,
name: user_sent.name.clone(), 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(); auth.login(&corrected_user).await.unwrap();
return "success"; return "success";
@@ -354,7 +372,6 @@ async fn authentication_check(
return Json(true); return Json(true);
} }
//https://openlibrary.org/api/books?bibkeys=ISBN:9780980200447&jscmd=data&format=json //https://openlibrary.org/api/books?bibkeys=ISBN:9780980200447&jscmd=data&format=json
async fn create_by_isbn( async fn create_by_isbn(
Extension(ref conn): Extension<DatabaseConnection>, Extension(ref conn): Extension<DatabaseConnection>,
@@ -362,67 +379,142 @@ async fn create_by_isbn(
Extension(user): Extension<booksman_orm::AxumUser>, Extension(user): Extension<booksman_orm::AxumUser>,
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>, axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
) -> impl IntoResponse { ) -> impl IntoResponse {
dotenvy::dotenv().ok(); dotenvy::dotenv().ok();
let images_dir = env::var("IMAGES_DIR").expect("IMAGES_DIR is not set in .env file"); let images_dir = env::var("IMAGES_DIR").expect("IMAGES_DIR is not set in .env file");
let userid = user.id; let userid = user.id;
print!("Get items with query params: {:?}\n", params); print!("Get items with query params: {:?}\n", params);
let isbns = params.get("isbns").unwrap(); 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 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 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() { for isbnstring in splitisbns.iter() {
let bookfound = resjson.book_items.get(isbnstring); let bookfound = resjson.book_items.get(isbnstring);
if !bookfound.clone().is_none() { if !bookfound.clone().is_none() {
let mut cover_id = "".to_string(); let mut cover_id = "".to_string();
if !bookfound.unwrap().cover.is_none() { if !bookfound.unwrap().cover.is_none() {
let coverurl = bookfound.clone().unwrap().cover.clone().unwrap().medium.clone(); let coverurl = bookfound
let img_bytes = reqwest::get(coverurl.clone()).await.unwrap().bytes().await.unwrap(); .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 image = image::load_from_memory(&img_bytes).unwrap();
let temp_cover = coverurl.clone(); let temp_cover = coverurl.clone();
let img_id = temp_cover.split("/").last().unwrap(); 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(); cover_id = img_id.to_string();
} }
let mut goodread_id = "".to_string(); let mut goodread_id = "".to_string();
if !bookfound.unwrap().identifiers.is_none() { 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() { if !goodread_identifier.is_none() {
goodread_id = goodread_identifier.unwrap().get(0).unwrap().to_string() goodread_id = goodread_identifier.unwrap().get(0).unwrap().to_string()
} }
} }
//let mut authors_name = Some(vec!["".to_string()]); //let mut authors_name = Some(vec!["".to_string()]);
//if !bookfound.unwrap().authors.is_none() { //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 { //} else {
// authors_name = None // authors_name = None
//} //}
let persons: Option<Vec<String>>; let persons: Option<Vec<String>>;
//= Some(vec!["".to_string()]); //= Some(vec!["".to_string()]);
if !bookfound.unwrap().subject_people.is_none() { 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 { } else {
persons = None; persons = None;
} }
let places: Option<Vec<String>>; let places: Option<Vec<String>>;
if !bookfound.unwrap().subject_places.is_none() { 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 { } else {
places = None; places = None;
} }
let subjects: Option<Vec<String>>; let subjects: Option<Vec<String>>;
if !bookfound.unwrap().subjects.is_none() { 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 { } else {
subjects = None; subjects = None;
} }
let times: Option<Vec<String>>; let times: Option<Vec<String>>;
if !bookfound.unwrap().subject_times.is_none() { 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 { } else {
times = None; times = None;
} }
@@ -446,7 +538,7 @@ async fn create_by_isbn(
place: places, place: places,
subject: subjects, subject: subjects,
time: times, 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; doc_sent.set_descriptions().await;
let book: book::Model = book::Model { let book: book::Model = book::Model {
@@ -488,7 +580,6 @@ async fn create_by_isbn(
MutationCore::create_book_person(conn, record) MutationCore::create_book_person(conn, record)
.await .await
.expect("could not create book"); .expect("could not create book");
} }
for place in doc_sent.place.as_ref().unwrap().iter() { for place in doc_sent.place.as_ref().unwrap().iter() {
let record: book_place::Model = book_place::Model { let record: book_place::Model = book_place::Model {
@@ -499,7 +590,6 @@ async fn create_by_isbn(
MutationCore::create_book_place(conn, record) MutationCore::create_book_place(conn, record)
.await .await
.expect("could not create book"); .expect("could not create book");
} }
for subject in doc_sent.subject.as_ref().unwrap().iter() { for subject in doc_sent.subject.as_ref().unwrap().iter() {
let record: book_subject::Model = book_subject::Model { let record: book_subject::Model = book_subject::Model {
@@ -510,7 +600,6 @@ async fn create_by_isbn(
MutationCore::create_book_subject(conn, record) MutationCore::create_book_subject(conn, record)
.await .await
.expect("could not create book"); .expect("could not create book");
} }
for time in doc_sent.time.as_ref().unwrap().iter() { for time in doc_sent.time.as_ref().unwrap().iter() {
let record: book_time::Model = book_time::Model { let record: book_time::Model = book_time::Model {
@@ -521,7 +610,6 @@ async fn create_by_isbn(
MutationCore::create_book_time(conn, record) MutationCore::create_book_time(conn, record)
.await .await
.expect("could not create book"); .expect("could not create book");
} }
for isbn in doc_sent.isbn.as_ref().unwrap().iter() { for isbn in doc_sent.isbn.as_ref().unwrap().iter() {
let record: book_isbn::Model = book_isbn::Model { let record: book_isbn::Model = book_isbn::Model {
@@ -532,7 +620,6 @@ async fn create_by_isbn(
MutationCore::create_book_isbn(conn, record) MutationCore::create_book_isbn(conn, record)
.await .await
.expect("could not create book"); .expect("could not create book");
} }
let book_meili = BookMeili { let book_meili = BookMeili {
id: doc_sent.id, id: doc_sent.id,
@@ -563,7 +650,6 @@ async fn create_by_isbn(
return "Done"; return "Done";
} }
async fn search_openlibrary( async fn search_openlibrary(
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>, axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
) -> impl IntoResponse { ) -> impl IntoResponse {
@@ -583,8 +669,7 @@ let mut vec = Vec::with_capacity(12);
if doc.id_goodreads.is_some() { if doc.id_goodreads.is_some() {
goodread = doc.id_goodreads.unwrap().get(0).unwrap().to_string(); goodread = doc.id_goodreads.unwrap().get(0).unwrap().to_string();
} }
vec.push( vec.push(BookUI {
BookUI{
id: -((i + 1) as i32), id: -((i + 1) as i32),
open_library_key: Some(doc.key), open_library_key: Some(doc.key),
title: doc.title, title: doc.title,
@@ -603,9 +688,8 @@ let mut vec = Vec::with_capacity(12);
place: doc.place, place: doc.place,
subject: doc.subject, subject: doc.subject,
time: doc.time, time: doc.time,
isbn: doc.isbn isbn: doc.isbn,
} });
);
} }
return Json(vec); return Json(vec);
} }
@@ -628,8 +712,6 @@ async fn list_book(
Extension(ref conn): Extension<DatabaseConnection>, Extension(ref conn): Extension<DatabaseConnection>,
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>, axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
) -> impl IntoResponse { ) -> impl IntoResponse {
dotenvy::dotenv().ok(); dotenvy::dotenv().ok();
let backend_url = env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file"); 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, time_added: bookandmeta.clone().book.time_added,
rating: bookandmeta.clone().book.rating, rating: bookandmeta.clone().book.rating,
comments: bookandmeta.clone().book.comments, comments: bookandmeta.clone().book.comments,
author_name: Some(bookandmeta.clone().authors.into_iter().map(|u| u.author_name).collect() ), author_name: Some(
person: Some(bookandmeta.clone().persons.into_iter().map(|u| u.person).collect()), bookandmeta
place: Some(bookandmeta.clone().places.into_iter().map(|u| u.place).collect()), .clone()
subject: Some(bookandmeta.clone().subjects.into_iter().map(|u| u.subject).collect()), .authors
time: Some(bookandmeta.clone().times.into_iter().map(|u| u.time).collect()), .into_iter()
isbn: Some(bookandmeta.clone().isbns.into_iter().map(|u| u.isbn).collect()), .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); resbooks.push(bookui);
} }
let res = PaginatedBookUIList { let res = PaginatedBookUIList {
num_pages: books.1 as u32, num_pages: books.1 as u32,
books: resbooks books: resbooks,
}; };
return Json(res); return Json(res);
// "success" // "success"
} }
async fn list_search_book( async fn list_search_book(
Extension(ref meili_client): Extension<Client>, Extension(ref meili_client): Extension<Client>,
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>, axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
@@ -695,7 +818,6 @@ async fn list_search_book(
dotenvy::dotenv().ok(); dotenvy::dotenv().ok();
let backend_url = env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file"); 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) let books = booksman_search::search_book(search, page, userid, meili_client)
.await .await
.expect("could not list books"); .expect("could not list books");
@@ -735,13 +857,12 @@ let mut resbooks: Vec<BookUI> = Vec::with_capacity(12);
let res = PaginatedBookUIList { let res = PaginatedBookUIList {
num_pages: (books.1 / 12 + 1) as u32, num_pages: (books.1 / 12 + 1) as u32,
books: resbooks books: resbooks,
}; };
return Json(res); return Json(res);
// "success" // "success"
} }
async fn create_book( async fn create_book(
Extension(ref conn): Extension<DatabaseConnection>, Extension(ref conn): Extension<DatabaseConnection>,
Extension(ref meili_client): Extension<Client>, Extension(ref meili_client): Extension<Client>,
@@ -765,11 +886,22 @@ async fn create_book(
if !doc_sent.cover.is_none() { if !doc_sent.cover.is_none() {
if !doc_sent.cover.clone().unwrap().is_empty() { 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 image = image::load_from_memory(&img_bytes).unwrap();
let temp_cover = doc_sent.cover.clone().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()); let img_id = format!(
image.save(format!("{}/{}",images_dir,img_id)).expect("Failed to save image"); "{}{}",
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()); cover = Some(img_id.to_string());
} }
} }
@@ -794,7 +926,12 @@ async fn create_book(
.await .await
.expect("could not create book"); .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 { let record: book_author::Model = book_author::Model {
id: 1, id: 1,
book_id: (created_book.last_insert_id), book_id: (created_book.last_insert_id),
@@ -804,7 +941,12 @@ async fn create_book(
.await .await
.expect("could not create book"); .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 { let record: book_person::Model = book_person::Model {
id: 1, id: 1,
book_id: (created_book.last_insert_id), book_id: (created_book.last_insert_id),
@@ -813,9 +955,13 @@ async fn create_book(
MutationCore::create_book_person(conn, record) MutationCore::create_book_person(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_place::Model = book_place::Model {
id: 1, id: 1,
book_id: (created_book.last_insert_id), book_id: (created_book.last_insert_id),
@@ -824,9 +970,13 @@ async fn create_book(
MutationCore::create_book_place(conn, record) MutationCore::create_book_place(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_subject::Model = book_subject::Model {
id: 1, id: 1,
book_id: (created_book.last_insert_id), book_id: (created_book.last_insert_id),
@@ -835,9 +985,13 @@ async fn create_book(
MutationCore::create_book_subject(conn, record) MutationCore::create_book_subject(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_time::Model = book_time::Model {
id: 1, id: 1,
book_id: (created_book.last_insert_id), book_id: (created_book.last_insert_id),
@@ -846,9 +1000,13 @@ async fn create_book(
MutationCore::create_book_time(conn, record) MutationCore::create_book_time(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_isbn::Model = book_isbn::Model {
id: 1, id: 1,
book_id: (created_book.last_insert_id), book_id: (created_book.last_insert_id),
@@ -857,7 +1015,6 @@ async fn create_book(
MutationCore::create_book_isbn(conn, record) MutationCore::create_book_isbn(conn, record)
.await .await
.expect("could not create book"); .expect("could not create book");
} }
let book_meili = BookMeili { let book_meili = BookMeili {
id: doc_sent.id, id: doc_sent.id,
@@ -882,12 +1039,9 @@ async fn create_book(
}; };
booksman_search::create_or_update_book(book_meili, userid, meili_client).await; booksman_search::create_or_update_book(book_meili, userid, meili_client).await;
"success" "success"
} }
async fn update_book( async fn update_book(
Extension(ref conn): Extension<DatabaseConnection>, Extension(ref conn): Extension<DatabaseConnection>,
Extension(ref meili_client): Extension<Client>, 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.is_none() {
if !doc_sent.cover.clone().unwrap().is_empty() { if !doc_sent.cover.clone().unwrap().is_empty() {
if doc_sent.cover.clone().unwrap().contains(&backend_url) { if doc_sent.cover.clone().unwrap().contains(&backend_url) {
cover = Some(doc_sent.cover.clone().unwrap().split("/").last().unwrap().to_string()); cover = Some(
} doc_sent
else { .cover
let img_bytes = reqwest::get(cover.unwrap()).await.unwrap().bytes().await.unwrap(); .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 image = image::load_from_memory(&img_bytes).unwrap();
let temp_cover = doc_sent.cover.clone().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()); let img_id = format!(
image.save(format!("{}/{}",images_dir,img_id)).expect("Failed to save image"); "{}{}",
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()); cover = Some(img_id.to_string());
} }
} }
@@ -960,7 +1133,12 @@ let book: book::Model = book::Model{
.await .await
.expect("could not delete book isbns while updating"); .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 { let record: book_author::Model = book_author::Model {
id: 1, id: 1,
book_id: doc_sent.id, book_id: doc_sent.id,
@@ -970,7 +1148,12 @@ let book: book::Model = book::Model{
.await .await
.expect("could not create book"); .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 { let record: book_person::Model = book_person::Model {
id: 1, id: 1,
book_id: doc_sent.id, book_id: doc_sent.id,
@@ -979,9 +1162,13 @@ let book: book::Model = book::Model{
MutationCore::create_book_person(conn, record) MutationCore::create_book_person(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_place::Model = book_place::Model {
id: 1, id: 1,
book_id: doc_sent.id, book_id: doc_sent.id,
@@ -990,9 +1177,13 @@ let book: book::Model = book::Model{
MutationCore::create_book_place(conn, record) MutationCore::create_book_place(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_subject::Model = book_subject::Model {
id: 1, id: 1,
book_id: doc_sent.id, book_id: doc_sent.id,
@@ -1001,9 +1192,13 @@ let book: book::Model = book::Model{
MutationCore::create_book_subject(conn, record) MutationCore::create_book_subject(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_time::Model = book_time::Model {
id: 1, id: 1,
book_id: doc_sent.id, book_id: doc_sent.id,
@@ -1012,9 +1207,13 @@ let book: book::Model = book::Model{
MutationCore::create_book_time(conn, record) MutationCore::create_book_time(conn, record)
.await .await
.expect("could not create book"); .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 { let record: book_isbn::Model = book_isbn::Model {
id: 1, id: 1,
book_id: doc_sent.id, book_id: doc_sent.id,
@@ -1023,7 +1222,6 @@ let book: book::Model = book::Model{
MutationCore::create_book_isbn(conn, record) MutationCore::create_book_isbn(conn, record)
.await .await
.expect("could not create book"); .expect("could not create book");
} }
let book_meili = BookMeili { let book_meili = BookMeili {

View File

@@ -1,3 +1 @@
pub mod entities; pub mod entities;

View File

@@ -10,7 +10,6 @@ impl MigrationTrait for Migration {
// Replace the sample below with your own migration scripts // Replace the sample below with your own migration scripts
//todo!(); //todo!();
manager manager
.create_table( .create_table(
Table::create() Table::create()
@@ -23,12 +22,17 @@ impl MigrationTrait for Migration {
.auto_increment() .auto_increment()
.primary_key(), .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()) .col(ColumnDef::new(User::PasswordHash).string().not_null())
.to_owned(), .to_owned(),
) )
.await.expect("Migration failed"); .await
.expect("Migration failed");
manager manager
.create_table( .create_table(
@@ -65,7 +69,8 @@ impl MigrationTrait for Migration {
) )
.to_owned(), .to_owned(),
) )
.await.expect("Migration failed"); .await
.expect("Migration failed");
manager manager
.create_table( .create_table(
@@ -91,7 +96,8 @@ impl MigrationTrait for Migration {
) )
.to_owned(), .to_owned(),
) )
.await.expect("Migration failed"); .await
.expect("Migration failed");
manager manager
.create_table( .create_table(
@@ -117,7 +123,8 @@ impl MigrationTrait for Migration {
) )
.to_owned(), .to_owned(),
) )
.await.expect("Migration failed"); .await
.expect("Migration failed");
manager manager
.create_table( .create_table(
@@ -143,7 +150,8 @@ impl MigrationTrait for Migration {
) )
.to_owned(), .to_owned(),
) )
.await.expect("Migration failed"); .await
.expect("Migration failed");
manager manager
.create_table( .create_table(
@@ -169,7 +177,8 @@ impl MigrationTrait for Migration {
) )
.to_owned(), .to_owned(),
) )
.await.expect("Migration failed"); .await
.expect("Migration failed");
manager manager
.create_table( .create_table(
@@ -195,7 +204,8 @@ impl MigrationTrait for Migration {
) )
.to_owned(), .to_owned(),
) )
.await.expect("Migration failed"); .await
.expect("Migration failed");
manager manager
.create_table( .create_table(
@@ -230,22 +240,28 @@ impl MigrationTrait for Migration {
manager manager
.drop_table(Table::drop().table(Book::Table).to_owned()) .drop_table(Table::drop().table(Book::Table).to_owned())
.await.expect("Drop failed"); .await
.expect("Drop failed");
manager manager
.drop_table(Table::drop().table(BookAuthor::Table).to_owned()) .drop_table(Table::drop().table(BookAuthor::Table).to_owned())
.await.expect("Drop failed"); .await
.expect("Drop failed");
manager manager
.drop_table(Table::drop().table(BookPerson::Table).to_owned()) .drop_table(Table::drop().table(BookPerson::Table).to_owned())
.await.expect("Drop failed"); .await
.expect("Drop failed");
manager manager
.drop_table(Table::drop().table(BookPlace::Table).to_owned()) .drop_table(Table::drop().table(BookPlace::Table).to_owned())
.await.expect("Drop failed"); .await
.expect("Drop failed");
manager manager
.drop_table(Table::drop().table(BookSubject::Table).to_owned()) .drop_table(Table::drop().table(BookSubject::Table).to_owned())
.await.expect("Drop failed"); .await
.expect("Drop failed");
manager manager
.drop_table(Table::drop().table(BookTime::Table).to_owned()) .drop_table(Table::drop().table(BookTime::Table).to_owned())
.await.expect("Drop failed"); .await
.expect("Drop failed");
manager manager
.drop_table(Table::drop().table(BookISBN::Table).to_owned()) .drop_table(Table::drop().table(BookISBN::Table).to_owned())
.await .await
@@ -275,7 +291,7 @@ enum Book {
TimeAdded, TimeAdded,
Rating, Rating,
Comments, Comments,
UserId UserId,
} }
#[derive(Iden)] #[derive(Iden)]

View File

@@ -1,9 +1,11 @@
//use ::entity::entities::prelude::Book; //use ::entity::entities::prelude::Book;
//use ::entity::entities::{prelude::*, *}; //use ::entity::entities::{prelude::*, *};
use ::entity::entities::user::Entity as User;
use ::entity::entities::book::Entity as Book; 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}; //, 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 sea_orm::*;
//use ::entity::entities::prelude::Book; //use ::entity::entities::prelude::Book;
@@ -137,7 +139,6 @@ impl Mutation {
id: i32, id: i32,
form_data: book::Model, form_data: book::Model,
) -> Result<book::Model, DbErr> { ) -> Result<book::Model, DbErr> {
let book: book::ActiveModel = Book::find_by_id(id) let book: book::ActiveModel = Book::find_by_id(id)
.one(db) .one(db)
.await? .await?
@@ -159,7 +160,9 @@ impl Mutation {
rating: Set(form_data.rating.to_owned()), rating: Set(form_data.rating.to_owned()),
comments: Set(form_data.comments.to_owned()), comments: Set(form_data.comments.to_owned()),
user_id: Set(form_data.user_id.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> { pub async fn delete_book(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
@@ -172,53 +175,48 @@ impl Mutation {
book.delete(db).await book.delete(db).await
} }
pub async fn delete_book_author(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> { pub async fn delete_book_author(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
book_author::Entity::delete_many().filter( book_author::Entity::delete_many()
Condition::any() .filter(Condition::any().add(book_author::Column::BookId.eq(id)))
.add(book_author::Column::BookId.eq(id)) .exec(db)
).exec(db).await .await
} }
pub async fn delete_book_person(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> { pub async fn delete_book_person(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
book_person::Entity::delete_many().filter( book_person::Entity::delete_many()
Condition::any() .filter(Condition::any().add(book_person::Column::BookId.eq(id)))
.add(book_person::Column::BookId.eq(id)) .exec(db)
).exec(db).await .await
} }
pub async fn delete_book_place(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> { pub async fn delete_book_place(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
book_place::Entity::delete_many().filter( book_place::Entity::delete_many()
Condition::any() .filter(Condition::any().add(book_place::Column::BookId.eq(id)))
.add(book_place::Column::BookId.eq(id)) .exec(db)
).exec(db).await .await
} }
pub async fn delete_book_subject(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> { pub async fn delete_book_subject(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
book_subject::Entity::delete_many().filter( book_subject::Entity::delete_many()
Condition::any() .filter(Condition::any().add(book_subject::Column::BookId.eq(id)))
.add(book_subject::Column::BookId.eq(id)) .exec(db)
).exec(db).await .await
} }
pub async fn delete_book_time(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> { pub async fn delete_book_time(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
book_time::Entity::delete_many().filter( book_time::Entity::delete_many()
Condition::any() .filter(Condition::any().add(book_time::Column::BookId.eq(id)))
.add(book_time::Column::BookId.eq(id)) .exec(db)
).exec(db).await .await
} }
pub async fn delete_book_isbn(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> { pub async fn delete_book_isbn(db: &DbConn, id: i32) -> Result<DeleteResult, DbErr> {
book_isbn::Entity::delete_many().filter( book_isbn::Entity::delete_many()
Condition::any() .filter(Condition::any().add(book_isbn::Column::BookId.eq(id)))
.add(book_isbn::Column::BookId.eq(id)) .exec(db)
).exec(db).await .await
} }
pub async fn delete_all_books(db: &DbConn) -> Result<DeleteResult, DbErr> { pub async fn delete_all_books(db: &DbConn) -> Result<DeleteResult, DbErr> {
Book::delete_many().exec(db).await Book::delete_many().exec(db).await
} }

View File

@@ -2,7 +2,9 @@ use ::entity::entities::book::Entity as Book;
use ::entity::entities::user::Entity as User; 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}; //, 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 ::entity::entities::{prelude::*, *};
use sea_orm::*; use sea_orm::*;
//use sea_query::Expr; //use sea_query::Expr;
@@ -26,12 +28,16 @@ impl Query {
Book::find_by_id(id).one(db).await Book::find_by_id(id).one(db).await
} }
pub async fn find_userid_by_name(
pub async fn find_userid_by_name(db: &DbConn, name: String) -> Result<Option<user::Model>, DbErr> { db: &DbConn,
User::find().filter(user::Column::UserName.eq(name)).one(db).await 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> { pub async fn find_user_by_id(db: &DbConn, id: i32) -> Result<Option<user::Model>, DbErr> {
User::find_by_id(id).one(db).await User::find_by_id(id).one(db).await
} }
@@ -62,14 +68,14 @@ impl Query {
.order_by_desc(book::Column::Id) .order_by_desc(book::Column::Id)
.paginate(db, posts_per_page); .paginate(db, posts_per_page);
let num_pages = paginator.num_pages().await?; 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 { } else {
let paginator = Book::find() let paginator = Book::find()
.filter(book::Column::UserId.eq(userid)) .filter(book::Column::UserId.eq(userid))
.order_by_asc(book::Column::Id) .order_by_asc(book::Column::Id)
.paginate(db, posts_per_page); .paginate(db, posts_per_page);
let num_pages = paginator.num_pages().await?; 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 // Fetch paginated posts
@@ -83,17 +89,30 @@ pub async fn find_books_plus_meta_in_page(
sort: String, sort: String,
) -> Result<(Vec<BookAndMetaV2>, u64), DbErr> { ) -> Result<(Vec<BookAndMetaV2>, u64), DbErr> {
// Setup paginator // 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(); let book_ids: Vec<i32> = books.0.clone().into_iter().map(|b| b.id).collect();
println!("SIZE IS {} and {:?}", book_ids.len(), book_ids); println!("SIZE IS {} and {:?}", book_ids.len(), book_ids);
let mut resbooks: Vec<BookAndMetaV2> = Vec::with_capacity(book_ids.len()); let mut resbooks: Vec<BookAndMetaV2> = Vec::with_capacity(book_ids.len());
for book in books.0.iter() { for book in books.0.iter() {
let bauthors: Vec<book_author::Model> = book.find_related(book_author::Entity).all(db).await?; let bauthors: Vec<book_author::Model> =
let bpersons: Vec<book_person::Model> = book.find_related(book_person::Entity).all(db).await?; book.find_related(book_author::Entity).all(db).await?;
let bplaces: Vec<book_place::Model> = book.find_related(book_place::Entity).all(db).await?; let bpersons: Vec<book_person::Model> =
let bsubjects: Vec<book_subject::Model> = book.find_related(book_subject::Entity).all(db).await?; book.find_related(book_person::Entity).all(db).await?;
let btimes: Vec<book_time::Model> = book.find_related(book_time::Entity).all(db).await?; let bplaces: Vec<book_place::Model> =
let bisbns: Vec<book_isbn::Model> = book.find_related(book_isbn::Entity).all(db).await?; 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 { let bookandmeta = BookAndMetaV2 {
book: (book.clone()), book: (book.clone()),
@@ -102,14 +121,11 @@ pub async fn find_books_plus_meta_in_page(
places: bplaces, places: bplaces,
subjects: bsubjects, subjects: bsubjects,
times: btimes, times: btimes,
isbns: bisbns isbns: bisbns,
}; };
resbooks.push(bookandmeta); resbooks.push(bookandmeta);
} }
Ok((resbooks, books.1)) Ok((resbooks, books.1))
} }
} }

View File

@@ -1,9 +1,8 @@
use sea_orm::*; use crate::Query;
use axum::async_trait; use axum::async_trait;
use axum_login::{secrecy::SecretVec, AuthUser, UserStore}; use axum_login::{secrecy::SecretVec, AuthUser, UserStore};
use crate::Query; use sea_orm::*;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AxumUser { pub struct AxumUser {
@@ -59,4 +58,3 @@ Role: PartialOrd + PartialEq + Clone + Send + Sync + 'static,
} }
} }
} }

View File

@@ -1,6 +1,6 @@
use meilisearch_sdk::client::*; use meilisearch_sdk::client::*;
use meilisearch_sdk::search::*; use meilisearch_sdk::search::*;
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug, Clone)] #[derive(Deserialize, Serialize, Debug, Clone)]
pub struct BookMeili { 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. // An index is where the documents are stored.
let books = client.index(format!("books{}", userid)); 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. // 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(&[ books.add_or_replace(&[book], Some("id")).await.unwrap();
book
], Some("id")).await.unwrap();
} }
pub async fn delete_book(bookid: i32, userid: i32, client: &Client) { pub async fn delete_book(bookid: i32, userid: i32, client: &Client) {
// An index is where the documents are stored. // An index is where the documents are stored.
let books = client.index(format!("books{}", userid)); let books = client.index(format!("books{}", userid));
books.delete_document(bookid).await.unwrap(); books.delete_document(bookid).await.unwrap();
} }
pub async fn search_book(
pub async fn search_book(search: &str, page: usize, userid: i32, client: &Client) -> Result<(Vec<BookMeili>, usize), meilisearch_sdk::errors::Error> { search: &str,
page: usize,
userid: i32,
client: &Client,
) -> Result<(Vec<BookMeili>, usize), meilisearch_sdk::errors::Error> {
// An index is where the documents are stored. // An index is where the documents are stored.
let books = client.index(format!("books{}", userid)); let books = client.index(format!("books{}", userid));
let results : SearchResults<BookMeili> = books.search().with_query(search).with_offset((page-1)*12) let results: SearchResults<BookMeili> = books
.execute::<BookMeili>().await.unwrap(); .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(); //.iter()s.map(|r| r.formatted_result.unwrap()).collect();
return Ok((formatted_results, results.estimated_total_hits)); return Ok((formatted_results, results.estimated_total_hits));
} }

View File

@@ -1,4 +1,3 @@
fn main() { fn main() {
booksman_api::main(); booksman_api::main();
} }

File diff suppressed because it is too large Load Diff