user-auth store frontend and backend

This commit is contained in:
2022-12-31 21:52:09 +05:30
parent 40bb4f688a
commit aa1172bbc0
3 changed files with 145 additions and 26 deletions

View File

@@ -254,6 +254,7 @@ pub async fn main() {
.route("/api/create", post(create_book))
.route("/api/update", post(update_book))
.route("/api/delete/:id", get(delete_book))
.route("/api/authentication_check", get(authentication_check))
.route_layer(RequireAuthorizationLayer::<booksman_orm::AxumUser>::login())
.route("/api/list", get(list_book))
.route("/api/list_search", get(list_search_book))
@@ -346,6 +347,12 @@ async fn list_users(
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

View File

@@ -37,6 +37,15 @@ body {
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 */
.header {
position: fixed; /* Stay in place */

View File

@@ -13,6 +13,7 @@ use web_sys::{Event, HtmlInputElement, KeyboardEvent}; // 0.3.5
use dotenv_codegen::dotenv;
use itertools::Itertools;
use std::collections::HashMap;
use wasm_bindgen::closure::Closure;
//use gloo_timers::future::TimeoutFuture;
//#[macro_use]
//extern crate dotenv_codegen;
@@ -90,23 +91,9 @@ pub struct AppState {
pub loggedin: RcSignal<bool>,
pub editmode: 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> {
let backend_url : &'static str = dotenv!("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)
}
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> {
//dotenvy::dotenv().ok();
let backend_url : &'static str = dotenv!("BACKEND_URL");
@@ -432,6 +432,20 @@ pub fn DropDownUser<G: Html>(cx: Scope, value: StringProp) -> View<G> {
#[component]
async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
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, || {
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.internalsearch.track();
app_state.refreshing.track();
//let csignal = csignals2.clone();
//let tempb = app_state.books.get();
//spawn_local( async move { info!(
// "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 {
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<_>>());
view! {cx,
p {
@@ -1118,14 +1184,17 @@ async fn PageBar<G: Html>(cx: Scope<'_>) -> View<G> {
let input_ref = create_node_ref(cx);
let handle_add = move |_| {
app_state.pagenum.set(*app_state.pagenum.get()+1);
app_state.refreshing.set(true);
if *app_state.pagenum.get() < *app_state.maxpage.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);
}
};
let handle_sub = move |_| {
if *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);
}
};
@@ -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);
if pg>0 && pg<*app_state.maxpage.get() {
app_state.pagenum.set(pg);
app_state.pagedisplay.set(pg);
app_state.refreshing.set(true);
} else {
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 passval = create_signal(cx, String::new());
let input_refP = create_node_ref(cx);
let node_ref = create_node_ref(cx);
let handle_register = move |_| {
let app_state = app_state.clone();
@@ -1198,6 +1269,8 @@ async fn LoginScreenUI<G: Html>(cx: Scope<'_>) -> View<G> {
};
let handle_login = move |_| {
let app_state = app_state.clone();
let userstr = (*userval.get()).clone();
let user = AxumUser{
id: 0,
name: (*userval.get()).clone(),
@@ -1207,30 +1280,59 @@ async fn LoginScreenUI<G: Html>(cx: Scope<'_>) -> View<G> {
login_user(user)
.await.expect("Couldn't login user");
});
app_state.loggedin.set(true);
app_state.useridloggedin.set( *(*app_state.userlist.get()).get(&(*userval.get()).clone()).unwrap_or(&0));
app_state.userid.set( *(*app_state.userlist.get()).get(&(*userval.get()).clone()).unwrap_or(&0));
app_state.userscreen.set(false);
spawn_local(async move {
let auth = authentication_check().await.unwrap_or(false);
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);
}
});
};
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,
div {
div(class="modal-box", ref=node_ref){
(if *app_state.userscreen.get() == true {
view!{cx,
div(class="modal-content"){
input(ref=input_refU,bind:value=userval)
input(ref=input_refP,bind:value=passval)
button(on:click=handle_login){ "LOGIN" }
button(on:click=handle_register){ "REGISTER" }
button(class="close", on:click=handle_close){ "CLOSE" }
}
}
}else {
view!{cx,""}
})
}
}
}
}
@@ -1262,6 +1364,7 @@ fn App<G: Html>(cx: Scope) -> View<G> {
loggedin: create_rc_signal(bool::default()),
editmode: create_rc_signal(bool::default()),
dropdownselect: create_rc_signal(bool::default()),
scrolling: create_rc_signal(bool::default()),
};
provide_context(cx, app_state);