1 use diesel::{result::Error, *};
2 use lemmy_db_queries::{
3 aggregates::comment_aggregates::CommentAggregates,
25 comment_report::CommentReport,
26 community::{Community, CommunityPersonBan, CommunitySafe},
27 person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
36 #[derive(Debug, PartialEq, Serialize, Clone)]
37 pub struct CommentReportView {
38 pub comment_report: CommentReport,
41 pub community: CommunitySafe,
42 pub creator: PersonSafe,
43 pub comment_creator: PersonSafeAlias1,
44 pub counts: CommentAggregates,
45 pub creator_banned_from_community: bool, // Left Join to CommunityPersonBan
46 pub my_vote: Option<i16>, // Left join to CommentLike
47 pub resolver: Option<PersonSafeAlias2>,
50 type CommentReportViewTuple = (
58 Option<CommunityPersonBan>,
60 Option<PersonSafeAlias2>,
63 impl CommentReportView {
64 /// returns the CommentReportView for the provided report_id
66 /// * `report_id` - the report id to obtain
69 report_id: CommentReportId,
70 my_person_id: PersonId,
71 ) -> Result<Self, Error> {
80 creator_banned_from_community,
83 ) = comment_report::table
85 .inner_join(comment::table)
86 .inner_join(post::table.on(comment::post_id.eq(post::id)))
87 .inner_join(community::table.on(post::community_id.eq(community::id)))
88 .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
89 .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
91 comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)),
94 community_person_ban::table.on(
96 .eq(community_person_ban::community_id)
97 .and(community_person_ban::person_id.eq(comment::creator_id)),
101 comment_like::table.on(
103 .eq(comment_like::comment_id)
104 .and(comment_like::person_id.eq(my_person_id)),
108 person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())),
111 comment_report::all_columns,
112 comment::all_columns,
114 Community::safe_columns_tuple(),
115 Person::safe_columns_tuple(),
116 PersonAlias1::safe_columns_tuple(),
117 comment_aggregates::all_columns,
118 community_person_ban::all_columns.nullable(),
119 comment_like::score.nullable(),
120 PersonAlias2::safe_columns_tuple().nullable(),
122 .first::<CommentReportViewTuple>(conn)?;
124 let my_vote = if comment_like.is_none() {
138 creator_banned_from_community: creator_banned_from_community.is_some(),
144 /// returns the current unresolved post report count for the supplied community ids
146 /// * `community_ids` - a Vec<i32> of community_ids to get a count for
147 /// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator
148 /// TODO FIX THIS NOW
150 pub fn get_report_count(
152 my_person_id: PersonId,
153 community_id: Option<CommunityId>,
154 ) -> Result<i64, Error> {
157 let mut query = comment_report::table
158 .inner_join(comment::table)
159 .inner_join(post::table.on(comment::post_id.eq(post::id)))
162 community_moderator::table.on(
163 community_moderator::community_id
164 .eq(post::community_id)
165 .and(community_moderator::person_id.eq(my_person_id)),
168 .filter(comment_report::resolved.eq(false))
171 if let Some(community_id) = community_id {
172 query = query.filter(post::community_id.eq(community_id))
175 query.select(count(comment_report::id)).first::<i64>(conn)
179 pub struct CommentReportQueryBuilder<'a> {
180 conn: &'a PgConnection,
181 my_person_id: PersonId,
182 community_id: Option<CommunityId>,
185 unresolved_only: Option<bool>,
188 impl<'a> CommentReportQueryBuilder<'a> {
189 pub fn create(conn: &'a PgConnection, my_person_id: PersonId) -> Self {
190 CommentReportQueryBuilder {
196 unresolved_only: Some(true),
200 pub fn community_id<T: MaybeOptional<CommunityId>>(mut self, community_id: T) -> Self {
201 self.community_id = community_id.get_optional();
205 pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
206 self.page = page.get_optional();
210 pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
211 self.limit = limit.get_optional();
215 pub fn unresolved_only<T: MaybeOptional<bool>>(mut self, unresolved_only: T) -> Self {
216 self.unresolved_only = unresolved_only.get_optional();
220 pub fn list(self) -> Result<Vec<CommentReportView>, Error> {
221 let mut query = comment_report::table
222 .inner_join(comment::table)
223 .inner_join(post::table.on(comment::post_id.eq(post::id)))
224 .inner_join(community::table.on(post::community_id.eq(community::id)))
225 .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
226 .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
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)),
236 comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)),
239 community_person_ban::table.on(
241 .eq(community_person_ban::community_id)
242 .and(community_person_ban::person_id.eq(comment::creator_id)),
246 comment_like::table.on(
248 .eq(comment_like::comment_id)
249 .and(comment_like::person_id.eq(self.my_person_id)),
253 person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())),
256 comment_report::all_columns,
257 comment::all_columns,
259 Community::safe_columns_tuple(),
260 Person::safe_columns_tuple(),
261 PersonAlias1::safe_columns_tuple(),
262 comment_aggregates::all_columns,
263 community_person_ban::all_columns.nullable(),
264 comment_like::score.nullable(),
265 PersonAlias2::safe_columns_tuple().nullable(),
269 if let Some(community_id) = self.community_id {
270 query = query.filter(post::community_id.eq(community_id));
273 if self.unresolved_only.unwrap_or(false) {
274 query = query.filter(comment_report::resolved.eq(false));
277 let (limit, offset) = limit_and_offset(self.page, self.limit);
280 .order_by(comment_report::published.asc())
283 .load::<CommentReportViewTuple>(self.conn)?;
285 Ok(CommentReportView::from_tuple_to_vec(res))
289 impl ViewToVec for CommentReportView {
290 type DbTuple = CommentReportViewTuple;
291 fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
295 comment_report: a.0.to_owned(),
296 comment: a.1.to_owned(),
297 post: a.2.to_owned(),
298 community: a.3.to_owned(),
299 creator: a.4.to_owned(),
300 comment_creator: a.5.to_owned(),
301 counts: a.6.to_owned(),
302 creator_banned_from_community: a.7.is_some(),
304 resolver: a.9.to_owned(),
306 .collect::<Vec<Self>>()
312 use crate::comment_report_view::{CommentReportQueryBuilder, CommentReportView};
313 use lemmy_db_queries::{
314 aggregates::comment_aggregates::CommentAggregates,
315 establish_unpooled_connection,
320 use lemmy_db_schema::source::{comment::*, comment_report::*, community::*, person::*, post::*};
321 use serial_test::serial;
326 let conn = establish_unpooled_connection();
328 let new_person = PersonForm {
329 name: "timmy_crv".into(),
330 ..PersonForm::default()
333 let inserted_timmy = Person::create(&conn, &new_person).unwrap();
335 let new_person_2 = PersonForm {
336 name: "sara_crv".into(),
337 ..PersonForm::default()
340 let inserted_sara = Person::create(&conn, &new_person_2).unwrap();
342 // Add a third person, since new ppl can only report something once.
343 let new_person_3 = PersonForm {
344 name: "jessica_crv".into(),
345 ..PersonForm::default()
348 let inserted_jessica = Person::create(&conn, &new_person_3).unwrap();
350 let new_community = CommunityForm {
351 name: "test community crv".to_string(),
352 title: "nada".to_owned(),
353 ..CommunityForm::default()
356 let inserted_community = Community::create(&conn, &new_community).unwrap();
359 let timmy_moderator_form = CommunityModeratorForm {
360 community_id: inserted_community.id,
361 person_id: inserted_timmy.id,
364 let _inserted_moderator = CommunityModerator::join(&conn, &timmy_moderator_form).unwrap();
366 let new_post = PostForm {
367 name: "A test post crv".into(),
368 creator_id: inserted_timmy.id,
369 community_id: inserted_community.id,
370 ..PostForm::default()
373 let inserted_post = Post::create(&conn, &new_post).unwrap();
375 let comment_form = CommentForm {
376 content: "A test comment 32".into(),
377 creator_id: inserted_timmy.id,
378 post_id: inserted_post.id,
379 ..CommentForm::default()
382 let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
385 let sara_report_form = CommentReportForm {
386 creator_id: inserted_sara.id,
387 comment_id: inserted_comment.id,
388 original_comment_text: "this was it at time of creation".into(),
389 reason: "from sara".into(),
392 let inserted_sara_report = CommentReport::report(&conn, &sara_report_form).unwrap();
395 let jessica_report_form = CommentReportForm {
396 creator_id: inserted_jessica.id,
397 comment_id: inserted_comment.id,
398 original_comment_text: "this was it at time of creation".into(),
399 reason: "from jessica".into(),
402 let inserted_jessica_report = CommentReport::report(&conn, &jessica_report_form).unwrap();
404 let agg = CommentAggregates::read(&conn, inserted_comment.id).unwrap();
406 let read_jessica_report_view =
407 CommentReportView::read(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
408 let expected_jessica_report_view = CommentReportView {
409 comment_report: inserted_jessica_report.to_owned(),
410 comment: inserted_comment.to_owned(),
412 community: CommunitySafe {
413 id: inserted_community.id,
414 name: inserted_community.name,
419 actor_id: inserted_community.actor_id.to_owned(),
421 title: inserted_community.title,
425 published: inserted_community.published,
427 creator: PersonSafe {
428 id: inserted_jessica.id,
429 name: inserted_jessica.name,
431 published: inserted_jessica.published,
433 actor_id: inserted_jessica.actor_id.to_owned(),
442 inbox_url: inserted_jessica.inbox_url.to_owned(),
443 shared_inbox_url: None,
444 matrix_user_id: None,
446 comment_creator: PersonSafeAlias1 {
447 id: inserted_timmy.id,
448 name: inserted_timmy.name.to_owned(),
450 published: inserted_timmy.published,
452 actor_id: inserted_timmy.actor_id.to_owned(),
461 inbox_url: inserted_timmy.inbox_url.to_owned(),
462 shared_inbox_url: None,
463 matrix_user_id: None,
465 creator_banned_from_community: false,
466 counts: CommentAggregates {
468 comment_id: inserted_comment.id,
472 published: agg.published,
478 assert_eq!(read_jessica_report_view, expected_jessica_report_view);
480 let mut expected_sara_report_view = expected_jessica_report_view.clone();
481 expected_sara_report_view.comment_report = inserted_sara_report;
482 expected_sara_report_view.creator = PersonSafe {
483 id: inserted_sara.id,
484 name: inserted_sara.name,
486 published: inserted_sara.published,
488 actor_id: inserted_sara.actor_id.to_owned(),
497 inbox_url: inserted_sara.inbox_url.to_owned(),
498 shared_inbox_url: None,
499 matrix_user_id: None,
502 // Do a batch read of timmys reports
503 let reports = CommentReportQueryBuilder::create(&conn, inserted_timmy.id)
510 expected_sara_report_view.to_owned(),
511 expected_jessica_report_view.to_owned()
515 // Make sure the counts are correct
516 let report_count = CommentReportView::get_report_count(&conn, inserted_timmy.id, None).unwrap();
517 assert_eq!(2, report_count);
519 // Try to resolve the report
520 CommentReport::resolve(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
521 let read_jessica_report_view_after_resolve =
522 CommentReportView::read(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
524 let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
525 expected_jessica_report_view_after_resolve
528 expected_jessica_report_view_after_resolve
530 .resolver_id = Some(inserted_timmy.id);
531 expected_jessica_report_view_after_resolve
533 .updated = read_jessica_report_view_after_resolve
536 expected_jessica_report_view_after_resolve.resolver = Some(PersonSafeAlias2 {
537 id: inserted_timmy.id,
538 name: inserted_timmy.name.to_owned(),
540 published: inserted_timmy.published,
542 actor_id: inserted_timmy.actor_id.to_owned(),
551 inbox_url: inserted_timmy.inbox_url.to_owned(),
552 shared_inbox_url: None,
553 matrix_user_id: None,
557 read_jessica_report_view_after_resolve,
558 expected_jessica_report_view_after_resolve
561 // Do a batch read of timmys reports
562 // It should only show saras, which is unresolved
563 let reports_after_resolve = CommentReportQueryBuilder::create(&conn, inserted_timmy.id)
566 assert_eq!(reports_after_resolve[0], expected_sara_report_view);
568 // Make sure the counts are correct
569 let report_count_after_resolved =
570 CommentReportView::get_report_count(&conn, inserted_timmy.id, None).unwrap();
571 assert_eq!(1, report_count_after_resolved);
573 Person::delete(&conn, inserted_timmy.id).unwrap();
574 Person::delete(&conn, inserted_sara.id).unwrap();
575 Person::delete(&conn, inserted_jessica.id).unwrap();
576 Community::delete(&conn, inserted_community.id).unwrap();