mas_storage/
app_session.rs1use async_trait::async_trait;
10use chrono::{DateTime, Utc};
11use mas_data_model::{BrowserSession, CompatSession, Device, Session, User};
12
13use crate::{Clock, Page, Pagination, repository_impl};
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum AppSessionState {
18    Active,
20    Finished,
22}
23
24impl AppSessionState {
25    #[must_use]
27    pub fn is_active(self) -> bool {
28        matches!(self, Self::Active)
29    }
30
31    #[must_use]
33    pub fn is_finished(self) -> bool {
34        matches!(self, Self::Finished)
35    }
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum AppSession {
41    Compat(Box<CompatSession>),
43
44    OAuth2(Box<Session>),
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
50pub struct AppSessionFilter<'a> {
51    user: Option<&'a User>,
52    browser_session: Option<&'a BrowserSession>,
53    state: Option<AppSessionState>,
54    device_id: Option<&'a Device>,
55    last_active_before: Option<DateTime<Utc>>,
56    last_active_after: Option<DateTime<Utc>>,
57}
58
59impl<'a> AppSessionFilter<'a> {
60    #[must_use]
62    pub fn new() -> Self {
63        Self::default()
64    }
65
66    #[must_use]
68    pub fn for_user(mut self, user: &'a User) -> Self {
69        self.user = Some(user);
70        self
71    }
72
73    #[must_use]
75    pub fn user(&self) -> Option<&'a User> {
76        self.user
77    }
78
79    #[must_use]
81    pub fn for_browser_session(mut self, browser_session: &'a BrowserSession) -> Self {
82        self.browser_session = Some(browser_session);
83        self
84    }
85
86    #[must_use]
88    pub fn browser_session(&self) -> Option<&'a BrowserSession> {
89        self.browser_session
90    }
91
92    #[must_use]
94    pub fn for_device(mut self, device_id: &'a Device) -> Self {
95        self.device_id = Some(device_id);
96        self
97    }
98
99    #[must_use]
101    pub fn device(&self) -> Option<&'a Device> {
102        self.device_id
103    }
104
105    #[must_use]
107    pub fn with_last_active_before(mut self, last_active_before: DateTime<Utc>) -> Self {
108        self.last_active_before = Some(last_active_before);
109        self
110    }
111
112    #[must_use]
114    pub fn with_last_active_after(mut self, last_active_after: DateTime<Utc>) -> Self {
115        self.last_active_after = Some(last_active_after);
116        self
117    }
118
119    #[must_use]
123    pub fn last_active_before(&self) -> Option<DateTime<Utc>> {
124        self.last_active_before
125    }
126
127    #[must_use]
131    pub fn last_active_after(&self) -> Option<DateTime<Utc>> {
132        self.last_active_after
133    }
134
135    #[must_use]
137    pub fn active_only(mut self) -> Self {
138        self.state = Some(AppSessionState::Active);
139        self
140    }
141
142    #[must_use]
144    pub fn finished_only(mut self) -> Self {
145        self.state = Some(AppSessionState::Finished);
146        self
147    }
148
149    #[must_use]
151    pub fn state(&self) -> Option<AppSessionState> {
152        self.state
153    }
154}
155
156#[async_trait]
159pub trait AppSessionRepository: Send + Sync {
160    type Error;
162
163    async fn list(
176        &mut self,
177        filter: AppSessionFilter<'_>,
178        pagination: Pagination,
179    ) -> Result<Page<AppSession>, Self::Error>;
180
181    async fn count(&mut self, filter: AppSessionFilter<'_>) -> Result<usize, Self::Error>;
191
192    async fn finish_sessions_to_replace_device(
200        &mut self,
201        clock: &dyn Clock,
202        user: &User,
203        device: &Device,
204    ) -> Result<(), Self::Error>;
205}
206
207repository_impl!(AppSessionRepository:
208    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>;
215
216    async fn finish_sessions_to_replace_device(
217        &mut self,
218        clock: &dyn Clock,
219        user: &User,
220        device: &Device,
221    ) -> Result<(), Self::Error>;
222);