User Authentication and Other fixes #1
@@ -254,6 +254,7 @@ pub async fn main() {
|
|||||||
.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/delete/:id", get(delete_book))
|
.route("/api/delete/:id", get(delete_book))
|
||||||
|
.route("/api/authentication_check", get(authentication_check))
|
||||||
.route_layer(RequireAuthorizationLayer::<booksman_orm::AxumUser>::login())
|
.route_layer(RequireAuthorizationLayer::<booksman_orm::AxumUser>::login())
|
||||||
.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))
|
||||||
@@ -346,6 +347,12 @@ async fn list_users(
|
|||||||
auth.logout().await;
|
auth.logout().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//https://openlibrary.org/api/books?bibkeys=ISBN:9780980200447&jscmd=data&format=json
|
||||||
|
async fn authentication_check(
|
||||||
|
Extension(user): Extension<booksman_orm::AxumUser>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
return 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
|
||||||
|
|||||||
@@ -37,6 +37,15 @@ body {
|
|||||||
background-color: #f1f1f1; /* Fallback color */
|
background-color: #f1f1f1; /* Fallback color */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dropdown Content (Hidden by Default) */
|
||||||
|
.dropdown-content {
|
||||||
|
position: absolute;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
min-width: 160px;
|
||||||
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Float three header columns side by side */
|
/* Float three header columns side by side */
|
||||||
.header {
|
.header {
|
||||||
position: fixed; /* Stay in place */
|
position: fixed; /* Stay in place */
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use web_sys::{Event, HtmlInputElement, KeyboardEvent}; // 0.3.5
|
|||||||
use dotenv_codegen::dotenv;
|
use dotenv_codegen::dotenv;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use wasm_bindgen::closure::Closure;
|
||||||
//use gloo_timers::future::TimeoutFuture;
|
//use gloo_timers::future::TimeoutFuture;
|
||||||
//#[macro_use]
|
//#[macro_use]
|
||||||
//extern crate dotenv_codegen;
|
//extern crate dotenv_codegen;
|
||||||
@@ -90,23 +91,9 @@ pub struct AppState {
|
|||||||
pub loggedin: RcSignal<bool>,
|
pub loggedin: RcSignal<bool>,
|
||||||
pub editmode: RcSignal<bool>,
|
pub editmode: RcSignal<bool>,
|
||||||
pub dropdownselect: RcSignal<bool>,
|
pub dropdownselect: RcSignal<bool>,
|
||||||
|
pub scrolling: RcSignal<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO
|
|
||||||
let callback: Closure<dyn FnMut()> = Closure::new(move || {
|
|
||||||
info!("Got scroll event");
|
|
||||||
});
|
|
||||||
|
|
||||||
let window = web_sys::window().expect("Failed to get window");
|
|
||||||
window
|
|
||||||
.add_event_listener_with_callback_and_bool(
|
|
||||||
"scroll",
|
|
||||||
callback.as_ref().unchecked_ref(),
|
|
||||||
false, // Changing this to true does not help :/
|
|
||||||
)
|
|
||||||
.expect("Failed to set listener");
|
|
||||||
callback.forget();*/
|
|
||||||
|
|
||||||
async fn login_user(user: AxumUser) -> Result<reqwasm::http::Response, reqwasm::Error> {
|
async fn login_user(user: AxumUser) -> Result<reqwasm::http::Response, reqwasm::Error> {
|
||||||
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
||||||
let url = format!("{}/api/login", backend_url);
|
let url = format!("{}/api/login", backend_url);
|
||||||
@@ -140,6 +127,19 @@ async fn list_users() -> Result<HashMap<String,i32>, reqwasm::Error> {
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn authentication_check() -> Result<bool, reqwasm::Error> {
|
||||||
|
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
||||||
|
let url = format!("{}/api/authentication_check", backend_url);
|
||||||
|
let resp = Request::get(&url).send().await?;
|
||||||
|
if resp.status() == 200 {
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn fetch_books(search: String) -> Result<Vec<BookUI>, reqwasm::Error> {
|
async fn fetch_books(search: String) -> Result<Vec<BookUI>, reqwasm::Error> {
|
||||||
//dotenvy::dotenv().ok();
|
//dotenvy::dotenv().ok();
|
||||||
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
||||||
@@ -432,6 +432,20 @@ pub fn DropDownUser<G: Html>(cx: Scope, value: StringProp) -> View<G> {
|
|||||||
#[component]
|
#[component]
|
||||||
async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
||||||
let app_state = use_context::<AppState>(cx);
|
let app_state = use_context::<AppState>(cx);
|
||||||
|
let callback_signal = use_context::<RcSignal<bool>>(cx);
|
||||||
|
let csignal = callback_signal.clone();
|
||||||
|
//callback_signal.clone().set(false);
|
||||||
|
create_effect(cx, || {
|
||||||
|
let app_state = app_state.clone();
|
||||||
|
let cxsignal = callback_signal.clone();
|
||||||
|
if *cxsignal.get() == true {
|
||||||
|
cxsignal.set(false);
|
||||||
|
if *app_state.pagedisplay.get() < *app_state.maxpage.get()-1 {
|
||||||
|
app_state.pagedisplay.set(*app_state.pagedisplay.get()+1);
|
||||||
|
app_state.scrolling.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
create_effect(cx, || {
|
create_effect(cx, || {
|
||||||
let app_state = app_state.clone();
|
let app_state = app_state.clone();
|
||||||
@@ -440,6 +454,8 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
app_state.openlibrary.track();
|
app_state.openlibrary.track();
|
||||||
app_state.internalsearch.track();
|
app_state.internalsearch.track();
|
||||||
app_state.refreshing.track();
|
app_state.refreshing.track();
|
||||||
|
//let csignal = csignals2.clone();
|
||||||
|
|
||||||
//let tempb = app_state.books.get();
|
//let tempb = app_state.books.get();
|
||||||
//spawn_local( async move { info!(
|
//spawn_local( async move { info!(
|
||||||
// "The state changed. Old value: {:?}",
|
// "The state changed. Old value: {:?}",
|
||||||
@@ -481,6 +497,40 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if *app_state.scrolling.get()==true {
|
||||||
|
app_state.scrolling.set(false);
|
||||||
|
if *app_state.internalsearch.get() == false {
|
||||||
|
info!("DB triggered");
|
||||||
|
spawn_local(async move {
|
||||||
|
let res = list_books(*app_state.pagedisplay.get(), *app_state.userid.get(), "desc".to_string())
|
||||||
|
.await.unwrap();
|
||||||
|
let mut currbooks = (*app_state.clone().books.get()).clone();
|
||||||
|
currbooks.extend(res.books.iter().cloned());
|
||||||
|
app_state.books.set(
|
||||||
|
currbooks
|
||||||
|
);
|
||||||
|
app_state.maxpage.set(
|
||||||
|
res.num_pages
|
||||||
|
)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
info!("IntSearch triggered");
|
||||||
|
|
||||||
|
spawn_local(async move {
|
||||||
|
let res = search_books(app_state.search.get().to_string(), *app_state.pagedisplay.get(), *app_state.userid.get())
|
||||||
|
.await.unwrap();
|
||||||
|
let mut currbooks = (*app_state.clone().books.get()).clone();
|
||||||
|
currbooks.extend(res.books.iter().cloned());
|
||||||
|
app_state.books.set(
|
||||||
|
currbooks
|
||||||
|
);
|
||||||
|
app_state.maxpage.set(
|
||||||
|
res.num_pages
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if *app_state.refreshing.get() == false {
|
if *app_state.refreshing.get() == false {
|
||||||
@@ -501,6 +551,22 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let callback: Closure<dyn FnMut()> = Closure::new(move || {
|
||||||
|
//let csignal = callback_signal.clone();
|
||||||
|
csignal.set(true);
|
||||||
|
info!("Got scroll event");
|
||||||
|
});
|
||||||
|
|
||||||
|
let window = web_sys::window().expect("Failed to get window");
|
||||||
|
window
|
||||||
|
.add_event_listener_with_callback_and_bool(
|
||||||
|
"scroll",
|
||||||
|
callback.as_ref().unchecked_ref(),
|
||||||
|
false, // Changing this to true does not help :/
|
||||||
|
)
|
||||||
|
.expect("Failed to set listener");
|
||||||
|
callback.forget();
|
||||||
|
|
||||||
let docs = create_memo(cx, || app_state.books.get().iter().cloned().collect::<Vec<_>>());
|
let docs = create_memo(cx, || app_state.books.get().iter().cloned().collect::<Vec<_>>());
|
||||||
view! {cx,
|
view! {cx,
|
||||||
p {
|
p {
|
||||||
@@ -1118,14 +1184,17 @@ async fn PageBar<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
let input_ref = create_node_ref(cx);
|
let input_ref = create_node_ref(cx);
|
||||||
|
|
||||||
let handle_add = move |_| {
|
let handle_add = move |_| {
|
||||||
|
if *app_state.pagenum.get() < *app_state.maxpage.get()-1 {
|
||||||
app_state.pagenum.set(*app_state.pagenum.get()+1);
|
app_state.pagenum.set(*app_state.pagenum.get()+1);
|
||||||
|
app_state.pagedisplay.set(*app_state.pagenum.get()+1);
|
||||||
app_state.refreshing.set(true);
|
app_state.refreshing.set(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle_sub = move |_| {
|
let handle_sub = move |_| {
|
||||||
if *app_state.pagenum.get()>1 {
|
if *app_state.pagenum.get()>1 {
|
||||||
app_state.pagenum.set(*app_state.pagenum.get()-1);
|
app_state.pagenum.set(*app_state.pagenum.get()-1);
|
||||||
|
app_state.pagedisplay.set(*app_state.pagenum.get()-1);
|
||||||
app_state.refreshing.set(true);
|
app_state.refreshing.set(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1137,6 +1206,7 @@ async fn PageBar<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
let pg = currpg.get().as_ref().clone().parse::<u32>().unwrap_or(1);
|
let pg = currpg.get().as_ref().clone().parse::<u32>().unwrap_or(1);
|
||||||
if pg>0 && pg<*app_state.maxpage.get() {
|
if pg>0 && pg<*app_state.maxpage.get() {
|
||||||
app_state.pagenum.set(pg);
|
app_state.pagenum.set(pg);
|
||||||
|
app_state.pagedisplay.set(pg);
|
||||||
app_state.refreshing.set(true);
|
app_state.refreshing.set(true);
|
||||||
} else {
|
} else {
|
||||||
currpg.set((*app_state.pagenum.get()).to_string());
|
currpg.set((*app_state.pagenum.get()).to_string());
|
||||||
@@ -1178,6 +1248,7 @@ async fn LoginScreenUI<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
let input_refU = create_node_ref(cx);
|
let input_refU = create_node_ref(cx);
|
||||||
let passval = create_signal(cx, String::new());
|
let passval = create_signal(cx, String::new());
|
||||||
let input_refP = create_node_ref(cx);
|
let input_refP = create_node_ref(cx);
|
||||||
|
let node_ref = create_node_ref(cx);
|
||||||
|
|
||||||
let handle_register = move |_| {
|
let handle_register = move |_| {
|
||||||
let app_state = app_state.clone();
|
let app_state = app_state.clone();
|
||||||
@@ -1198,6 +1269,8 @@ async fn LoginScreenUI<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let handle_login = move |_| {
|
let handle_login = move |_| {
|
||||||
|
let app_state = app_state.clone();
|
||||||
|
let userstr = (*userval.get()).clone();
|
||||||
let user = AxumUser{
|
let user = AxumUser{
|
||||||
id: 0,
|
id: 0,
|
||||||
name: (*userval.get()).clone(),
|
name: (*userval.get()).clone(),
|
||||||
@@ -1207,23 +1280,52 @@ async fn LoginScreenUI<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
login_user(user)
|
login_user(user)
|
||||||
.await.expect("Couldn't login user");
|
.await.expect("Couldn't login user");
|
||||||
});
|
});
|
||||||
app_state.loggedin.set(true);
|
spawn_local(async move {
|
||||||
app_state.useridloggedin.set( *(*app_state.userlist.get()).get(&(*userval.get()).clone()).unwrap_or(&0));
|
let auth = authentication_check().await.unwrap_or(false);
|
||||||
app_state.userid.set( *(*app_state.userlist.get()).get(&(*userval.get()).clone()).unwrap_or(&0));
|
app_state.loggedin.set(auth);
|
||||||
|
if auth == true {
|
||||||
|
app_state.useridloggedin.set( *(*app_state.userlist.get()).get(&userstr).unwrap_or(&0));
|
||||||
|
app_state.userid.set( *(*app_state.userlist.get()).get(&userstr).unwrap_or(&0));
|
||||||
app_state.userscreen.set(false);
|
app_state.userscreen.set(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
create_effect(cx, || {
|
||||||
|
if *app_state.userscreen.get() == true {
|
||||||
|
let dom_node = node_ref.try_get::<DomNode>();
|
||||||
|
if dom_node.is_some() {
|
||||||
|
dom_node.unwrap().set_attribute("popup-display","true");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let dom_node = node_ref.try_get::<DomNode>();
|
||||||
|
if dom_node.is_some() {
|
||||||
|
dom_node.unwrap().set_attribute("popup-display","false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let handle_close = move |_| {
|
||||||
|
app_state.displaying.set(false);
|
||||||
|
|
||||||
|
let dom_node = node_ref.try_get::<DomNode>();
|
||||||
|
if dom_node.is_some() {
|
||||||
|
dom_node.unwrap().set_attribute("popup-display","false");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
view! {cx,
|
view! {cx,
|
||||||
div {
|
div(class="modal-box", ref=node_ref){
|
||||||
|
|
||||||
(if *app_state.userscreen.get() == true {
|
(if *app_state.userscreen.get() == true {
|
||||||
view!{cx,
|
view!{cx,
|
||||||
|
div(class="modal-content"){
|
||||||
input(ref=input_refU,bind:value=userval)
|
input(ref=input_refU,bind:value=userval)
|
||||||
input(ref=input_refP,bind:value=passval)
|
input(ref=input_refP,bind:value=passval)
|
||||||
|
|
||||||
button(on:click=handle_login){ "LOGIN" }
|
button(on:click=handle_login){ "LOGIN" }
|
||||||
button(on:click=handle_register){ "REGISTER" }
|
button(on:click=handle_register){ "REGISTER" }
|
||||||
|
button(class="close", on:click=handle_close){ "CLOSE" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
view!{cx,""}
|
view!{cx,""}
|
||||||
@@ -1262,6 +1364,7 @@ fn App<G: Html>(cx: Scope) -> View<G> {
|
|||||||
loggedin: create_rc_signal(bool::default()),
|
loggedin: create_rc_signal(bool::default()),
|
||||||
editmode: create_rc_signal(bool::default()),
|
editmode: create_rc_signal(bool::default()),
|
||||||
dropdownselect: create_rc_signal(bool::default()),
|
dropdownselect: create_rc_signal(bool::default()),
|
||||||
|
scrolling: create_rc_signal(bool::default()),
|
||||||
};
|
};
|
||||||
provide_context(cx, app_state);
|
provide_context(cx, app_state);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user