diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 44fe39f..2d46af7 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,6 +1,6 @@ mod data; -use anyhow::Result; +use anyhow::{Error, Result}; use gloo_net::http::Request; use serde_json::json; use web_sys::RequestMode; @@ -29,7 +29,13 @@ impl Session { } } - pub fn login(&self, username: String, password: String, callback: Callback>) { + pub fn login( + &self, + username: String, + password: String, + callback: Callback<(Result, Callback>)>, + status_callback: Callback>, + ) { let url = format!("{}/account/authenticate", &self.base_url); let body = json!({ @@ -39,16 +45,25 @@ impl Session { let call = async move { let request = Request::post(&url).mode(RequestMode::Cors).json(&body)?; - let response = request - .send() - .await? - .json::() - .await?; + let response = request.send().await?; - Ok(response.token) + match response.status() { + 200 => Ok(response + .json::() + .await? + .token), + 400 => Err(Error::msg(format!("Bad request"))), + 401 => Err(Error::msg(format!("Wrong password!"))), + 403 => Err(Error::msg(format!("You're not allowed to do this!"))), + 404 => Err(Error::msg(format!("Unknown username!"))), + 424 => Err(Error::msg(format!("This account is not verified!"))), + e => Err(Error::msg(format!("Unknown response: {e}"))), + } }; - wasm_bindgen_futures::spawn_local(async move { callback.emit(call.await) }); + wasm_bindgen_futures::spawn_local( + async move { callback.emit((call.await, status_callback)) }, + ); } pub fn set_token(&mut self, token: String) { diff --git a/src/main.rs b/src/main.rs index a7c1124..70e8aea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,7 @@ fn switch(routes: Route) -> Html { #[derive(Clone, PartialEq)] pub struct Callbacks { - pub sign_in_callback: Callback>, + pub sign_in_callback: Callback<(Result, Callback>)>, } #[function_component] @@ -47,12 +47,21 @@ fn App() -> Html { let cloned_state = state.clone(); let callbacks = use_state(move || Callbacks { - sign_in_callback: Callback::from(move |response: Result| { - let mut new_state = cloned_state.deref().clone(); + sign_in_callback: Callback::from( + move |response: (Result, Callback>)| { + let mut new_state = cloned_state.deref().clone(); - new_state.set_token(response.expect("!!! remove this temporary expect !!!")); - cloned_state.set(new_state); - }), + response.1.emit(match response.0 { + Ok(token) => { + new_state.set_token(token); + Ok(()) + } + Err(e) => Err(e), + }); + + cloned_state.set(new_state); + }, + ), }); html! { diff --git a/src/topbar/guest/mod.rs b/src/topbar/guest/mod.rs index eaad046..107cb3f 100644 --- a/src/topbar/guest/mod.rs +++ b/src/topbar/guest/mod.rs @@ -2,6 +2,7 @@ mod signin; mod signup; use crate::topbar::Tab; +use anyhow::Result; use signin::SignIn; use signup::SignUp; use std::rc::Rc; @@ -10,11 +11,16 @@ use yew::prelude::*; pub enum Action { ToggleSignIn, ToggleSignUp, + + SignInStatus(String), } pub struct State { sign_in: bool, sign_up: bool, + + sign_in_status: AttrValue, + sign_up_status: AttrValue, } impl Default for State { @@ -22,6 +28,9 @@ impl Default for State { Self { sign_in: false, sign_up: false, + + sign_in_status: AttrValue::default(), + sign_up_status: AttrValue::default(), } } } @@ -41,6 +50,11 @@ impl Reducible for State { state.sign_in = false; state.sign_up = !self.sign_up; } + Action::SignInStatus(s) => { + state.sign_in = true; + state.sign_up = false; + state.sign_in_status = s.into(); + } } Rc::new(state) } @@ -60,6 +74,14 @@ pub fn TopBar() -> Html { Callback::from(move |_| state.dispatch(Action::ToggleSignUp)) }; + let sign_in_status = { + let state = state.clone(); + Callback::from(move |status: Result<()>| match status { + Ok(_) => state.dispatch(Action::ToggleSignIn), + Err(e) => state.dispatch(Action::SignInStatus(e.to_string())), + }) + }; + html! {