From e07efc9585701c9fb61f14ba9ae6384988a7c398 Mon Sep 17 00:00:00 2001 From: Valentin Tolmer Date: Sun, 23 May 2021 17:07:02 +0200 Subject: [PATCH] Implement client-side logout --- app/src/api.rs | 19 +++++++++++++++++++ app/src/cookies.rs | 7 +++++-- app/src/logout.rs | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/app/src/api.rs b/app/src/api.rs index fd8f682..9982625 100644 --- a/app/src/api.rs +++ b/app/src/api.rs @@ -83,4 +83,23 @@ impl HostService { .body(Json(&request))?; FetchService::fetch_with_options(request, get_default_options(), handler.into()) } + + pub fn logout(callback: Callback>) -> Result { + let url = "/auth/logout"; + let handler = move |response: Response>| { + let (meta, maybe_data) = response.into_parts(); + let message = maybe_data + .map_err(|e| anyhow!("Could not reach authentication server: {}", e)) + .and_then(|data| { + if meta.status.is_success() { + Ok(()) + } else { + Err(anyhow!("Could not logout: [{}]: {}", meta.status, data)) + } + }); + callback.emit(message) + }; + let request = Request::post(url).body(yew::format::Nothing)?; + FetchService::fetch_with_options(request, get_default_options(), handler.into()) + } } diff --git a/app/src/cookies.rs b/app/src/cookies.rs index 4dfd76d..e6469df 100644 --- a/app/src/cookies.rs +++ b/app/src/cookies.rs @@ -23,8 +23,11 @@ pub fn set_cookie(cookie_name: &str, value: &str, expiration: &DateTime) -> d.dyn_into::() .map_err(|_| anyhow!("Document is not an HTMLDocument")) })?; - doc.set_cookie(&format!("{}={};expires={};sameSite=Strict", cookie_name, value, expiration)) - .map_err(|_| anyhow!("Could not set cookie")) + doc.set_cookie(&format!( + "{}={};expires={};sameSite=Strict", + cookie_name, value, expiration + )) + .map_err(|_| anyhow!("Could not set cookie")) } pub fn get_cookie(cookie_name: &str) -> Result> { diff --git a/app/src/logout.rs b/app/src/logout.rs index a47f55f..c7d84ff 100644 --- a/app/src/logout.rs +++ b/app/src/logout.rs @@ -1,10 +1,13 @@ -use crate::cookies::delete_cookie; +use crate::{api::HostService, cookies::delete_cookie}; +use anyhow::Result; use yew::prelude::*; -use yew::services::ConsoleService; +use yew::services::{fetch::FetchTask, ConsoleService}; pub struct LogoutButton { link: ComponentLink, on_logged_out: Callback<()>, + // Used to keep the request alive long enough. + _task: Option, } #[derive(Clone, PartialEq, Properties)] @@ -13,7 +16,8 @@ pub struct Props { } pub enum Msg { - Logout, + LogoutRequested, + LogoutCompleted(Result<()>), } impl Component for LogoutButton { @@ -24,21 +28,34 @@ impl Component for LogoutButton { LogoutButton { link: link.clone(), on_logged_out: props.on_logged_out, + _task: None, } } fn update(&mut self, msg: Self::Message) -> ShouldRender { match msg { - Msg::Logout => match delete_cookie("user_id") { - Err(e) => { + Msg::LogoutRequested => { + match HostService::logout(self.link.callback(Msg::LogoutCompleted)) { + Ok(task) => self._task = Some(task), + Err(e) => ConsoleService::error(&e.to_string()), + }; + false + } + Msg::LogoutCompleted(res) => { + if let Err(e) = res { ConsoleService::error(&e.to_string()); - false } - Ok(()) => { - self.on_logged_out.emit(()); - true + match delete_cookie("user_id") { + Err(e) => { + ConsoleService::error(&e.to_string()); + false + } + Ok(()) => { + self.on_logged_out.emit(()); + true + } } - }, + } } } @@ -48,7 +65,7 @@ impl Component for LogoutButton { fn view(&self) -> Html { html! { - + } } }