User Authentication and Other fixes #1
@@ -349,9 +349,9 @@ async fn list_users(
|
|||||||
|
|
||||||
//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 authentication_check(
|
async fn authentication_check(
|
||||||
Extension(user): Extension<booksman_orm::AxumUser>,
|
Extension(_user): Extension<booksman_orm::AxumUser>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
return true;
|
return Json(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -634,10 +634,10 @@ 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: usize = params.get("userid").unwrap().parse().unwrap();
|
let userid: i32 = params.get("userid").unwrap().parse().unwrap();
|
||||||
let sort: String = params.get("sort").unwrap().to_string();
|
let sort: String = params.get("sort").unwrap().to_string();
|
||||||
|
|
||||||
let books = QueryCore::find_books_plus_meta_in_page(conn,page,userid,12, sort)
|
let books = QueryCore::find_books_plus_meta_in_page(conn,page,12,userid, sort)
|
||||||
.await
|
.await
|
||||||
.expect("could not list books");
|
.expect("could not list books");
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ pub async fn find_books_plus_meta_in_page(
|
|||||||
// Setup paginator
|
// Setup paginator
|
||||||
let books = Self::find_books_in_page(db,page.try_into().unwrap(),posts_per_page.try_into().unwrap(),userid, sort).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();
|
||||||
|
println!("SIZE IS {} and {:?}", book_ids.len(), book_ids);
|
||||||
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() {
|
||||||
let bauthors: Vec<book_author::Model> = book.find_related(book_author::Entity).all(db).await?;
|
let bauthors: Vec<book_author::Model> = book.find_related(book_author::Entity).all(db).await?;
|
||||||
|
|||||||
52
frontend/Cargo.lock
generated
52
frontend/Cargo.lock
generated
@@ -136,7 +136,6 @@ dependencies = [
|
|||||||
"serde-wasm-bindgen",
|
"serde-wasm-bindgen",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sycamore",
|
"sycamore",
|
||||||
"sycamore-router",
|
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-logger",
|
"wasm-logger",
|
||||||
@@ -381,22 +380,6 @@ version = "2.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimal-lexical"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom"
|
|
||||||
version = "7.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"minimal-lexical",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.13.1"
|
version = "1.13.1"
|
||||||
@@ -565,9 +548,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sycamore"
|
name = "sycamore"
|
||||||
version = "0.8.0"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e4decd3fabbb4cfa8ef4d8b4469c7d35d65555806f6c6642a2733d892472ffa"
|
checksum = "67817393b3c9828db84614f64db9a1ebb94729ce3a3751c41e7ff23d3f8e7f00"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"futures",
|
"futures",
|
||||||
@@ -631,31 +614,6 @@ dependencies = [
|
|||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sycamore-router"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "123b34a150dac877d7bfae82dadfb0c586fd35a8f5fcdf1721dafa079fdc4c40"
|
|
||||||
dependencies = [
|
|
||||||
"sycamore",
|
|
||||||
"sycamore-router-macro",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sycamore-router-macro"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "92914a2f809b636d245b28d8a734801ecb8ff9c4996bbe6ea4176582e12503eb"
|
|
||||||
dependencies = [
|
|
||||||
"nom",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sycamore-web"
|
name = "sycamore-web"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -728,12 +686,6 @@ version = "1.0.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8-width"
|
name = "utf8-width"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ wasm-logger = "0.2.0"
|
|||||||
serde = { version = "^1.0", features = ["derive"] }
|
serde = { version = "^1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde-wasm-bindgen = "0.4"
|
serde-wasm-bindgen = "0.4"
|
||||||
sycamore = {version = "0.8.0-beta.7", features = ["suspense"]}
|
sycamore = {version = "0.8.2", features = ["suspense"]}
|
||||||
sycamore-router = "0.8.0-beta.7"
|
#sycamore-router = "0.8.2"
|
||||||
wasm-bindgen = "0.2.79"
|
wasm-bindgen = "0.2.79"
|
||||||
#tokio = {version = "1.21.2", features = ["full"] }
|
#tokio = {version = "1.21.2", features = ["full"] }
|
||||||
#yew = "0.19.3"
|
#yew = "0.19.3"
|
||||||
|
|||||||
@@ -36,20 +36,24 @@ body {
|
|||||||
overflow: auto; /* Enable scroll if needed */
|
overflow: auto; /* Enable scroll if needed */
|
||||||
background-color: #f1f1f1; /* Fallback color */
|
background-color: #f1f1f1; /* Fallback color */
|
||||||
}
|
}
|
||||||
|
/* The container <div> - needed to position the dropdown content */
|
||||||
|
.dropdown {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
/* Dropdown Content (Hidden by Default) */
|
/* Dropdown Content (Hidden by Default) */
|
||||||
.dropdown-content {
|
.dropdown-content {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: #f1f1f1;
|
|
||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
|
||||||
z-index: 1;
|
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 */
|
||||||
overflow: hidden;
|
/* overflow: hidden;*/
|
||||||
z-index: 1; /* Sit on top */
|
z-index: 1; /* Sit on top */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
top: 0; /* Position the navbar at the top of the page */
|
top: 0; /* Position the navbar at the top of the page */
|
||||||
@@ -61,15 +65,22 @@ body {
|
|||||||
margin-top: 50px; /* Add a top margin to avoid content overlay */
|
margin-top: 50px; /* Add a top margin to avoid content overlay */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Float three header columns side by side */
|
||||||
|
.header-button {
|
||||||
|
float: left;
|
||||||
|
width: 10%;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Float three header columns side by side */
|
/* Float three header columns side by side */
|
||||||
.header-column {
|
.header-column {
|
||||||
float: left;
|
float: left;
|
||||||
width: 28%;
|
width: 25%;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
/* Float three header columns side by side */
|
/* Float three header columns side by side */
|
||||||
.header-page-column {
|
.header-page-column {
|
||||||
float: left;
|
float: right;
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
width: 15%;
|
width: 15%;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ async fn logout_user() -> Result<reqwasm::http::Response, reqwasm::Error> {
|
|||||||
async fn list_users() -> Result<HashMap<String,i32>, reqwasm::Error> {
|
async fn list_users() -> Result<HashMap<String,i32>, reqwasm::Error> {
|
||||||
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
let backend_url : &'static str = dotenv!("BACKEND_URL");
|
||||||
let url = format!("{}/api/list_users", backend_url);
|
let url = format!("{}/api/list_users", backend_url);
|
||||||
let resp = Request::post(&url).send().await?;
|
let resp = Request::get(&url).send().await?;
|
||||||
let users = resp.json::<Vec<AxumUser>>().await?;
|
let users = resp.json::<Vec<AxumUser>>().await?;
|
||||||
let mut res = HashMap::new();
|
let mut res = HashMap::new();
|
||||||
for user in users {
|
for user in users {
|
||||||
@@ -202,7 +202,7 @@ async fn list_books(page: u32, userid: i32, sort: String) -> Result<PaginatedBoo
|
|||||||
let url = format!("{}/api/list?page={}&userid={}&sort={}", backend_url, page, userid, sort);
|
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);
|
||||||
|
|
||||||
let body = resp.json::<PaginatedBookUIList>().await?;
|
let body = resp.json::<PaginatedBookUIList>().await?;
|
||||||
Ok(body)
|
Ok(body)
|
||||||
@@ -219,7 +219,7 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
|
|
||||||
let value3 = create_signal(cx, String::new());
|
let value3 = create_signal(cx, String::new());
|
||||||
let input_ref3 = create_node_ref(cx);
|
let input_ref3 = create_node_ref(cx);
|
||||||
|
let completed = create_selector(cx, || *app_state.editmode.get());
|
||||||
let editchecked = create_signal(cx, false);
|
let editchecked = create_signal(cx, false);
|
||||||
|
|
||||||
let handle_submit = |event: Event| {
|
let handle_submit = |event: Event| {
|
||||||
@@ -233,6 +233,7 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
app_state.search.set(task.clone());
|
app_state.search.set(task.clone());
|
||||||
app_state.openlibrary.set(true);
|
app_state.openlibrary.set(true);
|
||||||
app_state.internalsearch.set(false);
|
app_state.internalsearch.set(false);
|
||||||
|
app_state.refreshing.set(false);
|
||||||
|
|
||||||
info!("Fetching search {}\n", task.clone());
|
info!("Fetching search {}\n", task.clone());
|
||||||
app_state.books.set(Vec::new());
|
app_state.books.set(Vec::new());
|
||||||
@@ -322,6 +323,11 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
app_state.dropdownselect.set(true);
|
app_state.dropdownselect.set(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
create_effect(cx, || {
|
||||||
|
// Calling checked.set will also update the `checked` property on the input element.
|
||||||
|
editchecked.set(*completed.get())
|
||||||
|
});
|
||||||
|
|
||||||
// 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().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>>());
|
||||||
|
|
||||||
@@ -341,7 +347,7 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
type="checkbox",
|
type="checkbox",
|
||||||
on:input=toggle_editmode,
|
on:input=toggle_editmode,
|
||||||
bind:checked=editchecked
|
bind:checked=editchecked
|
||||||
)
|
)("EDIT")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -362,6 +368,8 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
div(class="header-column"){
|
div(class="header-column"){
|
||||||
(if *app_state.editmode.get() == false {
|
(if *app_state.editmode.get() == false {
|
||||||
view!{ cx,
|
view!{ cx,
|
||||||
|
div(class="dropdown"){
|
||||||
|
|
||||||
button(on:click=dropdown_userselect) { "Select User" }
|
button(on:click=dropdown_userselect) { "Select User" }
|
||||||
(if *app_state.dropdownselect.get() == true {
|
(if *app_state.dropdownselect.get() == true {
|
||||||
view!{ cx,
|
view!{ cx,
|
||||||
@@ -377,6 +385,7 @@ pub fn Header<G: Html>(cx: Scope) -> View<G> {
|
|||||||
} else {
|
} else {
|
||||||
view!{cx, ""}
|
view!{cx, ""}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}} else {
|
}} else {
|
||||||
view!{cx, ""}
|
view!{cx, ""}
|
||||||
})
|
})
|
||||||
@@ -425,16 +434,15 @@ pub fn DropDownUser<G: Html>(cx: Scope, value: StringProp) -> View<G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
button(class="delete", on:click=handle_select_user){ (buttontext) }
|
button(class="dropdown-item", on:click=handle_select_user){ (buttontext) }br{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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 callback_signal = use_context::<RcSignal<bool>>(cx);
|
||||||
let csignal = callback_signal.clone();
|
/*
|
||||||
//callback_signal.clone().set(false);
|
|
||||||
create_effect(cx, || {
|
create_effect(cx, || {
|
||||||
let app_state = app_state.clone();
|
let app_state = app_state.clone();
|
||||||
let cxsignal = callback_signal.clone();
|
let cxsignal = callback_signal.clone();
|
||||||
@@ -446,7 +454,7 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
create_effect(cx, || {
|
create_effect(cx, || {
|
||||||
let app_state = app_state.clone();
|
let app_state = app_state.clone();
|
||||||
app_state.search.track();
|
app_state.search.track();
|
||||||
@@ -455,6 +463,7 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
app_state.internalsearch.track();
|
app_state.internalsearch.track();
|
||||||
app_state.refreshing.track();
|
app_state.refreshing.track();
|
||||||
//let csignal = csignals2.clone();
|
//let csignal = csignals2.clone();
|
||||||
|
//info!("Something triggered{}",*app_state.clone().search.clone());
|
||||||
|
|
||||||
//let tempb = app_state.books.get();
|
//let tempb = app_state.books.get();
|
||||||
//spawn_local( async move { info!(
|
//spawn_local( async move { info!(
|
||||||
@@ -533,7 +542,9 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
//info!("LibrarySearch triggered?");
|
||||||
if *app_state.refreshing.get() == false {
|
if *app_state.refreshing.get() == false {
|
||||||
|
info!("LibrarySearch triggered");
|
||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
if *app_state.search.get() != "" {
|
if *app_state.search.get() != "" {
|
||||||
if *app_state.openlibrary.get() == true {
|
if *app_state.openlibrary.get() == true {
|
||||||
@@ -553,7 +564,6 @@ async fn ListDB<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
|
|
||||||
let callback: Closure<dyn FnMut()> = Closure::new(move || {
|
let callback: Closure<dyn FnMut()> = Closure::new(move || {
|
||||||
//let csignal = callback_signal.clone();
|
//let csignal = callback_signal.clone();
|
||||||
csignal.set(true);
|
|
||||||
info!("Got scroll event");
|
info!("Got scroll event");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1126,7 +1136,11 @@ async fn SelectedUI<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
div(class="more-info"){
|
div(class="more-info"){
|
||||||
div(class="more-info-buttons"){
|
div(class="more-info-buttons"){
|
||||||
button(class="close", on:click=handle_close){ "CLOSE" }
|
button(class="close", on:click=handle_close){ "CLOSE" }
|
||||||
button(class="close", on:click=handle_edit){ "EDIT" }
|
(if *app_state.editmode.get() == true {
|
||||||
|
view!{ cx,button(class="close", on:click=handle_edit){ "EDIT" }}
|
||||||
|
} else {
|
||||||
|
view!{cx, ""}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
img(src=coverurl.get(),width="200")
|
img(src=coverurl.get(),width="200")
|
||||||
label{"Title: "}
|
label{"Title: "}
|
||||||
@@ -1279,8 +1293,6 @@ async fn LoginScreenUI<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
spawn_local(async move {
|
spawn_local(async move {
|
||||||
login_user(user)
|
login_user(user)
|
||||||
.await.expect("Couldn't login user");
|
.await.expect("Couldn't login user");
|
||||||
});
|
|
||||||
spawn_local(async move {
|
|
||||||
let auth = authentication_check().await.unwrap_or(false);
|
let auth = authentication_check().await.unwrap_or(false);
|
||||||
app_state.loggedin.set(auth);
|
app_state.loggedin.set(auth);
|
||||||
if auth == true {
|
if auth == true {
|
||||||
@@ -1320,7 +1332,7 @@ async fn LoginScreenUI<G: Html>(cx: Scope<'_>) -> View<G> {
|
|||||||
view!{cx,
|
view!{cx,
|
||||||
div(class="modal-content"){
|
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,type="password")
|
||||||
|
|
||||||
button(on:click=handle_login){ "LOGIN" }
|
button(on:click=handle_login){ "LOGIN" }
|
||||||
button(on:click=handle_register){ "REGISTER" }
|
button(on:click=handle_register){ "REGISTER" }
|
||||||
|
|||||||
Reference in New Issue
Block a user