1 use crate::structs::CommentReportView;
2 use diesel::{dsl::*, result::Error, *};
4 aggregates::structs::CommentAggregates,
5 newtypes::{CommentReportId, CommunityId, PersonId},
19 comment_report::CommentReport,
20 community::{Community, CommunityPersonBan, CommunitySafe},
21 person::{Person, PersonSafe},
24 traits::{ToSafe, ViewToVec},
25 utils::limit_and_offset,
27 use typed_builder::TypedBuilder;
29 type CommentReportViewTuple = (
37 Option<CommunityPersonBan>,
42 impl CommentReportView {
43 /// returns the CommentReportView for the provided report_id
45 /// * `report_id` - the report id to obtain
47 conn: &mut PgConnection,
48 report_id: CommentReportId,
49 my_person_id: PersonId,
50 ) -> Result<Self, Error> {
51 let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
61 creator_banned_from_community,
64 ) = comment_report::table
66 .inner_join(comment::table)
67 .inner_join(post::table.on(comment::post_id.eq(post::id)))
68 .inner_join(community::table.on(post::community_id.eq(community::id)))
69 .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
70 .inner_join(person_alias_1.on(comment::creator_id.eq(person_alias_1.field(person::id))))
72 comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)),
75 community_person_ban::table.on(
77 .eq(community_person_ban::community_id)
78 .and(community_person_ban::person_id.eq(comment::creator_id))
80 community_person_ban::expires
82 .or(community_person_ban::expires.gt(now)),
87 comment_like::table.on(
89 .eq(comment_like::comment_id)
90 .and(comment_like::person_id.eq(my_person_id)),
95 .on(comment_report::resolver_id.eq(person_alias_2.field(person::id).nullable())),
98 comment_report::all_columns,
101 Community::safe_columns_tuple(),
102 Person::safe_columns_tuple(),
103 person_alias_1.fields(Person::safe_columns_tuple()),
104 comment_aggregates::all_columns,
105 community_person_ban::all_columns.nullable(),
106 comment_like::score.nullable(),
108 .fields(Person::safe_columns_tuple())
111 .first::<CommentReportViewTuple>(conn)?;
113 let my_vote = comment_like;
123 creator_banned_from_community: creator_banned_from_community.is_some(),
129 /// Returns the current unresolved post report count for the communities you mod
130 pub fn get_report_count(
131 conn: &mut PgConnection,
132 my_person_id: PersonId,
134 community_id: Option<CommunityId>,
135 ) -> Result<i64, Error> {
138 let mut query = comment_report::table
139 .inner_join(comment::table)
140 .inner_join(post::table.on(comment::post_id.eq(post::id)))
141 .filter(comment_report::resolved.eq(false))
144 if let Some(community_id) = community_id {
145 query = query.filter(post::community_id.eq(community_id))
148 // If its not an admin, get only the ones you mod
152 community_moderator::table.on(
153 community_moderator::community_id
154 .eq(post::community_id)
155 .and(community_moderator::person_id.eq(my_person_id)),
158 .select(count(comment_report::id))
161 query.select(count(comment_report::id)).first::<i64>(conn)
166 #[derive(TypedBuilder)]
167 #[builder(field_defaults(default))]
168 pub struct CommentReportQuery<'a> {
170 conn: &'a mut PgConnection,
172 my_person_id: PersonId,
175 community_id: Option<CommunityId>,
178 unresolved_only: Option<bool>,
181 impl<'a> CommentReportQuery<'a> {
182 pub fn list(self) -> Result<Vec<CommentReportView>, Error> {
183 let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
185 let mut query = comment_report::table
186 .inner_join(comment::table)
187 .inner_join(post::table.on(comment::post_id.eq(post::id)))
188 .inner_join(community::table.on(post::community_id.eq(community::id)))
189 .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
190 .inner_join(person_alias_1.on(comment::creator_id.eq(person_alias_1.field(person::id))))
192 comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)),
195 community_person_ban::table.on(
197 .eq(community_person_ban::community_id)
198 .and(community_person_ban::person_id.eq(comment::creator_id))
200 community_person_ban::expires
202 .or(community_person_ban::expires.gt(now)),
207 comment_like::table.on(
209 .eq(comment_like::comment_id)
210 .and(comment_like::person_id.eq(self.my_person_id)),
215 .on(comment_report::resolver_id.eq(person_alias_2.field(person::id).nullable())),
218 comment_report::all_columns,
219 comment::all_columns,
221 Community::safe_columns_tuple(),
222 Person::safe_columns_tuple(),
223 person_alias_1.fields(Person::safe_columns_tuple()),
224 comment_aggregates::all_columns,
225 community_person_ban::all_columns.nullable(),
226 comment_like::score.nullable(),
228 .fields(Person::safe_columns_tuple())
233 if let Some(community_id) = self.community_id {
234 query = query.filter(post::community_id.eq(community_id));
237 if self.unresolved_only.unwrap_or(true) {
238 query = query.filter(comment_report::resolved.eq(false));
241 let (limit, offset) = limit_and_offset(self.page, self.limit)?;
244 .order_by(comment_report::published.desc())
248 // If its not an admin, get only the ones you mod
249 let res = if !self.admin {
252 community_moderator::table.on(
253 community_moderator::community_id
254 .eq(post::community_id)
255 .and(community_moderator::person_id.eq(self.my_person_id)),
258 .load::<CommentReportViewTuple>(self.conn)?
260 query.load::<CommentReportViewTuple>(self.conn)?
263 Ok(CommentReportView::from_tuple_to_vec(res))
267 impl ViewToVec for CommentReportView {
268 type DbTuple = CommentReportViewTuple;
269 fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
278 comment_creator: a.5,
280 creator_banned_from_community: a.7.is_some(),
284 .collect::<Vec<Self>>()
290 use crate::comment_report_view::{CommentReportQuery, CommentReportView};
291 use lemmy_db_schema::{
292 aggregates::structs::CommentAggregates,
293 source::{comment::*, comment_report::*, community::*, person::*, post::*},
294 traits::{Crud, Joinable, Reportable},
295 utils::establish_unpooled_connection,
297 use serial_test::serial;
302 let conn = &mut establish_unpooled_connection();
304 let new_person = PersonForm {
305 name: "timmy_crv".into(),
306 public_key: Some("pubkey".to_string()),
307 ..PersonForm::default()
310 let inserted_timmy = Person::create(conn, &new_person).unwrap();
312 let new_person_2 = PersonForm {
313 name: "sara_crv".into(),
314 public_key: Some("pubkey".to_string()),
315 ..PersonForm::default()
318 let inserted_sara = Person::create(conn, &new_person_2).unwrap();
320 // Add a third person, since new ppl can only report something once.
321 let new_person_3 = PersonForm {
322 name: "jessica_crv".into(),
323 public_key: Some("pubkey".to_string()),
324 ..PersonForm::default()
327 let inserted_jessica = Person::create(conn, &new_person_3).unwrap();
329 let new_community = CommunityForm {
330 name: "test community crv".to_string(),
331 title: "nada".to_owned(),
332 public_key: Some("pubkey".to_string()),
333 ..CommunityForm::default()
336 let inserted_community = Community::create(conn, &new_community).unwrap();
339 let timmy_moderator_form = CommunityModeratorForm {
340 community_id: inserted_community.id,
341 person_id: inserted_timmy.id,
344 let _inserted_moderator = CommunityModerator::join(conn, &timmy_moderator_form).unwrap();
346 let new_post = PostForm {
347 name: "A test post crv".into(),
348 creator_id: inserted_timmy.id,
349 community_id: inserted_community.id,
350 ..PostForm::default()
353 let inserted_post = Post::create(conn, &new_post).unwrap();
355 let comment_form = CommentForm {
356 content: "A test comment 32".into(),
357 creator_id: inserted_timmy.id,
358 post_id: inserted_post.id,
359 ..CommentForm::default()
362 let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
365 let sara_report_form = CommentReportForm {
366 creator_id: inserted_sara.id,
367 comment_id: inserted_comment.id,
368 original_comment_text: "this was it at time of creation".into(),
369 reason: "from sara".into(),
372 let inserted_sara_report = CommentReport::report(conn, &sara_report_form).unwrap();
375 let jessica_report_form = CommentReportForm {
376 creator_id: inserted_jessica.id,
377 comment_id: inserted_comment.id,
378 original_comment_text: "this was it at time of creation".into(),
379 reason: "from jessica".into(),
382 let inserted_jessica_report = CommentReport::report(conn, &jessica_report_form).unwrap();
384 let agg = CommentAggregates::read(conn, inserted_comment.id).unwrap();
386 let read_jessica_report_view =
387 CommentReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
388 let expected_jessica_report_view = CommentReportView {
389 comment_report: inserted_jessica_report.to_owned(),
390 comment: inserted_comment.to_owned(),
392 community: CommunitySafe {
393 id: inserted_community.id,
394 name: inserted_community.name,
399 actor_id: inserted_community.actor_id.to_owned(),
401 title: inserted_community.title,
406 posting_restricted_to_mods: false,
407 published: inserted_community.published,
409 creator: PersonSafe {
410 id: inserted_jessica.id,
411 name: inserted_jessica.name,
413 published: inserted_jessica.published,
415 actor_id: inserted_jessica.actor_id.to_owned(),
424 inbox_url: inserted_jessica.inbox_url.to_owned(),
425 shared_inbox_url: None,
426 matrix_user_id: None,
429 comment_creator: PersonSafe {
430 id: inserted_timmy.id,
431 name: inserted_timmy.name.to_owned(),
433 published: inserted_timmy.published,
435 actor_id: inserted_timmy.actor_id.to_owned(),
444 inbox_url: inserted_timmy.inbox_url.to_owned(),
445 shared_inbox_url: None,
446 matrix_user_id: None,
449 creator_banned_from_community: false,
450 counts: CommentAggregates {
452 comment_id: inserted_comment.id,
456 published: agg.published,
463 assert_eq!(read_jessica_report_view, expected_jessica_report_view);
465 let mut expected_sara_report_view = expected_jessica_report_view.clone();
466 expected_sara_report_view.comment_report = inserted_sara_report;
467 expected_sara_report_view.creator = PersonSafe {
468 id: inserted_sara.id,
469 name: inserted_sara.name,
471 published: inserted_sara.published,
473 actor_id: inserted_sara.actor_id.to_owned(),
482 inbox_url: inserted_sara.inbox_url.to_owned(),
483 shared_inbox_url: None,
484 matrix_user_id: None,
488 // Do a batch read of timmys reports
489 let reports = CommentReportQuery::builder()
491 .my_person_id(inserted_timmy.id)
500 expected_jessica_report_view.to_owned(),
501 expected_sara_report_view.to_owned()
505 // Make sure the counts are correct
507 CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
508 assert_eq!(2, report_count);
510 // Try to resolve the report
511 CommentReport::resolve(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
512 let read_jessica_report_view_after_resolve =
513 CommentReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
515 let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
516 expected_jessica_report_view_after_resolve
519 expected_jessica_report_view_after_resolve
521 .resolver_id = Some(inserted_timmy.id);
522 expected_jessica_report_view_after_resolve
524 .updated = read_jessica_report_view_after_resolve
527 expected_jessica_report_view_after_resolve.resolver = Some(PersonSafe {
528 id: inserted_timmy.id,
529 name: inserted_timmy.name.to_owned(),
531 published: inserted_timmy.published,
533 actor_id: inserted_timmy.actor_id.to_owned(),
542 inbox_url: inserted_timmy.inbox_url.to_owned(),
543 shared_inbox_url: None,
544 matrix_user_id: None,
549 read_jessica_report_view_after_resolve,
550 expected_jessica_report_view_after_resolve
553 // Do a batch read of timmys reports
554 // It should only show saras, which is unresolved
555 let reports_after_resolve = CommentReportQuery::builder()
557 .my_person_id(inserted_timmy.id)
562 assert_eq!(reports_after_resolve[0], expected_sara_report_view);
563 assert_eq!(reports_after_resolve.len(), 1);
565 // Make sure the counts are correct
566 let report_count_after_resolved =
567 CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
568 assert_eq!(1, report_count_after_resolved);
570 Person::delete(conn, inserted_timmy.id).unwrap();
571 Person::delete(conn, inserted_sara.id).unwrap();
572 Person::delete(conn, inserted_jessica.id).unwrap();
573 Community::delete(conn, inserted_community.id).unwrap();