User Authentication and Other fixes #1

Merged
vinod merged 30 commits from user-auth into main 2023-02-05 09:01:08 +00:00
2 changed files with 52 additions and 41 deletions
Showing only changes of commit ec8122536d - Show all commits

View File

@@ -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"
} }

View File

@@ -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?;