1use super::ConnectionExt;
2use crate::schema::pending_remove::dsl;
3use crate::{DbConnection, impl_fetch, impl_store_or_ignore, schema::pending_remove};
4use diesel::dsl::exists;
5use diesel::prelude::*;
6use diesel::select;
7use serde::{Deserialize, Serialize};
8
9#[derive(
10 Debug,
11 Clone,
12 Serialize,
13 Deserialize,
14 Insertable,
15 Identifiable,
16 Queryable,
17 Eq,
18 PartialEq,
19 QueryableByName,
20)]
21#[diesel(table_name = pending_remove)]
22#[diesel(primary_key(inbox_id, group_id))]
23pub struct PendingRemove {
24 pub group_id: Vec<u8>,
26 pub inbox_id: String,
28 pub message_id: Vec<u8>,
30}
31
32impl_store_or_ignore!(PendingRemove, pending_remove);
33impl_fetch!(PendingRemove, pending_remove);
34pub trait QueryPendingRemove {
35 fn get_pending_remove_users(
36 &self,
37 group_id: &[u8],
38 ) -> Result<Vec<String>, crate::ConnectionError>;
39 fn get_user_pending_remove_status(
40 &self,
41 group_id: &[u8],
42 inbox_id: &str,
43 ) -> Result<bool, crate::ConnectionError>;
44 fn delete_pending_remove_users(
45 &self,
46 group_id: &[u8],
47 inbox_ids: Vec<String>,
48 ) -> Result<usize, crate::ConnectionError>;
49}
50impl<T> QueryPendingRemove for &T
51where
52 T: QueryPendingRemove,
53{
54 fn get_pending_remove_users(
55 &self,
56 group_id: &[u8],
57 ) -> Result<Vec<String>, crate::ConnectionError> {
58 (**self).get_pending_remove_users(group_id)
59 }
60 fn get_user_pending_remove_status(
61 &self,
62 group_id: &[u8],
63 inbox_id: &str,
64 ) -> Result<bool, crate::ConnectionError> {
65 (**self).get_user_pending_remove_status(group_id, inbox_id)
66 }
67 fn delete_pending_remove_users(
68 &self,
69 group_id: &[u8],
70 inbox_ids: Vec<String>,
71 ) -> Result<usize, crate::ConnectionError> {
72 (**self).delete_pending_remove_users(group_id, inbox_ids)
73 }
74}
75impl<C: ConnectionExt> QueryPendingRemove for DbConnection<C> {
76 fn get_pending_remove_users(
77 &self,
78 group_id: &[u8],
79 ) -> Result<Vec<String>, crate::ConnectionError> {
80 let result = self.raw_query_read(|conn| {
81 dsl::pending_remove
82 .filter(dsl::group_id.eq(group_id))
83 .select(dsl::inbox_id)
84 .load::<String>(conn)
85 })?;
86
87 Ok(result)
88 }
89
90 fn get_user_pending_remove_status(
91 &self,
92 group_id: &[u8],
93 inbox_id: &str,
94 ) -> Result<bool, crate::ConnectionError> {
95 let result: bool = self.raw_query_read(|conn| {
96 select(exists(dsl::pending_remove.filter(
97 dsl::group_id.eq(group_id).and(dsl::inbox_id.eq(inbox_id)),
98 )))
99 .get_result::<bool>(conn)
100 })?;
101 Ok(result)
102 }
103
104 fn delete_pending_remove_users(
105 &self,
106 group_id: &[u8],
107 inbox_ids: Vec<String>,
108 ) -> Result<usize, crate::ConnectionError> {
109 let result = self.raw_query_write(|conn| {
110 diesel::delete(
111 dsl::pending_remove.filter(
112 dsl::inbox_id
113 .eq_any(inbox_ids)
114 .and(dsl::group_id.eq(group_id)),
115 ),
116 )
117 .execute(conn)
118 })?;
119 Ok(result)
120 }
121}
122#[cfg(test)]
123mod tests {
124 use crate::encrypted_store::pending_remove::{PendingRemove, QueryPendingRemove};
125 use crate::{StoreOrIgnore, with_connection};
126
127 #[xmtp_common::test(unwrap_try = true)]
128 fn test_add_pending_remove() {
129 with_connection(|conn| {
130 PendingRemove {
132 inbox_id: "123".to_string(),
133 group_id: vec![1, 2, 3],
134 message_id: vec![1, 2, 3],
135 }
136 .store_or_ignore(conn)?;
137 let users = conn.get_pending_remove_users(&[1, 2, 3]).unwrap();
138 assert_eq!(users.len(), 1);
139 let users = conn.get_pending_remove_users(&[1]).unwrap();
140 assert_eq!(users.len(), 0);
141 })
142 }
143
144 #[xmtp_common::test(unwrap_try = true)]
145 fn test_delete_pending_remove_user() {
146 with_connection(|conn| {
147 PendingRemove {
149 inbox_id: "1".to_string(),
150 group_id: vec![1, 2, 3],
151 message_id: vec![1, 2, 3],
152 }
153 .store_or_ignore(conn)?;
154 PendingRemove {
155 inbox_id: "2".to_string(),
156 group_id: vec![1, 2, 3],
157 message_id: vec![1, 2, 3],
158 }
159 .store_or_ignore(conn)?;
160 PendingRemove {
161 inbox_id: "3".to_string(),
162 group_id: vec![1, 2, 3],
163 message_id: vec![1, 2, 3],
164 }
165 .store_or_ignore(conn)?;
166 let users = conn.get_pending_remove_users(&[1, 2, 3]).unwrap();
167 assert_eq!(users.len(), 3);
168 let deleted_users = conn
169 .delete_pending_remove_users(&[1, 2, 3], vec!["1".to_string(), "2".to_string()])
170 .unwrap();
171 assert_eq!(deleted_users, 2usize);
172 let users = conn.get_pending_remove_users(&[1, 2, 3]).unwrap();
173 assert_eq!(users.len(), 1);
174 let deleted_users = conn
175 .delete_pending_remove_users(&[1], vec!["3".to_string()])
176 .unwrap();
177 assert_eq!(deleted_users, 0usize);
178 })
179 }
180}