User Authentication and Other fixes #1
@@ -15,7 +15,7 @@ use std::str::FromStr;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
use tower_http::cors::{Any,CorsLayer};
|
use tower_http::cors::{Any,CorsLayer};
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
use booksman_search::BookMeili;
|
use booksman_search::BookMeili;
|
||||||
@@ -27,7 +27,7 @@ use booksman_orm::{
|
|||||||
};
|
};
|
||||||
use meilisearch_sdk::client::Client;
|
use meilisearch_sdk::client::Client;
|
||||||
//use itertools::Itertools;
|
//use itertools::Itertools;
|
||||||
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn};
|
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn,user};
|
||||||
use std::env;
|
use std::env;
|
||||||
use migration::{Migrator, MigratorTrait};
|
use migration::{Migrator, MigratorTrait};
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
@@ -38,11 +38,11 @@ use axum_login::{
|
|||||||
AuthLayer, AuthUser, RequireAuthorizationLayer,
|
AuthLayer, AuthUser, RequireAuthorizationLayer,
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
struct User {
|
struct User {
|
||||||
id: i64,
|
id: i32,
|
||||||
password_hash: String,
|
password_hash: String,
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ pub async fn main() {
|
|||||||
|
|
||||||
let secret = rand::thread_rng().gen::<[u8; 64]>();
|
let secret = rand::thread_rng().gen::<[u8; 64]>();
|
||||||
|
|
||||||
let session_store = MemoryStore::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 conn = Database::connect(db_url)
|
let conn = Database::connect(db_url)
|
||||||
@@ -266,11 +266,12 @@ pub async fn main() {
|
|||||||
|
|
||||||
|
|
||||||
let store = Arc::new(RwLock::new(HashMap::default()));
|
let store = Arc::new(RwLock::new(HashMap::default()));
|
||||||
let users : Vec<User> = get_users_seaorm(conn);
|
let usersmodels : Vec<user::Model> = QueryCore::list_all_users(&conn).await.unwrap_or(Vec::new());
|
||||||
|
//let users : Vec<User> = get_users_seaorm(conn);
|
||||||
//let user = User::get_rusty_user();
|
//let user = User::get_rusty_user();
|
||||||
for user in users.iter() {
|
//for user in users.iter() {
|
||||||
store.write().await.insert(user.get_id(), user);
|
// store.write().await.insert(user.get_id(), user);
|
||||||
}
|
//}
|
||||||
|
|
||||||
let user_store = AuthMemoryStore::new(&store);
|
let user_store = AuthMemoryStore::new(&store);
|
||||||
let auth_layer = AuthLayer::new(user_store, &secret);
|
let auth_layer = AuthLayer::new(user_store, &secret);
|
||||||
@@ -284,7 +285,7 @@ pub async fn main() {
|
|||||||
|
|
||||||
async fn register_handler(mut auth: AuthContext, Json(user_sent): Json<User>) {
|
async fn register_handler(mut auth: AuthContext, Json(user_sent): Json<User>) {
|
||||||
// add to db
|
// add to db
|
||||||
store.write().await.insert(user_sent.get_id(), user_sent);
|
//store.write().await.insert(user_sent.get_id(), user_sent);
|
||||||
auth.login(&user_sent).await.unwrap();
|
auth.login(&user_sent).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,6 +301,7 @@ pub async fn main() {
|
|||||||
.route("/api/delete/:id", get(delete_book))
|
.route("/api/delete/:id", get(delete_book))
|
||||||
.route("/api/list", get(list_book))
|
.route("/api/list", get(list_book))
|
||||||
.route("/api/list_search", get(list_search_book))
|
.route("/api/list_search", get(list_search_book))
|
||||||
|
.route("/api/list_users", get(list_users))
|
||||||
.route("/api/create", post(create_book))
|
.route("/api/create", post(create_book))
|
||||||
.route("/api/update", post(update_book))
|
.route("/api/update", post(update_book))
|
||||||
.route("/api/login", post(login_handler))
|
.route("/api/login", post(login_handler))
|
||||||
@@ -338,15 +340,31 @@ pub async fn main() {
|
|||||||
.expect("Unable to start server");
|
.expect("Unable to start server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn list_users(
|
||||||
|
Extension(ref conn): Extension<DatabaseConnection>,
|
||||||
|
axum::extract::Query(params): axum::extract::Query<HashMap<String, String>>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
|
||||||
|
let res = PaginatedBookUIList{
|
||||||
|
num_pages: books.1 as u32,
|
||||||
|
books: resbooks
|
||||||
|
};
|
||||||
|
return Json(res);
|
||||||
|
// "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//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>,
|
||||||
Extension(ref meili_client): Extension<Client>,
|
Extension(ref meili_client): Extension<Client>,
|
||||||
|
Extension(user): Extension<User>,
|
||||||
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;
|
||||||
|
|
||||||
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();
|
||||||
@@ -444,6 +462,7 @@ async fn create_by_isbn(
|
|||||||
time_added: doc_sent.time_added.to_owned(),
|
time_added: doc_sent.time_added.to_owned(),
|
||||||
id: 1,
|
id: 1,
|
||||||
location: doc_sent.location.to_owned(),
|
location: doc_sent.location.to_owned(),
|
||||||
|
user_id: userid,
|
||||||
};
|
};
|
||||||
let created_book = MutationCore::create_book(conn, book)
|
let created_book = MutationCore::create_book(conn, book)
|
||||||
.await
|
.await
|
||||||
@@ -535,7 +554,7 @@ async fn create_by_isbn(
|
|||||||
time: doc_sent.time.unwrap_or(vec!["".to_string()]),
|
time: doc_sent.time.unwrap_or(vec!["".to_string()]),
|
||||||
isbn: doc_sent.isbn.unwrap_or(vec!["".to_string()]),
|
isbn: doc_sent.isbn.unwrap_or(vec!["".to_string()]),
|
||||||
};
|
};
|
||||||
booksman_search::create_or_update_book(book_meili, meili_client).await;
|
booksman_search::create_or_update_book(book_meili, userid, meili_client).await;
|
||||||
} else {
|
} else {
|
||||||
println!("ISBN Not found : {}",isbnstring);
|
println!("ISBN Not found : {}",isbnstring);
|
||||||
}
|
}
|
||||||
@@ -593,12 +612,14 @@ let mut vec = Vec::with_capacity(12);
|
|||||||
async fn delete_book(
|
async fn delete_book(
|
||||||
Extension(ref conn): Extension<DatabaseConnection>,
|
Extension(ref conn): Extension<DatabaseConnection>,
|
||||||
Extension(ref meili_client): Extension<Client>,
|
Extension(ref meili_client): Extension<Client>,
|
||||||
|
Extension(user): Extension<User>,
|
||||||
Path(id): Path<i32>,
|
Path(id): Path<i32>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
MutationCore::delete_book(conn, id)
|
MutationCore::delete_book(conn, id)
|
||||||
.await
|
.await
|
||||||
.expect("could not delete book");
|
.expect("could not delete book");
|
||||||
booksman_search::delete_book(id, meili_client).await;
|
let userid = user.id;
|
||||||
|
booksman_search::delete_book(id, userid, meili_client).await;
|
||||||
"success"
|
"success"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,8 +633,9 @@ async fn list_book(
|
|||||||
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 page: usize = params.get("page").unwrap().parse().unwrap();
|
let page: usize = params.get("page").unwrap().parse().unwrap();
|
||||||
|
let userid = params.get("userid").unwrap();
|
||||||
|
|
||||||
let books = QueryCore::find_books_plus_meta_in_page(conn,page,12)
|
let books = QueryCore::find_books_plus_meta_in_page(conn,page,userid,12)
|
||||||
.await
|
.await
|
||||||
.expect("could not list books");
|
.expect("could not list books");
|
||||||
|
|
||||||
@@ -665,11 +687,13 @@ async fn list_search_book(
|
|||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let page: usize = params.get("page").unwrap().parse().unwrap();
|
let page: usize = params.get("page").unwrap().parse().unwrap();
|
||||||
let search = params.get("search").unwrap();
|
let search = params.get("search").unwrap();
|
||||||
|
let userid = params.get("userid").unwrap();
|
||||||
|
|
||||||
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, 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");
|
||||||
|
|
||||||
@@ -718,12 +742,14 @@ return Json(res);
|
|||||||
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>,
|
||||||
|
Extension(user): Extension<User>,
|
||||||
Json(doc_sent_orig): Json<BookUI>,
|
Json(doc_sent_orig): Json<BookUI>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
println!("Creating book");
|
println!("Creating book");
|
||||||
|
|
||||||
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 mut doc_sent = doc_sent_orig.clone();
|
let mut doc_sent = doc_sent_orig.clone();
|
||||||
let mut cover = doc_sent.cover.clone();
|
let mut cover = doc_sent.cover.clone();
|
||||||
if doc_sent_orig.description.is_none() {
|
if doc_sent_orig.description.is_none() {
|
||||||
@@ -759,6 +785,7 @@ async fn create_book(
|
|||||||
time_added: doc_sent.time_added.to_owned(),
|
time_added: doc_sent.time_added.to_owned(),
|
||||||
id: 1,
|
id: 1,
|
||||||
location: doc_sent.location.to_owned(),
|
location: doc_sent.location.to_owned(),
|
||||||
|
user_id: userid,
|
||||||
};
|
};
|
||||||
let created_book = MutationCore::create_book(conn, book)
|
let created_book = MutationCore::create_book(conn, book)
|
||||||
.await
|
.await
|
||||||
@@ -850,7 +877,7 @@ async fn create_book(
|
|||||||
time: doc_sent.time.unwrap_or(vec!["".to_string()]),
|
time: doc_sent.time.unwrap_or(vec!["".to_string()]),
|
||||||
isbn: doc_sent.isbn.unwrap_or(vec!["".to_string()]),
|
isbn: doc_sent.isbn.unwrap_or(vec!["".to_string()]),
|
||||||
};
|
};
|
||||||
booksman_search::create_or_update_book(book_meili, meili_client).await;
|
booksman_search::create_or_update_book(book_meili, userid, meili_client).await;
|
||||||
|
|
||||||
|
|
||||||
"success"
|
"success"
|
||||||
@@ -861,6 +888,7 @@ async fn create_book(
|
|||||||
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>,
|
||||||
|
Extension(user): Extension<User>,
|
||||||
Json(doc_sent): Json<BookUI>,
|
Json(doc_sent): Json<BookUI>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
println!("Updating book");
|
println!("Updating book");
|
||||||
@@ -868,6 +896,7 @@ println!("Updating book");
|
|||||||
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 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 userid = user.id.clone();
|
||||||
|
|
||||||
let mut cover = doc_sent.cover.clone();
|
let mut cover = doc_sent.cover.clone();
|
||||||
if !doc_sent.cover.is_none() {
|
if !doc_sent.cover.is_none() {
|
||||||
@@ -899,6 +928,7 @@ let book: book::Model = book::Model{
|
|||||||
time_added: doc_sent.time_added.to_owned(),
|
time_added: doc_sent.time_added.to_owned(),
|
||||||
id: doc_sent.id.to_owned(),
|
id: doc_sent.id.to_owned(),
|
||||||
location: doc_sent.location.to_owned(),
|
location: doc_sent.location.to_owned(),
|
||||||
|
user_id: userid,
|
||||||
};
|
};
|
||||||
MutationCore::update_book_by_id(conn, book.id, book)
|
MutationCore::update_book_by_id(conn, book.id, book)
|
||||||
.await
|
.await
|
||||||
@@ -1014,7 +1044,7 @@ let book: book::Model = book::Model{
|
|||||||
time: doc_sent.time.unwrap_or(vec!["".to_string()]),
|
time: doc_sent.time.unwrap_or(vec!["".to_string()]),
|
||||||
isbn: doc_sent.isbn.unwrap_or(vec!["".to_string()]),
|
isbn: doc_sent.isbn.unwrap_or(vec!["".to_string()]),
|
||||||
};
|
};
|
||||||
booksman_search::create_or_update_book(book_meili, meili_client).await;
|
booksman_search::create_or_update_book(book_meili, userid, meili_client).await;
|
||||||
|
|
||||||
"success"
|
"success"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,12 @@
|
|||||||
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};
|
use ::entity::entities::{book,book_author,book_person,book_place,book_subject,book_time,book_isbn,user};
|
||||||
//use ::entity::entities::{prelude::*, *};
|
//use ::entity::entities::{prelude::*, *};
|
||||||
use sea_orm::*;
|
use sea_orm::*;
|
||||||
//use sea_query::Expr;
|
//use sea_query::Expr;
|
||||||
|
|
||||||
#[derive(FromQueryResult,Clone)]
|
|
||||||
pub struct BookAndMeta {
|
|
||||||
pub id: i32,
|
|
||||||
pub open_library_key: String,
|
|
||||||
pub title: String,
|
|
||||||
pub edition_count: i32,
|
|
||||||
pub first_publish_year: i32,
|
|
||||||
pub median_page_count: i32,
|
|
||||||
pub goodread_id: String,
|
|
||||||
pub description: String,
|
|
||||||
pub cover: String,
|
|
||||||
pub location: String,
|
|
||||||
pub time_added: String,
|
|
||||||
pub rating: i32,
|
|
||||||
pub comments: String,
|
|
||||||
pub author_name: String,
|
|
||||||
pub person: String,
|
|
||||||
pub place: String,
|
|
||||||
pub subject: String,
|
|
||||||
pub time: String,
|
|
||||||
pub isbn: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BookAndMetaV2 {
|
pub struct BookAndMetaV2 {
|
||||||
pub book: book::Model,
|
pub book: book::Model,
|
||||||
@@ -48,6 +26,9 @@ impl Query {
|
|||||||
Book::find_by_id(id).one(db).await
|
Book::find_by_id(id).one(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn list_all_users(db: &DbConn) -> Result<Vec<user::Model>, DbErr> {
|
||||||
|
User::find().all(db).await
|
||||||
|
}
|
||||||
/* pub async fn find_bookplusmeta_by_id(db: &DbConn, id: i32) -> Result<Option<(book::Model, Vec<book_author::Model>, Vec<book_person::Model>)>, DbErr> {
|
/* pub async fn find_bookplusmeta_by_id(db: &DbConn, id: i32) -> Result<Option<(book::Model, Vec<book_author::Model>, Vec<book_person::Model>)>, DbErr> {
|
||||||
let book = Book::find_by_id(id).one(db).await?.unwrap();
|
let book = Book::find_by_id(id).one(db).await?.unwrap();
|
||||||
let authors = book.find_related(Author).all(db).await?;
|
let authors = book.find_related(Author).all(db).await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user