]> Untitled Git - lemmy.git/blob - crates/db_views/src/private_message_report_view.rs
Replace Option<bool> with bool for PostQuery and CommentQuery (#3819) (#3857)
[lemmy.git] / crates / db_views / src / private_message_report_view.rs
1 use crate::structs::PrivateMessageReportView;
2 use diesel::{
3   pg::Pg,
4   result::Error,
5   ExpressionMethods,
6   JoinOnDsl,
7   NullableExpressionMethods,
8   QueryDsl,
9 };
10 use diesel_async::RunQueryDsl;
11 use lemmy_db_schema::{
12   aliases,
13   newtypes::PrivateMessageReportId,
14   schema::{person, private_message, private_message_report},
15   source::{
16     person::Person,
17     private_message::PrivateMessage,
18     private_message_report::PrivateMessageReport,
19   },
20   traits::JoinView,
21   utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn},
22 };
23
24 type PrivateMessageReportViewTuple = (
25   PrivateMessageReport,
26   PrivateMessage,
27   Person,
28   Person,
29   Option<Person>,
30 );
31
32 fn queries<'a>() -> Queries<
33   impl ReadFn<'a, PrivateMessageReportView, PrivateMessageReportId>,
34   impl ListFn<'a, PrivateMessageReportView, PrivateMessageReportQuery>,
35 > {
36   let all_joins =
37     |query: private_message_report::BoxedQuery<'a, Pg>| {
38       query
39         .inner_join(private_message::table)
40         .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
41         .inner_join(
42           aliases::person1
43             .on(private_message_report::creator_id.eq(aliases::person1.field(person::id))),
44         )
45         .left_join(aliases::person2.on(
46           private_message_report::resolver_id.eq(aliases::person2.field(person::id).nullable()),
47         ))
48         .select((
49           private_message_report::all_columns,
50           private_message::all_columns,
51           person::all_columns,
52           aliases::person1.fields(person::all_columns),
53           aliases::person2.fields(person::all_columns).nullable(),
54         ))
55     };
56
57   let read = move |mut conn: DbConn<'a>, report_id: PrivateMessageReportId| async move {
58     all_joins(private_message_report::table.find(report_id).into_boxed())
59       .first::<PrivateMessageReportViewTuple>(&mut conn)
60       .await
61   };
62
63   let list = move |mut conn: DbConn<'a>, options: PrivateMessageReportQuery| async move {
64     let mut query = all_joins(private_message_report::table.into_boxed());
65
66     if options.unresolved_only {
67       query = query.filter(private_message_report::resolved.eq(false));
68     }
69
70     let (limit, offset) = limit_and_offset(options.page, options.limit)?;
71
72     query
73       .order_by(private_message::published.desc())
74       .limit(limit)
75       .offset(offset)
76       .load::<PrivateMessageReportViewTuple>(&mut conn)
77       .await
78   };
79
80   Queries::new(read, list)
81 }
82
83 impl PrivateMessageReportView {
84   /// returns the PrivateMessageReportView for the provided report_id
85   ///
86   /// * `report_id` - the report id to obtain
87   pub async fn read(
88     pool: &mut DbPool<'_>,
89     report_id: PrivateMessageReportId,
90   ) -> Result<Self, Error> {
91     queries().read(pool, report_id).await
92   }
93
94   /// Returns the current unresolved post report count for the communities you mod
95   pub async fn get_report_count(pool: &mut DbPool<'_>) -> Result<i64, Error> {
96     use diesel::dsl::count;
97     let conn = &mut get_conn(pool).await?;
98
99     private_message_report::table
100       .inner_join(private_message::table)
101       .filter(private_message_report::resolved.eq(false))
102       .into_boxed()
103       .select(count(private_message_report::id))
104       .first::<i64>(conn)
105       .await
106   }
107 }
108
109 #[derive(Default)]
110 pub struct PrivateMessageReportQuery {
111   pub page: Option<i64>,
112   pub limit: Option<i64>,
113   pub unresolved_only: bool,
114 }
115
116 impl PrivateMessageReportQuery {
117   pub async fn list(self, pool: &mut DbPool<'_>) -> Result<Vec<PrivateMessageReportView>, Error> {
118     queries().list(pool, self).await
119   }
120 }
121
122 impl JoinView for PrivateMessageReportView {
123   type JoinTuple = PrivateMessageReportViewTuple;
124   fn from_tuple(a: Self::JoinTuple) -> Self {
125     Self {
126       private_message_report: a.0,
127       private_message: a.1,
128       private_message_creator: a.2,
129       creator: a.3,
130       resolver: a.4,
131     }
132   }
133 }
134
135 #[cfg(test)]
136 mod tests {
137   #![allow(clippy::unwrap_used)]
138   #![allow(clippy::indexing_slicing)]
139
140   use crate::private_message_report_view::PrivateMessageReportQuery;
141   use lemmy_db_schema::{
142     source::{
143       instance::Instance,
144       person::{Person, PersonInsertForm},
145       private_message::{PrivateMessage, PrivateMessageInsertForm},
146       private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
147     },
148     traits::{Crud, Reportable},
149     utils::build_db_pool_for_tests,
150   };
151   use serial_test::serial;
152
153   #[tokio::test]
154   #[serial]
155   async fn test_crud() {
156     let pool = &build_db_pool_for_tests().await;
157     let pool = &mut pool.into();
158
159     let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
160       .await
161       .unwrap();
162
163     let new_person_1 = PersonInsertForm::builder()
164       .name("timmy_mrv".into())
165       .public_key("pubkey".to_string())
166       .instance_id(inserted_instance.id)
167       .build();
168     let inserted_timmy = Person::create(pool, &new_person_1).await.unwrap();
169
170     let new_person_2 = PersonInsertForm::builder()
171       .name("jessica_mrv".into())
172       .public_key("pubkey".to_string())
173       .instance_id(inserted_instance.id)
174       .build();
175     let inserted_jessica = Person::create(pool, &new_person_2).await.unwrap();
176
177     // timmy sends private message to jessica
178     let pm_form = PrivateMessageInsertForm::builder()
179       .creator_id(inserted_timmy.id)
180       .recipient_id(inserted_jessica.id)
181       .content("something offensive".to_string())
182       .build();
183     let pm = PrivateMessage::create(pool, &pm_form).await.unwrap();
184
185     // jessica reports private message
186     let pm_report_form = PrivateMessageReportForm {
187       creator_id: inserted_jessica.id,
188       original_pm_text: pm.content.clone(),
189       private_message_id: pm.id,
190       reason: "its offensive".to_string(),
191     };
192     let pm_report = PrivateMessageReport::report(pool, &pm_report_form)
193       .await
194       .unwrap();
195
196     let reports = PrivateMessageReportQuery::default()
197       .list(pool)
198       .await
199       .unwrap();
200     assert_eq!(1, reports.len());
201     assert!(!reports[0].private_message_report.resolved);
202     assert_eq!(inserted_timmy.name, reports[0].private_message_creator.name);
203     assert_eq!(inserted_jessica.name, reports[0].creator.name);
204     assert_eq!(pm_report.reason, reports[0].private_message_report.reason);
205     assert_eq!(pm.content, reports[0].private_message.content);
206
207     let new_person_3 = PersonInsertForm::builder()
208       .name("admin_mrv".into())
209       .public_key("pubkey".to_string())
210       .instance_id(inserted_instance.id)
211       .build();
212     let inserted_admin = Person::create(pool, &new_person_3).await.unwrap();
213
214     // admin resolves the report (after taking appropriate action)
215     PrivateMessageReport::resolve(pool, pm_report.id, inserted_admin.id)
216       .await
217       .unwrap();
218
219     let reports = PrivateMessageReportQuery {
220       unresolved_only: (false),
221       ..Default::default()
222     }
223     .list(pool)
224     .await
225     .unwrap();
226     assert_eq!(1, reports.len());
227     assert!(reports[0].private_message_report.resolved);
228     assert!(reports[0].resolver.is_some());
229     assert_eq!(
230       inserted_admin.name,
231       reports[0].resolver.as_ref().unwrap().name
232     );
233
234     Instance::delete(pool, inserted_instance.id).await.unwrap();
235   }
236 }