Skip to main content

revolt_database/models/sessions/ops/
mongodb.rs

1use crate::{AbstractSessions, MongoDb, Session};
2use bson::{to_bson, to_document};
3use iso8601_timestamp::Timestamp;
4use mongodb::options::UpdateOptions;
5use revolt_result::Result;
6
7const COL: &str = "sessions";
8
9#[async_trait]
10impl AbstractSessions for MongoDb {
11    /// Find session by id
12    async fn fetch_session(&self, id: &str) -> Result<Session> {
13        query!(self, find_one_by_id, COL, id)?.ok_or_else(|| create_error!(UnknownUser))
14    }
15
16    /// Find sessions by user id
17    async fn fetch_sessions(&self, user_id: &str) -> Result<Vec<Session>> {
18        query!(
19            self,
20            find,
21            COL,
22            doc! {
23                "user_id": user_id
24            }
25        )
26    }
27
28    /// Find sessions by user ids
29    async fn fetch_sessions_with_subscription(&self, user_ids: &[String]) -> Result<Vec<Session>> {
30        query!(
31            self,
32            find,
33            COL,
34            doc! {
35                "user_id": {
36                    "$in": user_ids
37                },
38                "subscription": {
39                    "$exists": true
40                }
41            }
42        )
43    }
44
45    /// Fetch a session from the database by token
46    async fn fetch_session_by_token(&self, token: &str) -> Result<Session> {
47        query!(
48            self,
49            find_one,
50            COL,
51            doc! {
52                "token": token
53            }
54        )?
55        .ok_or_else(|| create_error!(InvalidSession))
56    }
57
58    /// Save session
59    async fn save_session(&self, session: &Session) -> Result<()> {
60        self.col::<Session>(COL)
61            .update_one(
62                doc! {
63                    "_id": &session.id
64                },
65                doc! {
66                    "$set": to_document(session).map_err(|_| create_database_error!("to_document", COL))?,
67                },
68            )
69            .with_options(UpdateOptions::builder().upsert(true).build())
70            .await
71            .map_err(|_| create_database_error!("upsert_one", COL))
72            .map(|_| ())
73    }
74
75    /// Delete session
76    async fn delete_session(&self, id: &str) -> Result<()> {
77        self.col::<Session>(COL)
78            .delete_one(doc! {
79                "_id": id
80            })
81            .await
82            .map_err(|_| create_database_error!("delete_one", COL))
83            .map(|_| ())
84    }
85
86    /// Delete session
87    async fn delete_all_sessions(&self, user_id: &str, ignore: Option<String>) -> Result<()> {
88        let mut query = doc! {
89            "user_id": user_id
90        };
91
92        if let Some(id) = ignore {
93            query.insert(
94                "_id",
95                doc! {
96                    "$ne": id
97                },
98            );
99        }
100
101        self.col::<Session>(COL)
102            .delete_many(query)
103            .await
104            .map_err(|_| create_database_error!("delete_one", COL))
105            .map(|_| ())
106    }
107
108    /// Remove push subscription for a session by session id
109    async fn remove_push_subscription_by_session_id(&self, session_id: &str) -> Result<()> {
110        self.col::<Session>(COL)
111            .update_one(
112                doc! {
113                    "_id": session_id
114                },
115                doc! {
116                    "$unset": {
117                        "subscription": 1
118                    }
119                },
120            )
121            .await
122            .map(|_| ())
123            .map_err(|_| create_database_error!("update_one", COL))
124    }
125
126    async fn update_session_last_seen(&self, session_id: &str, when: Timestamp) -> Result<()> {
127        self.col::<Session>(COL)
128            .update_one(
129                doc! {
130                    "_id": session_id
131                },
132                doc! {
133                    "$set": {
134                        "last_seen": to_bson(&when).unwrap()
135                    }
136                },
137            )
138            .await
139            .map(|_| ())
140            .map_err(|_| create_database_error!("update_one", COL))
141    }
142}