axum_security/cookie/store/
mod.rs1mod memory;
2
3use std::{error::Error, pin::Pin, sync::Arc};
4
5pub use memory::MemStore;
6
7use crate::cookie::{CookieSession, SessionId};
8
9pub trait CookieStore: Send + Sync + 'static {
10 type State: Send + Sync + 'static;
11 type Error: std::error::Error + Send + Sync + 'static;
12
13 fn spawn_maintenance_task(&self) -> bool {
14 true
15 }
16
17 fn store_session(
18 &self,
19 session: CookieSession<Self::State>,
20 ) -> impl Future<Output = Result<(), Self::Error>> + Send;
21
22 fn remove_session(
23 &self,
24 id: &SessionId,
25 ) -> impl Future<Output = Result<Option<CookieSession<Self::State>>, Self::Error>> + Send;
26
27 fn load_session(
28 &self,
29 id: &SessionId,
30 ) -> impl Future<Output = Result<Option<CookieSession<Self::State>>, Self::Error>> + Send;
31
32 fn remove_before(&self, deadline: u64) -> impl Future<Output = Result<(), Self::Error>> + Send;
33}
34
35pub type BoxDynError = Box<dyn Error + Send + 'static>;
36
37#[allow(clippy::type_complexity)]
38trait DynStore<S>: Send + Sync + 'static {
39 fn spawn_maintenance_task(&self) -> bool;
40
41 fn store_session(
42 &self,
43 session: CookieSession<S>,
44 ) -> Pin<Box<dyn Future<Output = Result<(), BoxDynError>> + Send + '_>>;
45
46 fn remove_session<'a>(
47 &'a self,
48 id: &'a SessionId,
49 ) -> Pin<Box<dyn Future<Output = Result<Option<CookieSession<S>>, BoxDynError>> + Send + 'a>>;
50
51 fn load_session<'a>(
52 &'a self,
53 id: &'a SessionId,
54 ) -> Pin<Box<dyn Future<Output = Result<Option<CookieSession<S>>, BoxDynError>> + Send + 'a>>;
55
56 fn remove_before(
57 &self,
58 deadline: u64,
59 ) -> Pin<Box<dyn Future<Output = Result<(), BoxDynError>> + Send + '_>>;
60}
61
62impl<T> DynStore<T::State> for T
63where
64 T: CookieStore,
65{
66 fn spawn_maintenance_task(&self) -> bool {
67 <T as CookieStore>::spawn_maintenance_task(self)
68 }
69
70 fn store_session(
71 &self,
72 session: CookieSession<T::State>,
73 ) -> Pin<Box<dyn Future<Output = Result<(), BoxDynError>> + Send + '_>> {
74 Box::pin(async move {
75 <T as CookieStore>::store_session(self, session)
76 .await
77 .map_err(|e| Box::new(e) as Box<dyn Error + Send>)
78 })
79 }
80
81 fn remove_session<'a>(
82 &'a self,
83 id: &'a SessionId,
84 ) -> Pin<
85 Box<dyn Future<Output = Result<Option<CookieSession<T::State>>, BoxDynError>> + Send + 'a>,
86 > {
87 Box::pin(async move {
88 <T as CookieStore>::remove_session(self, id)
89 .await
90 .map_err(|e| Box::new(e) as Box<dyn Error + Send>)
91 })
92 }
93
94 fn load_session<'a>(
95 &'a self,
96 id: &'a SessionId,
97 ) -> Pin<
98 Box<dyn Future<Output = Result<Option<CookieSession<T::State>>, BoxDynError>> + Send + 'a>,
99 > {
100 Box::pin(async move {
101 <T as CookieStore>::load_session(self, id)
102 .await
103 .map_err(|e| Box::new(e) as Box<dyn Error + Send>)
104 })
105 }
106
107 fn remove_before(
108 &self,
109 deadline: u64,
110 ) -> Pin<Box<dyn Future<Output = Result<(), BoxDynError>> + Send + '_>> {
111 Box::pin(async move {
112 <T as CookieStore>::remove_before(self, deadline)
113 .await
114 .map_err(|e| Box::new(e) as Box<dyn Error + Send>)
115 })
116 }
117}
118
119pub(crate) struct ErasedStore<S>(Arc<dyn DynStore<S>>);
120
121impl<S: 'static> ErasedStore<S> {
122 pub fn new(store: S) -> ErasedStore<S::State>
123 where
124 S: CookieStore,
125 {
126 ErasedStore(Arc::new(store))
127 }
128
129 pub fn spawn_maintenance_task(&self) -> bool {
130 self.0.spawn_maintenance_task()
131 }
132
133 pub async fn store_session(
134 &self,
135 session: CookieSession<S>,
136 ) -> Result<(), Box<dyn Error + Send + 'static>> {
137 self.0.store_session(session).await
138 }
139
140 pub async fn remove_session(
141 &self,
142 id: &SessionId,
143 ) -> Result<Option<CookieSession<S>>, BoxDynError> {
144 self.0.remove_session(id).await
145 }
146
147 pub async fn load_session(
148 &self,
149 id: &SessionId,
150 ) -> Result<Option<CookieSession<S>>, BoxDynError> {
151 self.0.load_session(id).await
152 }
153
154 pub async fn remove_before(&self, deadline: u64) -> Result<(), BoxDynError> {
155 self.0.remove_before(deadline).await
156 }
157}
158
159impl<S> Clone for ErasedStore<S> {
160 fn clone(&self) -> Self {
161 ErasedStore(self.0.clone())
162 }
163}