1use oiseau::{PostgresRow, cache::Cache, execute, get, params, query_row, query_rows};
2use crate::{
3 DataManager, auto_method,
4 model::{
5 groups::{GroupRole, GroupMembership},
6 id::Id,
7 Error, Result,
8 },
9};
10
11impl DataManager {
12 pub(crate) fn get_group_membership_from_row(x: &PostgresRow) -> GroupMembership {
14 GroupMembership {
15 id: Id::deserialize(&get!(x->0(String))),
16 created: get!(x->1(i64)) as u128,
17 owner: Id::deserialize(&get!(x->2(String))),
18 group: Id::deserialize(&get!(x->3(String))),
19 role: serde_json::from_str(&get!(x->4(String))).unwrap(),
20 }
21 }
22
23 auto_method!(get_group_membership_by_id()@get_group_membership_from_row -> "SELECT * FROM group_memberships WHERE id = $1" --name="membership" --returns=GroupMembership --cache-key-tmpl="juic.group_membership:{}");
24
25 pub async fn get_group_membership_by_owner_group(
27 &self,
28 owner: &Id,
29 group: &Id,
30 ) -> Result<GroupMembership> {
31 let conn = match self.0.connect().await {
32 Ok(c) => c,
33 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
34 };
35
36 let res = query_row!(
37 &conn,
38 "SELECT * FROM group_memberships WHERE owner = $1 AND group_id = $2",
39 &[&owner.printable(), &group.printable()],
40 |x| { Ok(Self::get_group_membership_from_row(x)) }
41 );
42
43 if res.is_err() {
44 return Err(Error::GeneralNotFound("membership".to_string()));
45 }
46
47 Ok(res.unwrap())
48 }
49
50 pub async fn get_group_memberships_by_owner(
57 &self,
58 id: &Id,
59 batch: usize,
60 page: usize,
61 ) -> Result<Vec<GroupMembership>> {
62 let conn = match self.0.connect().await {
63 Ok(c) => c,
64 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
65 };
66
67 let res = query_rows!(
68 &conn,
69 "SELECT * FROM group_memberships WHERE owner = $1 AND role != '\"Banned\"' ORDER BY created DESC LIMIT $2 OFFSET $3",
70 &[&id.printable(), &(batch as i64), &((page * batch) as i64)],
71 |x| { Self::get_group_membership_from_row(x) }
72 );
73
74 if res.is_err() {
75 return Err(Error::GeneralNotFound("group membership".to_string()));
76 }
77
78 Ok(res.unwrap())
79 }
80
81 pub async fn get_group_memberships_group_by_owner_all(&self, id: &Id) -> Result<Vec<Id>> {
86 let conn = match self.0.connect().await {
87 Ok(c) => c,
88 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
89 };
90
91 let res = query_rows!(
92 &conn,
93 "SELECT group_id FROM group_memberships WHERE owner = $1 AND role != '\"Banned\"'",
94 &[&id.printable()],
95 |x| { Id::deserialize(&get!(x->0(String))) }
96 );
97
98 if res.is_err() {
99 return Err(Error::GeneralNotFound("group membership".to_string()));
100 }
101
102 Ok(res.unwrap())
103 }
104
105 pub async fn get_group_memberships_by_group_role(
107 &self,
108 group: &Id,
109 role: &GroupRole,
110 batch: usize,
111 page: usize,
112 ) -> Result<Vec<GroupMembership>> {
113 let conn = match self.0.connect().await {
114 Ok(c) => c,
115 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
116 };
117
118 let res = query_rows!(
119 &conn,
120 "SELECT * FROM group_memberships WHERE role = $1 AND group_id = $2 ORDER BY created DESC LIMIT $3 OFFSET $4",
121 &[
122 &serde_json::to_string(&role).unwrap(),
123 &group.printable(),
124 &(batch as i64),
125 &((page * batch) as i64)
126 ],
127 |x| { Self::get_group_membership_from_row(x) }
128 );
129
130 if res.is_err() {
131 return Err(Error::GeneralNotFound("membership".to_string()));
132 }
133
134 Ok(res.unwrap())
135 }
136
137 pub async fn create_group_membership(&self, data: GroupMembership) -> Result<()> {
142 let conn = match self.0.connect().await {
143 Ok(c) => c,
144 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
145 };
146
147 let res = execute!(
148 &conn,
149 "INSERT INTO group_memberships VALUES ($1, $2, $3, $4, $5)",
150 params![
151 &data.id.printable(),
152 &(data.created as i64),
153 &data.owner.printable(),
154 &data.group.printable(),
155 &serde_json::to_string(&data.role).unwrap(),
156 ]
157 );
158
159 if let Err(e) = res {
160 return Err(Error::DatabaseError(e.to_string()));
161 }
162
163 if data.role == GroupRole::Owner || data.role == GroupRole::Member {
165 self.incr_group_members(&data.group).await?;
166 }
167
168 Ok(())
170 }
171
172 pub async fn delete_group_membership(&self, id: &Id) -> Result<()> {
173 let y = self.get_group_membership_by_id(id).await?;
174
175 let conn = match self.0.connect().await {
176 Ok(c) => c,
177 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
178 };
179
180 let res = execute!(
181 &conn,
182 "DELETE FROM group_memberships WHERE id = $1",
183 &[&id.printable()]
184 );
185
186 if let Err(e) = res {
187 return Err(Error::DatabaseError(e.to_string()));
188 }
189
190 self.0
191 .1
192 .remove(format!("juic.group_membership:{}", id))
193 .await;
194
195 if y.role == GroupRole::Owner || y.role == GroupRole::Member {
197 self.decr_group_members(&y.group).await?;
198 }
199
200 Ok(())
202 }
203
204 pub async fn update_group_membership_role(&self, id: &Id, role: GroupRole) -> Result<()> {
205 let y = self.get_group_membership_by_id(id).await?;
206
207 let conn = match self.0.connect().await {
208 Ok(c) => c,
209 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
210 };
211
212 let res = execute!(
213 &conn,
214 "UPDATE group_memberships SET role = $1 WHERE id = $2",
215 &[&serde_json::to_string(&role).unwrap(), &id.printable()]
216 );
217
218 if let Err(e) = res {
219 return Err(Error::DatabaseError(e.to_string()));
220 }
221
222 self.0
223 .1
224 .remove(format!("juic.group_membership:{}", id))
225 .await;
226
227 if (y.role == GroupRole::Owner || y.role == GroupRole::Member)
229 && (role == GroupRole::Banned || role == GroupRole::Pending)
230 {
231 self.decr_group_members(&y.group).await?;
233 } else if (y.role == GroupRole::Banned || y.role == GroupRole::Pending)
234 && (role == GroupRole::Owner || role == GroupRole::Member)
235 {
236 self.incr_group_members(&y.group).await?;
238 }
239
240 Ok(())
242 }
243}