Implement client-side logout

This commit is contained in:
Valentin Tolmer 2021-05-23 17:07:02 +02:00
parent 054f970f91
commit e07efc9585
3 changed files with 52 additions and 13 deletions

View File

@ -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<()>>) -> Result<FetchTask> {
let url = "/auth/logout";
let handler = move |response: Response<Result<String>>| {
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())
}
}

View File

@ -23,8 +23,11 @@ pub fn set_cookie(cookie_name: &str, value: &str, expiration: &DateTime<Utc>) ->
d.dyn_into::<web_sys::HtmlDocument>()
.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<Option<String>> {

View File

@ -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<Self>,
on_logged_out: Callback<()>,
// Used to keep the request alive long enough.
_task: Option<FetchTask>,
}
#[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! {
<button onclick=self.link.callback(|_| { Msg::Logout })>{"Logout"}</button>
<button onclick=self.link.callback(|_| { Msg::LogoutRequested })>{"Logout"}</button>
}
}
}