feat: implemented signin api call

This commit is contained in:
antifallobst 2023-10-02 15:53:33 +02:00
parent 8c756a4eb6
commit d0e119eabc
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
7 changed files with 75 additions and 27 deletions

9
Cargo.lock generated
View File

@ -128,8 +128,13 @@ name = "frontend"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"futures-channel",
"gloo 0.10.0", "gloo 0.10.0",
"gloo-net 0.4.0",
"serde",
"serde_json",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-futures",
"web-sys", "web-sys",
"yew", "yew",
"yew-router", "yew-router",
@ -877,9 +882,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.105" version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",

View File

@ -6,9 +6,19 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [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 = { version = "0.20.0", features = ["csr"] }
yew-router = "0.17.0" yew-router = "0.17.0"
web-sys = { version = "0.3.64", features = ["HtmlInputElement"] }
# Web
wasm-bindgen = "0.2.87" wasm-bindgen = "0.2.87"
wasm-bindgen-futures = "0.4"
web-sys = { version = "0.3.64", features = ["HtmlInputElement"] }
gloo = "0.10.0" gloo = "0.10.0"
anyhow = "1.0.75" gloo-net = "0.4.0"

6
src/backend/data.rs Normal file
View File

@ -0,0 +1,6 @@
use serde::Deserialize;
#[derive(Deserialize)]
pub struct AccountAuthenticateResponse {
pub token: String,
}

View File

@ -1,4 +1,10 @@
mod data;
use anyhow::Result; use anyhow::Result;
use gloo_net::http::Request;
use serde_json::json;
use web_sys::RequestMode;
use yew::Callback;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct Session { pub struct Session {
@ -23,12 +29,33 @@ impl Session {
} }
} }
pub fn login(&mut self, username: &str, password: &str) -> Result<()> { pub fn login(&self, username: String, password: String, callback: Callback<Result<String>>) {
gloo::console::log!("Login: ", username, " || ", password); let url = format!("{}/account/authenticate", &self.base_url);
Ok(())
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::<data::AccountAuthenticateResponse>()
.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 { pub fn is_authenticated(&self) -> bool {
self.auth_token.is_some() self.auth_token.is_some()
} }
} }

View File

@ -2,6 +2,7 @@ mod backend;
mod content; mod content;
mod topbar; mod topbar;
use anyhow::Result;
use backend::Session; use backend::Session;
use content::{error, home::Home}; use content::{error, home::Home};
use std::ops::Deref; use std::ops::Deref;
@ -36,20 +37,20 @@ fn switch(routes: Route) -> Html {
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct Callbacks { pub struct Callbacks {
pub sign_in_callback: Callback<(String, String)>, pub sign_in_callback: Callback<Result<String>>,
} }
#[function_component] #[function_component]
fn App() -> Html { 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 cloned_state = state.clone();
let callbacks = use_state(move || Callbacks { let callbacks = use_state(move || Callbacks {
sign_in_callback: Callback::from(move |data: (String, String)| { sign_in_callback: Callback::from(move |response: Result<String>| {
let mut new_state = cloned_state.deref().clone(); let mut new_state = cloned_state.deref().clone();
new_state
.login(data.0.as_str(), data.1.as_str()) new_state.set_token(response.expect("!!! remove this temporary expect !!!"));
.expect("Login failed");
cloned_state.set(new_state); cloned_state.set(new_state);
}), }),
}); });

View File

@ -2,7 +2,6 @@ mod signin;
mod signup; mod signup;
use crate::topbar::Tab; use crate::topbar::Tab;
use crate::Callbacks;
use signin::SignIn; use signin::SignIn;
use signup::SignUp; use signup::SignUp;
use std::rc::Rc; use std::rc::Rc;
@ -50,7 +49,6 @@ impl Reducible for State {
#[function_component] #[function_component]
pub fn TopBar() -> Html { pub fn TopBar() -> Html {
let state = use_reducer(State::default); let state = use_reducer(State::default);
let callbacks = use_context::<Callbacks>().expect("Callbacks context not available!");
let sign_in_onclick = { let sign_in_onclick = {
let state = state.clone(); let state = state.clone();
@ -77,7 +75,7 @@ pub fn TopBar() -> Html {
</ul> </ul>
if state.sign_in { if state.sign_in {
<SignIn callback={callbacks.sign_in_callback}/> <SignIn/>
} }
if state.sign_up { if state.sign_up {

View File

@ -1,3 +1,5 @@
use crate::backend::Session;
use crate::Callbacks;
use std::ops::Deref; use std::ops::Deref;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
use web_sys::HtmlInputElement; use web_sys::HtmlInputElement;
@ -9,14 +11,11 @@ struct Data {
pub password: String, pub password: String,
} }
#[derive(Properties, PartialEq)]
pub struct Props {
pub callback: Callback<(String, String)>,
}
#[function_component] #[function_component]
pub fn SignIn(props: &Props) -> Html { pub fn SignIn() -> Html {
let state = use_state(|| Data::default()); let state = use_state(|| Data::default());
let callbacks = use_context::<Callbacks>().expect("Callbacks context not available!");
let session = use_context::<Session>().unwrap_or_default();
let cloned_state = state.clone(); let cloned_state = state.clone();
let on_username_changed = Callback::from(move |event: Event| { let on_username_changed = Callback::from(move |event: Event| {
@ -44,14 +43,16 @@ pub fn SignIn(props: &Props) -> Html {
cloned_state.set(data); cloned_state.set(data);
}); });
let cloned_state = state.clone();
let callback = props.callback.clone();
let onsubmit = Callback::from(move |event: SubmitEvent| { let onsubmit = Callback::from(move |event: SubmitEvent| {
event.prevent_default(); 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! { html! {