use topcoat::{
context::{Cx, try_request_context},
cookie::{CookieJar, CookieJarCell, Cookies, cookie_store, cookies},
};
use crate::outcome::Notification;
pub(crate) const COOKIE_NAME: &str = "__Host-tablo_notification";
fn hardened(jar: &CookieJar) -> impl Cookies + '_ {
jar.default_path("/")
.default_http_only(true)
.default_secure(true)
.default_same_site(topcoat::cookie::SameSite::Lax)
}
pub fn set_notification(cx: &Cx, notification: Notification) {
if try_request_context::<CookieJarCell>(cx).is_none() {
return;
}
if let Err(error) = cookie_store::<Notification, _>(hardened(cookies(cx)), COOKIE_NAME)
.set(notification)
.commit()
{
tracing::error!(error = %error, "flash notification commit failed");
}
}
pub(crate) fn notify_write_failure(cx: &Cx, failure: &'static str) {
set_notification(
cx,
Notification::error(crate::t!(cx, failure))
.description(crate::t!(cx, "tablo-failed-description")),
);
}
pub fn take_notification(cx: &Cx) -> Option<Notification> {
try_request_context::<CookieJarCell>(cx)?;
let unparsed = cookie_store::<Notification, _>(hardened(cookies(cx)), COOKIE_NAME);
match unparsed.parse() {
Ok(Some(store)) => {
let notification = store.get();
store.remove();
Some(notification)
}
Err(_) => {
cookie_store::<Notification, _>(hardened(cookies(cx)), COOKIE_NAME).remove();
None
}
Ok(None) => None,
}
}
#[cfg(test)]
mod tests;