From 9e0fd44448248fb85d86498724ef1fbd59299d41 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Thu, 17 Jun 2021 14:31:18 +0000 Subject: [PATCH] Working login flow. --- Cargo.lock | 127 ++++++++------------------- web-ui/crate/Cargo.toml | 15 +--- web-ui/crate/src/components/login.rs | 29 +----- web-ui/crate/src/lib.rs | 98 ++++++++++++++++----- web-ui/crate/src/state.rs | 21 +++++ 5 files changed, 140 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa5fde9..9a30a1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,6 +390,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg-match" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8100e46ff92eb85bf6dc2930c73f2a4f7176393c84a9446b3d501e1b354e7b34" + [[package]] name = "chacha20" version = "0.6.0" @@ -2728,12 +2734,6 @@ dependencies = [ "uncased", ] -[[package]] -name = "route-recognizer" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824172f0afccf3773c3905f5550ac94572144efe0deaf49a1f22bbca188d193e" - [[package]] name = "ruma" version = "0.1.2" @@ -3014,12 +3014,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -[[package]] -name = "scoped-tls-hkt" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63" - [[package]] name = "scopeguard" version = "1.1.0" @@ -3592,9 +3586,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "yew", - "yew-functional", "yew-router", - "yew-services", "yewdux", "yewtil", ] @@ -4221,28 +4213,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "weblog" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eec0958e0181982bc8b4577b1363f21300a670603615c58643f172c92c47357" -dependencies = [ - "wasm-bindgen", - "web-sys", - "weblog-proc-macro", -] - -[[package]] -name = "weblog-proc-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d9abb8ee84ede5408a346721d72fb216a27f53a539ff3c83ed1bf7625af7104" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "which" version = "4.1.0" @@ -4335,18 +4305,22 @@ checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71" [[package]] name = "yew" -version = "0.17.4" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4d5154faef86dddd2eb333d4755ea5643787d20aca683e58759b0e53351409f" dependencies = [ "anyhow", "anymap", "bincode", + "cfg-if 1.0.0", + "cfg-match", "console_error_panic_hook", "gloo", "http", "indexmap", "js-sys", "log", + "ryu", "serde", "serde_json", "slab", @@ -4357,31 +4331,11 @@ dependencies = [ "yew-macro", ] -[[package]] -name = "yew-functional" -version = "0.13.0" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" -dependencies = [ - "scoped-tls-hkt", - "wasm-bindgen", - "yew", - "yew-functional-macro", -] - -[[package]] -name = "yew-functional-macro" -version = "0.1.0" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "yew-macro" -version = "0.17.0" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6e23bfe3dc3933fbe9592d149c9985f3047d08c637a884b9344c21e56e092ef" dependencies = [ "boolinator", "lazy_static", @@ -4392,68 +4346,65 @@ dependencies = [ [[package]] name = "yew-router" -version = "0.14.0" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27666236d9597eac9be560e841e415e20ba67020bc8cd081076be178e159c8bc" dependencies = [ + "cfg-if 1.0.0", + "cfg-match", "gloo", "js-sys", - "route-recognizer", + "log", + "nom 5.1.2", "serde", - "serde_urlencoded", + "serde_json", "wasm-bindgen", "web-sys", - "weblog", "yew", "yew-router-macro", + "yew-router-route-parser", ] [[package]] name = "yew-router-macro" -version = "0.14.0" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c0ace2924b7a175e2d1c0e62ee7022a5ad840040dcd52414ce5f410ab322dba" dependencies = [ - "heck", "proc-macro2", "quote", "syn", + "yew-router-route-parser", ] [[package]] -name = "yew-services" -version = "0.1.0" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" +name = "yew-router-route-parser" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de4a67208fb46b900af18a7397938b01f379dfc18da34799cfa8347eec715697" dependencies = [ - "anyhow", - "gloo", - "http", - "js-sys", - "serde", - "serde_json", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "yew", + "nom 5.1.2", ] [[package]] name = "yewdux" -version = "0.6.1" -source = "git+https://github.com/deftsp/yewdux?rev=dbda686#dbda686dea05c0efaef0cd3af46012033071f40e" +version = "0.6.2" +source = "git+https://github.com/intendednull/yewdux?rev=v0.6.2#a6d8dbf69d472a2d0e82ab70237b16e86865c994" dependencies = [ "serde", "yew", - "yew-services", ] [[package]] name = "yewtil" -version = "0.3.2" -source = "git+https://github.com/yewstack/yew?rev=246bc59#246bc5960b504258b0603bc76760777e6650c91d" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8543663ac49cd613df079282a1d8bdbdebdad6e02bac229f870fd4237b5d9aaa" dependencies = [ "log", "wasm-bindgen", "wasm-bindgen-futures", + "web-sys", "yew", ] diff --git a/web-ui/crate/Cargo.toml b/web-ui/crate/Cargo.toml index 6c51a42..f9434e5 100644 --- a/web-ui/crate/Cargo.toml +++ b/web-ui/crate/Cargo.toml @@ -13,20 +13,13 @@ crate-type = ["cdylib", "rlib"] tenebrous-api = { path = "../../api" } [dependencies] -# yew = { version = "0.18" } -# yewtil = {version = "0.4" } -# yew-router = {version = "0.15" } -# yewdux = {version = "^0.6" } -yew = { git = "https://github.com/yewstack/yew", rev = "246bc59" } -yew-functional = { git = "https://github.com/yewstack/yew", rev = "246bc59" } -yew-router = { git = "https://github.com/yewstack/yew", rev = "246bc59" } -yew-services = { git = "https://github.com/yewstack/yew", rev = "246bc59" } -yewtil = { git = "https://github.com/yewstack/yew", rev = "246bc59"} -yewdux = { git = "https://github.com/deftsp/yewdux", rev = "dbda686"} +yew = { version = "0.18" } +yewtil = {version = "0.4" } +yew-router = {version = "0.15" } +yewdux = { git = "https://github.com/intendednull/yewdux", rev = "v0.6.2"} wasm-bindgen = { version = "0.2" } wasm-bindgen-futures = "0.4" js-sys = "0.3" -#grpc-web-client = "0.1" graphql_client = { git = "https://github.com/graphql-rust/graphql-client", branch = "master" } graphql_client_web = { git = "https://github.com/graphql-rust/graphql-client", branch = "master" } serde = { version = "1.0.67", features = ["derive"] } diff --git a/web-ui/crate/src/components/login.rs b/web-ui/crate/src/components/login.rs index 41f930c..650e94b 100644 --- a/web-ui/crate/src/components/login.rs +++ b/web-ui/crate/src/components/login.rs @@ -25,20 +25,14 @@ pub enum LoginAction { } pub(crate) type Login = WithDispatch; + async fn do_login( dispatch: &WebUiDispatcher, username: &str, password: &str, ) -> Result<(), UiError> { let jwt = api::auth::login(username, password).await?; - //state.jwt_token = Some(jwt); - dispatch.send(Action::UpdateJwt(jwt)); - Ok(()) -} - -async fn do_refresh_jwt(dispatch: &WebUiDispatcher) -> Result<(), UiError> { - let jwt = api::auth::refresh_jwt().await?; - dispatch.send(Action::UpdateJwt(jwt)); + dispatch.send(Action::Login(jwt)); Ok(()) } @@ -78,31 +72,12 @@ impl Component for YewduxLogin { self.dispatch.neq_assign(Rc::new(dispatch)) } - fn rendered(&mut self, first_render: bool) { - if first_render { - // - } - } - fn view(&self) -> Html { - // let do_the_login = self.dispatch.reduce_callback(|state| { - // spawn_local(async move { - // do_login(state, "user", "pw").await; - // }); - // }); - let do_the_login = self.link.callback(move |e: FocusEvent| { e.prevent_default(); LoginAction::Login }); - // let refresh_jwt = self.link.callback(move |_| { - // let dispatch = dispatch2.clone(); - // spawn_local(async move { - // do_refresh_jwt(&*dispatch).await; - // }); - // }); - let update_username = self .link .callback(|e: InputData| LoginAction::UpdateUsername(e.value)); diff --git a/web-ui/crate/src/lib.rs b/web-ui/crate/src/lib.rs index c26d219..e760859 100644 --- a/web-ui/crate/src/lib.rs +++ b/web-ui/crate/src/lib.rs @@ -1,11 +1,16 @@ use crate::components::error_message::ErrorMessage; use crate::components::login::Login; +use error::UiError; use rooms::RoomList; use rooms::YewduxRoomList; +use state::{Action, AuthState, WebUiDispatcher}; use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::spawn_local; use yew::prelude::*; use yew_router::prelude::*; +use yew_router::{components::RouterAnchor, prelude::*, switch::Permissive}; use yewdux::prelude::*; +use yewtil::NeqAssign; pub mod api; pub mod components; @@ -14,20 +19,20 @@ pub mod grpc; pub mod rooms; pub mod state; -#[derive(Routable, PartialEq, Clone, Debug)] +#[derive(Clone, Debug, Switch)] pub enum AppRoute { - #[at("/rooms")] + #[to = "/rooms"] Rooms, - #[at("/rooms/{room_id}")] + #[to = "/rooms/{room_id}"] Room { room_id: String }, - #[at("/")] + #[to = "/"] Index, } type AppRouter = Router; -type AppAnchor = Link; //For rendering clickable links. +type AppAnchor = RouterAnchor; //For rendering clickable links. -fn render_route(routes: &AppRoute) -> Html { +fn render_route(routes: AppRoute) -> Html { match routes { AppRoute::Rooms => { html! { @@ -36,13 +41,12 @@ fn render_route(routes: &AppRoute) -> Html { } AppRoute::Room { room_id } => { html! { -
{"This is the specifi roompage."}
+
{"This is the specific room page."}
} } AppRoute::Index => { html! {
-
@@ -51,34 +55,80 @@ fn render_route(routes: &AppRoute) -> Html { } } -struct App; +struct YewduxApp { + link: ComponentLink, + dispatch: WebUiDispatcher, +} -impl Component for App { +type App = WithDispatch; + +async fn refresh_jwt(dispatch: &WebUiDispatcher) { + match api::auth::refresh_jwt().await { + Ok(jwt) => { + dispatch.send(Action::Login(jwt)); + } + Err(e) => { + web_sys::console::log_1(&e.to_string().into()); + dispatch.send(Action::ChangeAuthState(AuthState::NotLoggedIn)); + } + } +} + +impl Component for YewduxApp { type Message = (); - type Properties = (); + type Properties = WebUiDispatcher; - fn create(_: Self::Properties, _link: ComponentLink) -> Self { - Self + fn create(dispatch: Self::Properties, link: ComponentLink) -> Self { + Self { dispatch, link } } fn update(&mut self, _: Self::Message) -> ShouldRender { false } - fn change(&mut self, _: Self::Properties) -> ShouldRender { - false + fn change(&mut self, dispatch: Self::Properties) -> ShouldRender { + self.dispatch.neq_assign(dispatch) + } + + fn rendered(&mut self, first_render: bool) { + if first_render { + let auth_state = self.dispatch.state().auth_state; + + if auth_state == AuthState::RefreshNeeded { + let dispatch = self.dispatch.clone(); + spawn_local(async move { + refresh_jwt(&dispatch).await; + }); + } + } } fn view(&self) -> Html { - html! { -
- -
- -
-
+ let auth_state = self.dispatch.state().auth_state; + + match auth_state { + AuthState::RefreshNeeded => { + html! { +
{"Loading..."}
+ } + } + AuthState::NotLoggedIn => { + html! { + + } + } + AuthState::LoggedIn => { + html! { +
+ +
+ +
+
+ } + } } } } diff --git a/web-ui/crate/src/state.rs b/web-ui/crate/src/state.rs index 591b39f..7d9d56f 100644 --- a/web-ui/crate/src/state.rs +++ b/web-ui/crate/src/state.rs @@ -8,8 +8,22 @@ pub(crate) struct Room { pub display_name: String, } +#[derive(Clone, Copy, Eq, PartialEq)] +pub(crate) enum AuthState { + NotLoggedIn, + LoggedIn, + RefreshNeeded, +} + +impl Default for AuthState { + fn default() -> Self { + AuthState::RefreshNeeded + } +} + #[derive(Default, Clone)] pub(crate) struct WebUiState { + pub auth_state: AuthState, pub jwt_token: Option, pub rooms: Vec, pub error_messages: Vec, @@ -20,6 +34,8 @@ pub(crate) enum Action { AddRoom(Room), ErrorMessage(UiError), ClearErrorMessage, + ChangeAuthState(AuthState), + Login(String), } impl Reducer for WebUiState { @@ -32,7 +48,12 @@ impl Reducer for WebUiState { fn reduce(&mut self, action: Self::Action) -> bool { match action { Action::UpdateJwt(jwt_token) => self.jwt_token = Some(jwt_token), + Action::Login(jwt_token) => { + self.jwt_token = Some(jwt_token); + self.auth_state = AuthState::LoggedIn; + } Action::AddRoom(room) => self.rooms.push(room.clone()), + Action::ChangeAuthState(auth_state) => self.auth_state = auth_state, Action::ErrorMessage(error) => self.error_messages.push(error.to_string()), Action::ClearErrorMessage => { if self.error_messages.len() > 0 {