revolt_database/models/accounts/ops/
mongodb.rs1use crate::{AbstractAccounts, Account, MongoDb};
2use bson::{to_bson, to_document};
3use iso8601_timestamp::Timestamp;
4use mongodb::options::{Collation, CollationStrength, FindOneOptions, UpdateOptions};
5use revolt_result::Result;
6
7const COL: &str = "accounts";
8
9#[async_trait]
10impl AbstractAccounts for MongoDb {
11 async fn fetch_account(&self, id: &str) -> Result<Account> {
13 query!(self, find_one_by_id, COL, id)?.ok_or_else(|| create_error!(UnknownUser))
14 }
15
16 async fn fetch_account_by_normalised_email(
18 &self,
19 normalised_email: &str,
20 ) -> Result<Option<Account>> {
21 query!(
22 self,
23 find_one_with_options,
24 COL,
25 doc! {
26 "email_normalised": normalised_email
27 },
28 FindOneOptions::builder()
29 .collation(
30 Collation::builder()
31 .locale("en")
32 .strength(CollationStrength::Secondary)
33 .build(),
34 )
35 .build()
36 )
37 }
38
39 async fn fetch_account_with_email_verification(&self, token: &str) -> Result<Account> {
41 query!(
42 self,
43 find_one,
44 COL,
45 doc! {
46 "verification.token": token,
47 "verification.expiry": {
48 "$gte": to_bson(&Timestamp::now_utc()).unwrap()
49 }
50 }
51 )?
52 .ok_or_else(|| create_error!(InvalidToken))
53 }
54
55 async fn fetch_account_with_password_reset(&self, token: &str) -> Result<Account> {
57 query!(
58 self,
59 find_one,
60 COL,
61 doc! {
62 "password_reset.token": token,
63 "password_reset.expiry": {
64 "$gte": to_bson(&Timestamp::now_utc()).unwrap()
65 }
66 }
67 )?
68 .ok_or_else(|| create_error!(InvalidToken))
69 }
70
71 async fn fetch_account_with_deletion_token(&self, token: &str) -> Result<Account> {
73 query!(
74 self,
75 find_one,
76 COL,
77 doc! {
78 "deletion.token": token,
79 "deletion.expiry": {
80 "$gte": to_bson(&Timestamp::now_utc()).unwrap()
81 }
82 }
83 )?
84 .ok_or_else(|| create_error!(InvalidToken))
85 }
86
87 async fn fetch_accounts_due_for_deletion(&self) -> Result<Vec<Account>> {
89 query!(
90 self,
91 find,
92 COL,
93 doc! {
94 "deletion.status": "Scheduled",
95 "deletion.after": {
96 "$lte": to_bson(&Timestamp::now_utc()).unwrap()
97 }
98 }
99 )
100 }
101
102 async fn save_account(&self, account: &Account) -> Result<()> {
104 self.col::<Account>(COL)
105 .update_one(
106 doc! {
107 "_id": &account.id
108 },
109 doc! {
110 "$set": to_document(account).map_err(|_| create_database_error!("to_document", COL))?
111 },
112 )
113 .with_options(UpdateOptions::builder().upsert(true).build())
114 .await
115 .map_err(|_| create_database_error!("find_one", COL))
116 .map(|_| ())
117 }
118}