1use http_types::cookies::SameSite;
2use tide::http::cookies::Cookie;
3
4use crate::{Flash, FlashMessage, FlashStore};
5
6#[derive(Debug)]
7pub struct CookieConfig {
8 pub max_age: time::Duration,
9 pub site: SameSite,
10 pub http_only: bool,
11 pub path: String,
12}
13
14impl Default for CookieConfig {
15 fn default() -> Self {
16 Self {
17 max_age: time::Duration::seconds(60),
18 site: SameSite::Lax,
19 http_only: true,
20 path: String::from("/"),
21 }
22 }
23}
24
25#[derive(Debug)]
26pub struct CookieStore {
27 pub config: CookieConfig,
28}
29
30impl Default for CookieStore {
31 fn default() -> Self {
32 Self {
33 config: CookieConfig::default(),
34 }
35 }
36}
37
38impl FlashStore for CookieStore {
39 fn load<State>(&self, req: &tide::Request<State>) -> Option<Vec<FlashMessage>> {
40 match req.cookie("_flash") {
41 None => None,
42 Some(cookie) => {
43 let messages: Vec<FlashMessage> =
44 serde_json::from_str(cookie.value()).unwrap_or_default();
45 Some(messages)
46 }
47 }
48 }
49
50 fn insert(&self, res: &mut tide::Response) {
51 if let Some(flash) = res.ext::<Flash>() {
52 res.insert_cookie(
53 Cookie::build(
54 "_flash",
55 serde_json::to_string(&flash.messages).unwrap_or_default(),
56 )
57 .max_age(self.config.max_age)
58 .same_site(self.config.site)
59 .http_only(self.config.http_only)
60 .path(self.config.path.clone())
61 .finish(),
62 );
63 }
64 }
65
66 fn clear(&self, res: &mut tide::Response) {
67 res.insert_cookie(
68 Cookie::build("_flash", "")
69 .max_age(time::Duration::seconds(0))
70 .same_site(self.config.site)
71 .http_only(self.config.http_only)
72 .path(self.config.path.clone())
73 .finish(),
74 );
75 }
76}