Skip to main content

revolt_database/models/accounts/ops/
reference.rs

1use crate::{AbstractAccounts, Account, DeletionInfo, EmailVerification, ReferenceDb};
2use iso8601_timestamp::Timestamp;
3use revolt_result::Result;
4
5#[async_trait]
6impl AbstractAccounts for ReferenceDb {
7    /// Find account by id
8    async fn fetch_account(&self, id: &str) -> Result<Account> {
9        let accounts = self.accounts.lock().await;
10        accounts
11            .get(id)
12            .cloned()
13            .ok_or_else(|| create_error!(UnknownUser))
14    }
15
16    /// Find account by normalised email
17    async fn fetch_account_by_normalised_email(
18        &self,
19        normalised_email: &str,
20    ) -> Result<Option<Account>> {
21        let accounts = self.accounts.lock().await;
22        Ok(accounts
23            .values()
24            .find(|account| account.email_normalised == normalised_email)
25            .cloned())
26    }
27
28    /// Find account with active pending email verification
29    async fn fetch_account_with_email_verification(&self, token_to_match: &str) -> Result<Account> {
30        let accounts = self.accounts.lock().await;
31        accounts
32            .values()
33            .find(|account| match &account.verification {
34                EmailVerification::Pending { token, .. }
35                | EmailVerification::Moving { token, .. } => token == token_to_match,
36                _ => false,
37            })
38            .cloned()
39            .ok_or_else(|| create_error!(InvalidToken))
40    }
41
42    /// Find account with active password reset
43    async fn fetch_account_with_password_reset(&self, token: &str) -> Result<Account> {
44        let accounts = self.accounts.lock().await;
45        accounts
46            .values()
47            .find(|account| {
48                if let Some(reset) = &account.password_reset {
49                    reset.token == token
50                } else {
51                    false
52                }
53            })
54            .cloned()
55            .ok_or_else(|| create_error!(InvalidToken))
56    }
57
58    /// Find account with active deletion token
59    async fn fetch_account_with_deletion_token(&self, token_to_match: &str) -> Result<Account> {
60        let accounts = self.accounts.lock().await;
61        accounts
62            .values()
63            .find(|account| {
64                if let Some(DeletionInfo::WaitingForVerification { token, .. }) = &account.deletion
65                {
66                    token == token_to_match
67                } else {
68                    false
69                }
70            })
71            .cloned()
72            .ok_or_else(|| create_error!(InvalidToken))
73    }
74
75    /// Find accounts which are due to be deleted
76    async fn fetch_accounts_due_for_deletion(&self) -> Result<Vec<Account>> {
77        let now = Timestamp::now_utc();
78        let accounts = self.accounts.lock().await;
79
80        Ok(accounts
81            .values()
82            .filter(|account| {
83                if let Some(DeletionInfo::Scheduled { after }) = &account.deletion {
84                    after <= &now
85                } else {
86                    false
87                }
88            })
89            .cloned()
90            .collect())
91    }
92
93    // Save account
94    async fn save_account(&self, account: &Account) -> Result<()> {
95        let mut accounts = self.accounts.lock().await;
96        accounts.insert(account.id.to_string(), account.clone());
97        Ok(())
98    }
99}