revolt_database/models/users/ops/
reference.rs

1use authifier::models::Session;
2use iso8601_timestamp::Timestamp;
3use revolt_result::Result;
4
5use crate::{FieldsUser, PartialUser, RelationshipStatus, User};
6use crate::{ReferenceDb, Relationship};
7
8use super::AbstractUsers;
9
10#[async_trait]
11impl AbstractUsers for ReferenceDb {
12    /// Insert a new user into the database
13    async fn insert_user(&self, user: &User) -> Result<()> {
14        let mut users = self.users.lock().await;
15        if users.contains_key(&user.id) {
16            Err(create_database_error!("insert", "user"))
17        } else {
18            users.insert(user.id.to_string(), user.clone());
19            Ok(())
20        }
21    }
22
23    /// Fetch a user from the database
24    async fn fetch_user(&self, id: &str) -> Result<User> {
25        let users = self.users.lock().await;
26        users
27            .get(id)
28            .cloned()
29            .ok_or_else(|| create_error!(NotFound))
30    }
31
32    /// Fetch a user from the database by their username
33    async fn fetch_user_by_username(&self, username: &str, discriminator: &str) -> Result<User> {
34        let users = self.users.lock().await;
35        let lowercase = username.to_lowercase();
36        users
37            .values()
38            .find(|user| {
39                user.username.to_lowercase() == lowercase && user.discriminator == discriminator
40            })
41            .cloned()
42            .ok_or_else(|| create_error!(NotFound))
43    }
44
45    /// Fetch a session from the database by token
46    async fn fetch_session_by_token(&self, _token: &str) -> Result<Session> {
47        todo!()
48    }
49
50    /// Fetch multiple users by their ids
51    async fn fetch_users<'a>(&self, ids: &'a [String]) -> Result<Vec<User>> {
52        let users = self.users.lock().await;
53        ids.iter()
54            .map(|id| {
55                users
56                    .get(id)
57                    .cloned()
58                    .ok_or_else(|| create_error!(NotFound))
59            })
60            .collect()
61    }
62
63    /// Fetch all discriminators in use for a username
64    async fn fetch_discriminators_in_use(&self, username: &str) -> Result<Vec<String>> {
65        let users = self.users.lock().await;
66        let lowercase = username.to_lowercase();
67        Ok(users
68            .values()
69            .filter(|user| user.username.to_lowercase() == lowercase)
70            .map(|user| &user.discriminator)
71            .cloned()
72            .collect())
73    }
74
75    /// Fetch ids of users that both users are friends with
76    async fn fetch_mutual_user_ids(&self, _user_a: &str, _user_b: &str) -> Result<Vec<String>> {
77        todo!()
78    }
79
80    /// Fetch ids of channels that both users are in
81    async fn fetch_mutual_channel_ids(&self, _user_a: &str, _user_b: &str) -> Result<Vec<String>> {
82        todo!()
83    }
84
85    /// Fetch ids of servers that both users share
86    async fn fetch_mutual_server_ids(&self, _user_a: &str, _user_b: &str) -> Result<Vec<String>> {
87        todo!()
88    }
89
90    /// Update a user by their id given some data
91    async fn update_user(
92        &self,
93        id: &str,
94        partial: &PartialUser,
95        remove: Vec<FieldsUser>,
96    ) -> Result<()> {
97        let mut users = self.users.lock().await;
98        if let Some(user) = users.get_mut(id) {
99            for field in remove {
100                #[allow(clippy::disallowed_methods)]
101                user.remove_field(&field);
102            }
103
104            user.apply_options(partial.clone());
105            Ok(())
106        } else {
107            Err(create_error!(NotFound))
108        }
109    }
110
111    /// Set relationship with another user
112    ///
113    /// This should use pull_relationship if relationship is None or User.
114    async fn set_relationship(
115        &self,
116        user_id: &str,
117        target_id: &str,
118        relationship: &RelationshipStatus,
119    ) -> Result<()> {
120        if let RelationshipStatus::User | RelationshipStatus::None = &relationship {
121            self.pull_relationship(user_id, target_id).await
122        } else {
123            let mut users = self.users.lock().await;
124            let user = users
125                .get_mut(user_id)
126                .ok_or_else(|| create_error!(NotFound))?;
127
128            let relation = Relationship {
129                id: target_id.to_string(),
130                status: relationship.clone(),
131            };
132
133            if let Some(relations) = &mut user.relations {
134                relations.retain(|relation| relation.id != target_id);
135                relations.push(relation);
136            } else {
137                user.relations = Some(vec![relation]);
138            }
139
140            Ok(())
141        }
142    }
143
144    /// Remove relationship with another user
145    async fn pull_relationship(&self, user_id: &str, target_id: &str) -> Result<()> {
146        let mut users = self.users.lock().await;
147        let user = users
148            .get_mut(user_id)
149            .ok_or_else(|| create_error!(NotFound))?;
150
151        if let Some(relations) = &mut user.relations {
152            relations.retain(|relation| relation.id != target_id);
153        }
154
155        Ok(())
156    }
157
158    /// Delete a user by their id
159    async fn delete_user(&self, id: &str) -> Result<()> {
160        let mut users = self.users.lock().await;
161        if users.remove(id).is_some() {
162            Ok(())
163        } else {
164            Err(create_error!(NotFound))
165        }
166    }
167
168    /// Remove push subscription for a session by session id (TODO: remove)
169    async fn remove_push_subscription_by_session_id(&self, _session_id: &str) -> Result<()> {
170        todo!()
171    }
172
173    async fn update_session_last_seen(&self, _session_id: &str, _when: Timestamp) -> Result<()> {
174        todo!()
175    }
176}