1 use crate::structs::PostReportView;
2 use diesel::{dsl::*, result::Error, *};
4 aggregates::structs::PostAggregates,
5 newtypes::{CommunityId, PersonId, PostReportId},
19 community::{Community, CommunityPersonBan, CommunitySafe},
20 person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
22 post_report::PostReport,
24 traits::{ToSafe, ViewToVec},
25 utils::limit_and_offset,
27 use typed_builder::TypedBuilder;
29 type PostReportViewTuple = (
35 Option<CommunityPersonBan>,
38 Option<PersonSafeAlias2>,
42 /// returns the PostReportView for the provided report_id
44 /// * `report_id` - the report id to obtain
47 report_id: PostReportId,
48 my_person_id: PersonId,
49 ) -> Result<Self, Error> {
56 creator_banned_from_community,
60 ) = post_report::table
62 .inner_join(post::table)
63 .inner_join(community::table.on(post::community_id.eq(community::id)))
64 .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
65 .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
67 community_person_ban::table.on(
69 .eq(community_person_ban::community_id)
70 .and(community_person_ban::person_id.eq(post::creator_id))
72 community_person_ban::expires
74 .or(community_person_ban::expires.gt(now)),
81 .eq(post_like::post_id)
82 .and(post_like::person_id.eq(my_person_id)),
85 .inner_join(post_aggregates::table.on(post_report::post_id.eq(post_aggregates::post_id)))
87 person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
90 post_report::all_columns,
92 Community::safe_columns_tuple(),
93 Person::safe_columns_tuple(),
94 PersonAlias1::safe_columns_tuple(),
95 community_person_ban::all_columns.nullable(),
96 post_like::score.nullable(),
97 post_aggregates::all_columns,
98 PersonAlias2::safe_columns_tuple().nullable(),
100 .first::<PostReportViewTuple>(conn)?;
102 let my_vote = post_like;
110 creator_banned_from_community: creator_banned_from_community.is_some(),
117 /// returns the current unresolved post report count for the communities you mod
118 pub fn get_report_count(
120 my_person_id: PersonId,
122 community_id: Option<CommunityId>,
123 ) -> Result<i64, Error> {
125 let mut query = post_report::table
126 .inner_join(post::table)
127 .filter(post_report::resolved.eq(false))
130 if let Some(community_id) = community_id {
131 query = query.filter(post::community_id.eq(community_id))
134 // If its not an admin, get only the ones you mod
138 community_moderator::table.on(
139 community_moderator::community_id
140 .eq(post::community_id)
141 .and(community_moderator::person_id.eq(my_person_id)),
144 .select(count(post_report::id))
147 query.select(count(post_report::id)).first::<i64>(conn)
152 #[derive(TypedBuilder)]
153 #[builder(field_defaults(default))]
154 pub struct PostReportQuery<'a> {
156 conn: &'a PgConnection,
158 my_person_id: PersonId,
161 community_id: Option<CommunityId>,
164 unresolved_only: Option<bool>,
167 impl<'a> PostReportQuery<'a> {
168 pub fn list(self) -> Result<Vec<PostReportView>, Error> {
169 let mut query = post_report::table
170 .inner_join(post::table)
171 .inner_join(community::table.on(post::community_id.eq(community::id)))
172 .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
173 .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
175 community_person_ban::table.on(
177 .eq(community_person_ban::community_id)
178 .and(community_person_ban::person_id.eq(post::creator_id))
180 community_person_ban::expires
182 .or(community_person_ban::expires.gt(now)),
189 .eq(post_like::post_id)
190 .and(post_like::person_id.eq(self.my_person_id)),
193 .inner_join(post_aggregates::table.on(post_report::post_id.eq(post_aggregates::post_id)))
195 person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
198 post_report::all_columns,
200 Community::safe_columns_tuple(),
201 Person::safe_columns_tuple(),
202 PersonAlias1::safe_columns_tuple(),
203 community_person_ban::all_columns.nullable(),
204 post_like::score.nullable(),
205 post_aggregates::all_columns,
206 PersonAlias2::safe_columns_tuple().nullable(),
210 if let Some(community_id) = self.community_id {
211 query = query.filter(post::community_id.eq(community_id));
214 if self.unresolved_only.unwrap_or(true) {
215 query = query.filter(post_report::resolved.eq(false));
218 let (limit, offset) = limit_and_offset(self.page, self.limit)?;
221 .order_by(post_report::published.desc())
225 // If its not an admin, get only the ones you mod
226 let res = if !self.admin {
229 community_moderator::table.on(
230 community_moderator::community_id
231 .eq(post::community_id)
232 .and(community_moderator::person_id.eq(self.my_person_id)),
235 .load::<PostReportViewTuple>(self.conn)?
237 query.load::<PostReportViewTuple>(self.conn)?
240 Ok(PostReportView::from_tuple_to_vec(res))
244 impl ViewToVec for PostReportView {
245 type DbTuple = PostReportViewTuple;
246 fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
255 creator_banned_from_community: a.5.is_some(),
260 .collect::<Vec<Self>>()
266 use crate::post_report_view::{PostReportQuery, PostReportView};
267 use lemmy_db_schema::{
268 aggregates::structs::PostAggregates,
273 post_report::{PostReport, PostReportForm},
275 traits::{Crud, Joinable, Reportable},
276 utils::establish_unpooled_connection,
278 use serial_test::serial;
283 let conn = establish_unpooled_connection();
285 let new_person = PersonForm {
286 name: "timmy_prv".into(),
287 public_key: Some("pubkey".to_string()),
288 ..PersonForm::default()
291 let inserted_timmy = Person::create(&conn, &new_person).unwrap();
293 let new_person_2 = PersonForm {
294 name: "sara_prv".into(),
295 public_key: Some("pubkey".to_string()),
296 ..PersonForm::default()
299 let inserted_sara = Person::create(&conn, &new_person_2).unwrap();
301 // Add a third person, since new ppl can only report something once.
302 let new_person_3 = PersonForm {
303 name: "jessica_prv".into(),
304 public_key: Some("pubkey".to_string()),
305 ..PersonForm::default()
308 let inserted_jessica = Person::create(&conn, &new_person_3).unwrap();
310 let new_community = CommunityForm {
311 name: "test community prv".to_string(),
312 title: "nada".to_owned(),
313 public_key: Some("pubkey".to_string()),
314 ..CommunityForm::default()
317 let inserted_community = Community::create(&conn, &new_community).unwrap();
320 let timmy_moderator_form = CommunityModeratorForm {
321 community_id: inserted_community.id,
322 person_id: inserted_timmy.id,
325 let _inserted_moderator = CommunityModerator::join(&conn, &timmy_moderator_form).unwrap();
327 let new_post = PostForm {
328 name: "A test post crv".into(),
329 creator_id: inserted_timmy.id,
330 community_id: inserted_community.id,
331 ..PostForm::default()
334 let inserted_post = Post::create(&conn, &new_post).unwrap();
337 let sara_report_form = PostReportForm {
338 creator_id: inserted_sara.id,
339 post_id: inserted_post.id,
340 original_post_name: "Orig post".into(),
341 original_post_url: None,
342 original_post_body: None,
343 reason: "from sara".into(),
346 let inserted_sara_report = PostReport::report(&conn, &sara_report_form).unwrap();
349 let jessica_report_form = PostReportForm {
350 creator_id: inserted_jessica.id,
351 post_id: inserted_post.id,
352 original_post_name: "Orig post".into(),
353 original_post_url: None,
354 original_post_body: None,
355 reason: "from jessica".into(),
358 let inserted_jessica_report = PostReport::report(&conn, &jessica_report_form).unwrap();
360 let agg = PostAggregates::read(&conn, inserted_post.id).unwrap();
362 let read_jessica_report_view =
363 PostReportView::read(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
364 let expected_jessica_report_view = PostReportView {
365 post_report: inserted_jessica_report.to_owned(),
366 post: inserted_post.to_owned(),
367 community: CommunitySafe {
368 id: inserted_community.id,
369 name: inserted_community.name,
374 actor_id: inserted_community.actor_id.to_owned(),
376 title: inserted_community.title,
381 posting_restricted_to_mods: false,
382 published: inserted_community.published,
384 creator: PersonSafe {
385 id: inserted_jessica.id,
386 name: inserted_jessica.name,
388 published: inserted_jessica.published,
390 actor_id: inserted_jessica.actor_id.to_owned(),
399 inbox_url: inserted_jessica.inbox_url.to_owned(),
400 shared_inbox_url: None,
401 matrix_user_id: None,
404 post_creator: PersonSafeAlias1 {
405 id: inserted_timmy.id,
406 name: inserted_timmy.name.to_owned(),
408 published: inserted_timmy.published,
410 actor_id: inserted_timmy.actor_id.to_owned(),
419 inbox_url: inserted_timmy.inbox_url.to_owned(),
420 shared_inbox_url: None,
421 matrix_user_id: None,
424 creator_banned_from_community: false,
426 counts: PostAggregates {
428 post_id: inserted_post.id,
434 published: agg.published,
435 newest_comment_time_necro: inserted_post.published,
436 newest_comment_time: inserted_post.published,
441 assert_eq!(read_jessica_report_view, expected_jessica_report_view);
443 let mut expected_sara_report_view = expected_jessica_report_view.clone();
444 expected_sara_report_view.post_report = inserted_sara_report;
445 expected_sara_report_view.my_vote = None;
446 expected_sara_report_view.creator = PersonSafe {
447 id: inserted_sara.id,
448 name: inserted_sara.name,
450 published: inserted_sara.published,
452 actor_id: inserted_sara.actor_id.to_owned(),
461 inbox_url: inserted_sara.inbox_url.to_owned(),
462 shared_inbox_url: None,
463 matrix_user_id: None,
467 // Do a batch read of timmys reports
468 let reports = PostReportQuery::builder()
470 .my_person_id(inserted_timmy.id)
479 expected_jessica_report_view.to_owned(),
480 expected_sara_report_view.to_owned()
484 // Make sure the counts are correct
486 PostReportView::get_report_count(&conn, inserted_timmy.id, false, None).unwrap();
487 assert_eq!(2, report_count);
489 // Try to resolve the report
490 PostReport::resolve(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
491 let read_jessica_report_view_after_resolve =
492 PostReportView::read(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
494 let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
495 expected_jessica_report_view_after_resolve
498 expected_jessica_report_view_after_resolve
500 .resolver_id = Some(inserted_timmy.id);
501 expected_jessica_report_view_after_resolve
503 .updated = read_jessica_report_view_after_resolve.post_report.updated;
504 expected_jessica_report_view_after_resolve.resolver = Some(PersonSafeAlias2 {
505 id: inserted_timmy.id,
506 name: inserted_timmy.name.to_owned(),
508 published: inserted_timmy.published,
510 actor_id: inserted_timmy.actor_id.to_owned(),
519 inbox_url: inserted_timmy.inbox_url.to_owned(),
520 shared_inbox_url: None,
521 matrix_user_id: None,
526 read_jessica_report_view_after_resolve,
527 expected_jessica_report_view_after_resolve
530 // Do a batch read of timmys reports
531 // It should only show saras, which is unresolved
532 let reports_after_resolve = PostReportQuery::builder()
534 .my_person_id(inserted_timmy.id)
539 assert_eq!(reports_after_resolve[0], expected_sara_report_view);
541 // Make sure the counts are correct
542 let report_count_after_resolved =
543 PostReportView::get_report_count(&conn, inserted_timmy.id, false, None).unwrap();
544 assert_eq!(1, report_count_after_resolved);
546 Person::delete(&conn, inserted_timmy.id).unwrap();
547 Person::delete(&conn, inserted_sara.id).unwrap();
548 Person::delete(&conn, inserted_jessica.id).unwrap();
549 Community::delete(&conn, inserted_community.id).unwrap();