User Authentication and Other fixes #1
@@ -327,8 +327,15 @@ async fn list_users(
|
|||||||
}
|
}
|
||||||
return Json(users);
|
return Json(users);
|
||||||
}
|
}
|
||||||
async fn login_handler(mut auth: AuthContext, Json(user_sent): Json<booksman_orm::AxumUser>) -> impl IntoResponse {
|
async fn login_handler(mut auth: AuthContext, Extension(ref conn): Extension<DatabaseConnection>, Json(user_sent): Json<booksman_orm::AxumUser>) -> impl IntoResponse {
|
||||||
auth.login(&user_sent).await.unwrap();
|
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()
|
||||||
|
};
|
||||||
|
auth.login(&corrected_user).await.unwrap();
|
||||||
return "success";
|
return "success";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,8 +628,9 @@ async fn list_book(
|
|||||||
|
|
||||||
let page: usize = params.get("page").unwrap().parse().unwrap();
|
let page: usize = params.get("page").unwrap().parse().unwrap();
|
||||||
let userid: usize = params.get("userid").unwrap().parse().unwrap();
|
let userid: usize = params.get("userid").unwrap().parse().unwrap();
|
||||||
|
let sort: String = params.get("sort").unwrap().to_string();
|
||||||
|
|
||||||
let books = QueryCore::find_books_plus_meta_in_page(conn,page,userid,12)
|
let books = QueryCore::find_books_plus_meta_in_page(conn,page,userid,12, sort)
|
||||||
.await
|
.await
|
||||||
.expect("could not list books");
|
.expect("could not list books");
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ impl Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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> {
|
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
|
||||||
}
|
}
|
||||||
@@ -48,16 +53,26 @@ impl Query {
|
|||||||
page: u64,
|
page: u64,
|
||||||
posts_per_page: u64,
|
posts_per_page: u64,
|
||||||
userid: i32,
|
userid: i32,
|
||||||
|
sort: String,
|
||||||
) -> Result<(Vec<book::Model>, u64), DbErr> {
|
) -> Result<(Vec<book::Model>, u64), DbErr> {
|
||||||
// Setup paginator
|
// Setup paginator
|
||||||
let paginator = Book::find()
|
if sort == "desc".to_string() {
|
||||||
.filter(book::Column::UserId.eq(userid))
|
let paginator = Book::find()
|
||||||
.order_by_asc(book::Column::Id)
|
.filter(book::Column::UserId.eq(userid))
|
||||||
.paginate(db, posts_per_page);
|
.order_by_desc(book::Column::Id)
|
||||||
let num_pages = paginator.num_pages().await?;
|
.paginate(db, posts_per_page);
|
||||||
|
let num_pages = paginator.num_pages().await?;
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch paginated posts
|
// Fetch paginated posts
|
||||||
paginator.fetch_page(page - 1).await.map(|p| (p, num_pages))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn find_books_plus_meta_in_page(
|
pub async fn find_books_plus_meta_in_page(
|
||||||
@@ -65,9 +80,10 @@ pub async fn find_books_plus_meta_in_page(
|
|||||||
page: usize,
|
page: usize,
|
||||||
posts_per_page: usize,
|
posts_per_page: usize,
|
||||||
userid: i32,
|
userid: i32,
|
||||||
|
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).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();
|
||||||
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() {
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ pub struct BookUIProp {
|
|||||||
bookitem: BookUI,
|
bookitem: BookUI,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Prop, Debug, Clone, PartialEq, Hash, Eq)]
|
||||||
|
pub struct StringProp {
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
struct PaginatedBookUIList {
|
struct PaginatedBookUIList {
|
||||||
num_pages: u32,
|
num_pages: u32,
|
||||||
@@ -146,11 +151,11 @@ async fn fetch_books(search: String) -> Result<Vec<BookUI>, reqwasm::Error> {
|
|||||||
Ok(body)
|
Ok(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn search_books(search: String, page: u32) -> Result<PaginatedBookUIList, reqwasm::Error> {
|
async fn search_books(search: String, page: u32, userid:i32) -> Result<PaginatedBookUIList, reqwasm::Error> {
|
||||||
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
||||||
//"http://localhost:8081";
|
//"http://localhost:8081";
|
||||||
//env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file");
|
//env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file");
|
||||||
let url = format!("{}/api/list_search?search={}&page={}",backend_url, search, page);
|
let url = format!("{}/api/list_search?search={}&page={}&userid={}",backend_url, search, page, userid);
|
||||||
let resp = Request::get(&url).send().await?;
|
let resp = Request::get(&url).send().await?;
|
||||||
println!("Fetching books\n");
|
println!("Fetching books\n");
|
||||||
let body = resp.json::<PaginatedBookUIList>().await?;
|
let body = resp.json::<PaginatedBookUIList>().await?;
|
||||||
@@ -191,10 +196,10 @@ async fn delete_book(id: i32) -> Result<reqwasm::http::Response, reqwasm::Error>
|
|||||||
Ok(resp)
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_books(page: u32) -> Result<PaginatedBookUIList, reqwasm::Error> {
|
async fn list_books(page: u32, userid: i32, sort: String) -> Result<PaginatedBookUIList, reqwasm::Error> {
|
||||||
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
||||||
//env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file");
|
//env::var("BACKEND_URL").expect("BACKEND_URL is not set in .env file");
|
||||||
let url = format!("{}/api/list?page={}", backend_url, page);
|
let url = format!("{}/api/list?page={}&userid={}&sort={}", backend_url, page, userid, sort);
|
||||||
let resp = Request::get(&url).send().await?;
|
let resp = Request::get(&url).send().await?;
|
||||||
println!("Fetching books\n");
|
println!("Fetching books\n");
|
||||||
info!("BACKEND{}",backend_url);
|
info!("BACKEND{}",backend_url);
|
||||||
@@ -309,6 +314,7 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let dropdown_userselect = |_| {
|
let dropdown_userselect = |_| {
|
||||||
|
let app_state = app_state.clone();
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
app_state.userlist.set(list_users()
|
app_state.userlist.set(list_users()
|
||||||
.await.expect("Couldn't list user"));
|
.await.expect("Couldn't list user"));
|
||||||
@@ -316,8 +322,10 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
app_state.dropdownselect.set(true);
|
app_state.dropdownselect.set(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// let users = create_memo(cx, || app_state.userlist.get().keys().cloned().map(|x| StringProp{value: x}).collect::<Vec<StringProp>>());
|
||||||
let users = create_memo(cx, || app_state.userlist.get().keys().cloned().collect::<Vec<String>>());
|
let users = create_memo(cx, || app_state.userlist.get().keys().cloned().collect::<Vec<String>>());
|
||||||
|
|
||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
header(class="header") {
|
header(class="header") {
|
||||||
div(class="header-button"){
|
div(class="header-button"){
|
||||||
@@ -361,9 +369,9 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
Keyed(
|
Keyed(
|
||||||
iterable=users,
|
iterable=users,
|
||||||
view=move |cx, x| view! { cx,
|
view=move |cx, x| view! { cx,
|
||||||
DropDownUser(user=x)
|
DropDownUser(value=x)
|
||||||
},
|
},
|
||||||
key =|x| x )
|
key =|x| x.clone() )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -406,16 +414,18 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[component(inline_props)]
|
#[component(inline_props)]
|
||||||
pub fn DropDownUser<G: Html>(cx: Scope, user: String) -> View<G> {
|
pub fn DropDownUser<G: Html>(cx: Scope, value: StringProp) -> View<G> {
|
||||||
let app_state = use_context::<AppState>(cx);
|
let app_state = use_context::<AppState>(cx);
|
||||||
|
let buttontext = value.clone().value.clone();
|
||||||
|
let valueclosure = value.clone();
|
||||||
|
|
||||||
let handle_select_user = move |_| {
|
let handle_select_user = move |_| {
|
||||||
app_state.userid.set( *(*app_state.userlist.get()).get(&(user).clone()).unwrap_or(&0));
|
app_state.userid.set( *(*app_state.userlist.get()).get(&(valueclosure.value).clone()).unwrap_or(&0));
|
||||||
app_state.dropdownselect.set(false);
|
app_state.dropdownselect.set(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
button(class="delete", on:click=handle_select_user){ format!("{}",user) }
|
button(class="delete", on:click=handle_select_user){ (buttontext) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,7 +457,7 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
info!("DB triggered");
|
info!("DB triggered");
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
|
|
||||||
let res = list_books(*app_state.pagenum.get())
|
let res = list_books(*app_state.pagenum.get(), *app_state.userid.get(), "desc".to_string())
|
||||||
.await.unwrap();
|
.await.unwrap();
|
||||||
app_state.books.set(
|
app_state.books.set(
|
||||||
res.books
|
res.books
|
||||||
@@ -460,7 +470,7 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
info!("IntSearch triggered");
|
info!("IntSearch triggered");
|
||||||
|
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
let res = search_books(app_state.search.get().to_string(), *app_state.pagenum.get())
|
let res = search_books(app_state.search.get().to_string(), *app_state.pagenum.get(), *app_state.userid.get())
|
||||||
.await.unwrap();
|
.await.unwrap();
|
||||||
app_state.books.set(
|
app_state.books.set(
|
||||||
res.books
|
res.books
|
||||||
|
|||||||
Reference in New Issue
Block a user