alibi_core/store/contracts/
session.rs1use super::*;
2#[async_trait]
3pub trait SessionStore<S: AuthSchema>: Send + Sync {
4 async fn prepare_secondary_session_creation(
7 &self,
8 _input: CreateSession,
9 _persist: bool,
10 ) -> AuthResult<S::Session> {
11 Err(AuthError::NotImplemented(
12 "Secondary session creation is unsupported".into(),
13 ))
14 }
15 async fn complete_secondary_session_creation(&self, _session: &S::Session) -> AuthResult<()> {
17 Err(AuthError::NotImplemented(
18 "Secondary session creation is unsupported".into(),
19 ))
20 }
21 async fn prepare_secondary_session_update(
23 &self,
24 _session: S::Session,
25 _expires_at: Option<chrono::DateTime<chrono::Utc>>,
26 _fields: crate::field_policy::FieldValues,
27 ) -> AuthResult<Option<(S::Session, crate::field_policy::FieldValues)>> {
28 Err(AuthError::NotImplemented(
29 "Secondary session updates are unsupported".into(),
30 ))
31 }
32 async fn complete_secondary_session_update(
34 &self,
35 _session: S::Session,
36 _expires_at: Option<chrono::DateTime<chrono::Utc>>,
37 _fields: crate::field_policy::FieldValues,
38 _persist: bool,
39 ) -> AuthResult<Option<S::Session>> {
40 Err(AuthError::NotImplemented(
41 "Secondary session updates are unsupported".into(),
42 ))
43 }
44 async fn end_session_preserving(&self, _token: &str) -> AuthResult<()> {
46 Err(AuthError::NotImplemented(
47 "Preserving ended session rows is unsupported".into(),
48 ))
49 }
50 async fn end_user_sessions_preserving(&self, _user_id: &str) -> AuthResult<()> {
52 Err(AuthError::NotImplemented(
53 "Preserving ended session rows is unsupported".into(),
54 ))
55 }
56 async fn get_session_user(&self, _token: &str) -> AuthResult<Option<S::User>> {
59 Ok(None)
60 }
61
62 async fn get_session_user_record(
64 &self,
65 token: &str,
66 ) -> AuthResult<Option<crate::AdapterRecord<S::User>>> {
67 self.get_session_user(token)
68 .await?
69 .map(crate::AdapterRecord::physical)
70 .transpose()
71 }
72
73 async fn create_session_record(
76 &self,
77 create_session: CreateSession,
78 ) -> AuthResult<crate::AdapterRecord<S::Session>> {
79 crate::AdapterRecord::physical(self.create_session(create_session).await?)
80 }
81
82 async fn get_session_record(
85 &self,
86 token: &str,
87 ) -> AuthResult<Option<crate::AdapterRecord<S::Session>>> {
88 self.get_session(token)
89 .await?
90 .map(crate::AdapterRecord::physical)
91 .transpose()
92 }
93
94 async fn get_sessions_by_tokens_record(
97 &self,
98 tokens: &[String],
99 ) -> AuthResult<Vec<crate::AdapterRecord<S::Session>>> {
100 self.get_sessions_by_tokens(tokens)
101 .await?
102 .into_iter()
103 .map(crate::AdapterRecord::physical)
104 .collect()
105 }
106
107 async fn get_user_sessions_record(
110 &self,
111 user_id: &str,
112 ) -> AuthResult<Vec<crate::AdapterRecord<S::Session>>> {
113 self.get_user_sessions(user_id)
114 .await?
115 .into_iter()
116 .map(crate::AdapterRecord::physical)
117 .collect()
118 }
119
120 async fn get_active_user_sessions_record(
123 &self,
124 user_id: &str,
125 ) -> AuthResult<Vec<crate::AdapterRecord<S::Session>>> {
126 use crate::AuthSession;
127 let now = chrono::Utc::now();
128 self.get_user_sessions(user_id)
129 .await?
130 .into_iter()
131 .filter(|session| session.expires_at() > now && session.active())
132 .map(crate::AdapterRecord::physical)
133 .collect()
134 }
135
136 async fn refresh_session_record(
139 &self,
140 token: &str,
141 expires_at: chrono::DateTime<chrono::Utc>,
142 ) -> AuthResult<Option<crate::AdapterRecord<S::Session>>> {
143 self.refresh_session(token, expires_at)
144 .await?
145 .map(crate::AdapterRecord::physical)
146 .transpose()
147 }
148
149 async fn update_session_fields_record(
152 &self,
153 token: &str,
154 fields: crate::field_policy::FieldValues,
155 ) -> AuthResult<Option<crate::AdapterRecord<S::Session>>> {
156 self.update_session_fields(token, fields)
157 .await?
158 .map(crate::AdapterRecord::physical)
159 .transpose()
160 }
161
162 async fn update_session_active_organization_record(
165 &self,
166 token: &str,
167 organization_id: Option<&str>,
168 ) -> AuthResult<crate::AdapterRecord<S::Session>> {
169 crate::AdapterRecord::physical(
170 self.update_session_active_organization(token, organization_id)
171 .await?,
172 )
173 }
174
175 async fn update_session_active_team_record(
178 &self,
179 token: &str,
180 team_id: Option<&str>,
181 ) -> AuthResult<crate::AdapterRecord<S::Session>> {
182 crate::AdapterRecord::physical(self.update_session_active_team(token, team_id).await?)
183 }
184
185 async fn update_session_fields(
187 &self,
188 _token: &str,
189 _fields: crate::field_policy::FieldValues,
190 ) -> AuthResult<Option<S::Session>> {
191 Err(AuthError::internal(
192 "the store does not support session field updates",
193 ))
194 }
195
196 async fn create_session(&self, create_session: CreateSession) -> AuthResult<S::Session>;
197
198 async fn get_session(&self, token: &str) -> AuthResult<Option<S::Session>>;
199
200 async fn get_sessions_by_tokens(&self, tokens: &[String]) -> AuthResult<Vec<S::Session>> {
203 let mut sessions = Vec::new();
204 for token in BTreeSet::from_iter(tokens) {
205 if let Some(session) = self.get_session(token).await? {
206 sessions.push(session);
207 }
208 }
209 Ok(sessions)
210 }
211
212 async fn get_user_sessions(&self, user_id: &str) -> AuthResult<Vec<S::Session>>;
213
214 async fn update_session_expiry(
215 &self,
216 token: &str,
217 expires_at: chrono::DateTime<chrono::Utc>,
218 ) -> AuthResult<()>;
219
220 async fn refresh_session_with_fields(
225 &self,
226 token: &str,
227 expires_at: chrono::DateTime<chrono::Utc>,
228 mut fields: crate::field_policy::FieldValues,
229 ) -> AuthResult<Option<S::Session>> {
230 fields.apply_adapter_transforms_async().await?;
231 if !fields.is_empty() {
232 return Err(AuthError::NotImplemented(
233 "The store does not support refresh field updates".into(),
234 ));
235 }
236 self.refresh_session(token, expires_at).await
237 }
238
239 async fn refresh_session(
242 &self,
243 token: &str,
244 expires_at: chrono::DateTime<chrono::Utc>,
245 ) -> AuthResult<Option<S::Session>> {
246 match self.update_session_expiry(token, expires_at).await {
247 Ok(()) => self.get_session(token).await,
248 Err(AuthError::SessionNotFound) => Ok(None),
249 Err(error) => Err(error),
250 }
251 }
252
253 async fn delete_session(&self, token: &str) -> AuthResult<()>;
254
255 async fn delete_user_sessions(&self, user_id: &str) -> AuthResult<()>;
256
257 async fn delete_expired_sessions(&self) -> AuthResult<usize>;
258
259 async fn update_session_active_organization(
260 &self,
261 token: &str,
262 organization_id: Option<&str>,
263 ) -> AuthResult<S::Session>;
264
265 async fn update_session_active_team(
266 &self,
267 _token: &str,
268 _team_id: Option<&str>,
269 ) -> AuthResult<S::Session> {
270 Err(AuthError::internal(
271 "active-team updates are not supported by this store",
272 ))
273 }
274}