mas_storage/
app_session.rs1use async_trait::async_trait;
11use chrono::{DateTime, Utc};
12use mas_data_model::{BrowserSession, Clock, CompatSession, Device, Session, User};
13
14use crate::{Page, Pagination, repository_impl};
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum AppSessionState {
19 Active,
21 Finished,
23}
24
25impl AppSessionState {
26 #[must_use]
28 pub fn is_active(self) -> bool {
29 matches!(self, Self::Active)
30 }
31
32 #[must_use]
34 pub fn is_finished(self) -> bool {
35 matches!(self, Self::Finished)
36 }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
41pub enum AppSession {
42 Compat(Box<CompatSession>),
44
45 OAuth2(Box<Session>),
47}
48
49#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
51pub struct AppSessionFilter<'a> {
52 user: Option<&'a User>,
53 browser_session: Option<&'a BrowserSession>,
54 state: Option<AppSessionState>,
55 device_id: Option<&'a Device>,
56 last_active_before: Option<DateTime<Utc>>,
57 last_active_after: Option<DateTime<Utc>>,
58 created_before: Option<DateTime<Utc>>,
59 created_after: Option<DateTime<Utc>>,
60}
61
62impl<'a> AppSessionFilter<'a> {
63 #[must_use]
65 pub fn new() -> Self {
66 Self::default()
67 }
68
69 #[must_use]
71 pub fn for_user(mut self, user: &'a User) -> Self {
72 self.user = Some(user);
73 self
74 }
75
76 #[must_use]
78 pub fn user(&self) -> Option<&'a User> {
79 self.user
80 }
81
82 #[must_use]
84 pub fn for_browser_session(mut self, browser_session: &'a BrowserSession) -> Self {
85 self.browser_session = Some(browser_session);
86 self
87 }
88
89 #[must_use]
91 pub fn browser_session(&self) -> Option<&'a BrowserSession> {
92 self.browser_session
93 }
94
95 #[must_use]
97 pub fn for_device(mut self, device_id: &'a Device) -> Self {
98 self.device_id = Some(device_id);
99 self
100 }
101
102 #[must_use]
104 pub fn device(&self) -> Option<&'a Device> {
105 self.device_id
106 }
107
108 #[must_use]
110 pub fn with_last_active_before(mut self, last_active_before: DateTime<Utc>) -> Self {
111 self.last_active_before = Some(last_active_before);
112 self
113 }
114
115 #[must_use]
117 pub fn with_last_active_after(mut self, last_active_after: DateTime<Utc>) -> Self {
118 self.last_active_after = Some(last_active_after);
119 self
120 }
121
122 #[must_use]
126 pub fn last_active_before(&self) -> Option<DateTime<Utc>> {
127 self.last_active_before
128 }
129
130 #[must_use]
134 pub fn last_active_after(&self) -> Option<DateTime<Utc>> {
135 self.last_active_after
136 }
137
138 #[must_use]
140 pub fn with_created_before(mut self, created_before: DateTime<Utc>) -> Self {
141 self.created_before = Some(created_before);
142 self
143 }
144
145 #[must_use]
147 pub fn with_created_after(mut self, created_after: DateTime<Utc>) -> Self {
148 self.created_after = Some(created_after);
149 self
150 }
151
152 #[must_use]
156 pub fn created_before(&self) -> Option<DateTime<Utc>> {
157 self.created_before
158 }
159
160 #[must_use]
164 pub fn created_after(&self) -> Option<DateTime<Utc>> {
165 self.created_after
166 }
167
168 #[must_use]
170 pub fn active_only(mut self) -> Self {
171 self.state = Some(AppSessionState::Active);
172 self
173 }
174
175 #[must_use]
177 pub fn finished_only(mut self) -> Self {
178 self.state = Some(AppSessionState::Finished);
179 self
180 }
181
182 #[must_use]
184 pub fn state(&self) -> Option<AppSessionState> {
185 self.state
186 }
187}
188
189#[async_trait]
192pub trait AppSessionRepository: Send + Sync {
193 type Error;
195
196 async fn list(
209 &mut self,
210 filter: AppSessionFilter<'_>,
211 pagination: Pagination,
212 ) -> Result<Page<AppSession>, Self::Error>;
213
214 async fn count(&mut self, filter: AppSessionFilter<'_>) -> Result<usize, Self::Error>;
224
225 async fn finish_sessions_to_replace_device(
235 &mut self,
236 clock: &dyn Clock,
237 user: &User,
238 device: &Device,
239 ) -> Result<bool, Self::Error>;
240}
241
242repository_impl!(AppSessionRepository:
243 async fn list(
244 &mut self,
245 filter: AppSessionFilter<'_>,
246 pagination: Pagination,
247 ) -> Result<Page<AppSession>, Self::Error>;
248
249 async fn count(&mut self, filter: AppSessionFilter<'_>) -> Result<usize, Self::Error>;
250
251 async fn finish_sessions_to_replace_device(
252 &mut self,
253 clock: &dyn Clock,
254 user: &User,
255 device: &Device,
256 ) -> Result<bool, Self::Error>;
257);