diff --git a/Cargo.lock b/Cargo.lock index 399ade9..13cf9cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,8 +128,13 @@ name = "frontend" version = "0.1.0" dependencies = [ "anyhow", + "futures-channel", "gloo 0.10.0", + "gloo-net 0.4.0", + "serde", + "serde_json", "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", "yew", "yew-router", @@ -877,9 +882,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", diff --git a/Cargo.toml b/Cargo.toml index 035de76..3151af9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,19 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +# Misc +anyhow = "1.0.75" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +futures-channel = "0.3.28" + +# Yew yew = { version = "0.20.0", features = ["csr"] } yew-router = "0.17.0" -web-sys = { version = "0.3.64", features = ["HtmlInputElement"] } + +# Web wasm-bindgen = "0.2.87" +wasm-bindgen-futures = "0.4" +web-sys = { version = "0.3.64", features = ["HtmlInputElement"] } gloo = "0.10.0" -anyhow = "1.0.75" \ No newline at end of file +gloo-net = "0.4.0" \ No newline at end of file diff --git a/src/backend/data.rs b/src/backend/data.rs new file mode 100644 index 0000000..7a4ca62 --- /dev/null +++ b/src/backend/data.rs @@ -0,0 +1,6 @@ +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct AccountAuthenticateResponse { + pub token: String, +} diff --git a/src/backend/mod.rs b/src/backend/mod.rs index e81c400..44fe39f 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,4 +1,10 @@ +mod data; + use anyhow::Result; +use gloo_net::http::Request; +use serde_json::json; +use web_sys::RequestMode; +use yew::Callback; #[derive(Clone, PartialEq)] pub struct Session { @@ -23,12 +29,33 @@ impl Session { } } - pub fn login(&mut self, username: &str, password: &str) -> Result<()> { - gloo::console::log!("Login: ", username, " || ", password); - Ok(()) + pub fn login(&self, username: String, password: String, callback: Callback>) { + let url = format!("{}/account/authenticate", &self.base_url); + + let body = json!({ + "username": username, + "password": password + }); + + let call = async move { + let request = Request::post(&url).mode(RequestMode::Cors).json(&body)?; + let response = request + .send() + .await? + .json::() + .await?; + + Ok(response.token) + }; + + wasm_bindgen_futures::spawn_local(async move { callback.emit(call.await) }); + } + + pub fn set_token(&mut self, token: String) { + self.auth_token = Some(token); } pub fn is_authenticated(&self) -> bool { self.auth_token.is_some() } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 6a0f0e5..a7c1124 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod backend; mod content; mod topbar; +use anyhow::Result; use backend::Session; use content::{error, home::Home}; use std::ops::Deref; @@ -36,20 +37,20 @@ fn switch(routes: Route) -> Html { #[derive(Clone, PartialEq)] pub struct Callbacks { - pub sign_in_callback: Callback<(String, String)>, + pub sign_in_callback: Callback>, } #[function_component] fn App() -> Html { - let state = use_state(Session::default); + // let state = use_state(Session::default); + let state = use_state(|| Session::new("http://localhost:8080".to_string())); let cloned_state = state.clone(); let callbacks = use_state(move || Callbacks { - sign_in_callback: Callback::from(move |data: (String, String)| { + sign_in_callback: Callback::from(move |response: Result| { let mut new_state = cloned_state.deref().clone(); - new_state - .login(data.0.as_str(), data.1.as_str()) - .expect("Login failed"); + + new_state.set_token(response.expect("!!! remove this temporary expect !!!")); cloned_state.set(new_state); }), }); diff --git a/src/topbar/guest/mod.rs b/src/topbar/guest/mod.rs index f6c207f..eaad046 100644 --- a/src/topbar/guest/mod.rs +++ b/src/topbar/guest/mod.rs @@ -2,7 +2,6 @@ mod signin; mod signup; use crate::topbar::Tab; -use crate::Callbacks; use signin::SignIn; use signup::SignUp; use std::rc::Rc; @@ -50,7 +49,6 @@ impl Reducible for State { #[function_component] pub fn TopBar() -> Html { let state = use_reducer(State::default); - let callbacks = use_context::().expect("Callbacks context not available!"); let sign_in_onclick = { let state = state.clone(); @@ -77,7 +75,7 @@ pub fn TopBar() -> Html { if state.sign_in { - + } if state.sign_up { diff --git a/src/topbar/guest/signin.rs b/src/topbar/guest/signin.rs index 11bfe8b..f11ea92 100644 --- a/src/topbar/guest/signin.rs +++ b/src/topbar/guest/signin.rs @@ -1,3 +1,5 @@ +use crate::backend::Session; +use crate::Callbacks; use std::ops::Deref; use wasm_bindgen::JsCast; use web_sys::HtmlInputElement; @@ -9,14 +11,11 @@ struct Data { pub password: String, } -#[derive(Properties, PartialEq)] -pub struct Props { - pub callback: Callback<(String, String)>, -} - #[function_component] -pub fn SignIn(props: &Props) -> Html { +pub fn SignIn() -> Html { let state = use_state(|| Data::default()); + let callbacks = use_context::().expect("Callbacks context not available!"); + let session = use_context::().unwrap_or_default(); let cloned_state = state.clone(); let on_username_changed = Callback::from(move |event: Event| { @@ -44,14 +43,16 @@ pub fn SignIn(props: &Props) -> Html { cloned_state.set(data); }); - let cloned_state = state.clone(); - let callback = props.callback.clone(); let onsubmit = Callback::from(move |event: SubmitEvent| { event.prevent_default(); - let data = cloned_state.deref().clone(); + let state = state.deref().clone(); - callback.emit((data.username, data.password)); + session.login( + state.username, + state.password, + callbacks.sign_in_callback.clone(), + ); }); html! {