1 use crate::structs::CommentReportView;
2 use diesel::{dsl::*, result::Error, *};
4 aggregates::structs::CommentAggregates,
5 newtypes::{CommentReportId, CommunityId, PersonId},
21 comment_report::CommentReport,
22 community::{Community, CommunityPersonBan, CommunitySafe},
23 person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
26 traits::{ToSafe, ViewToVec},
27 utils::limit_and_offset,
29 use typed_builder::TypedBuilder;
31 type CommentReportViewTuple = (
39 Option<CommunityPersonBan>,
41 Option<PersonSafeAlias2>,
44 impl CommentReportView {
45 /// returns the CommentReportView for the provided report_id
47 /// * `report_id` - the report id to obtain
50 report_id: CommentReportId,
51 my_person_id: PersonId,
52 ) -> Result<Self, Error> {
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::table.on(comment::creator_id.eq(person_alias_1::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)),
94 person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())),
97 comment_report::all_columns,
100 Community::safe_columns_tuple(),
101 Person::safe_columns_tuple(),
102 PersonAlias1::safe_columns_tuple(),
103 comment_aggregates::all_columns,
104 community_person_ban::all_columns.nullable(),
105 comment_like::score.nullable(),
106 PersonAlias2::safe_columns_tuple().nullable(),
108 .first::<CommentReportViewTuple>(conn)?;
110 let my_vote = comment_like;
120 creator_banned_from_community: creator_banned_from_community.is_some(),
126 /// Returns the current unresolved post report count for the communities you mod
127 pub fn get_report_count(
129 my_person_id: PersonId,
131 community_id: Option<CommunityId>,
132 ) -> Result<i64, Error> {
135 let mut query = comment_report::table
136 .inner_join(comment::table)
137 .inner_join(post::table.on(comment::post_id.eq(post::id)))
138 .filter(comment_report::resolved.eq(false))
141 if let Some(community_id) = community_id {
142 query = query.filter(post::community_id.eq(community_id))
145 // If its not an admin, get only the ones you mod
149 community_moderator::table.on(
150 community_moderator::community_id
151 .eq(post::community_id)
152 .and(community_moderator::person_id.eq(my_person_id)),
155 .select(count(comment_report::id))
158 query.select(count(comment_report::id)).first::<i64>(conn)
163 #[derive(TypedBuilder)]
164 #[builder(field_defaults(default))]
165 pub struct CommentReportQuery<'a> {
167 conn: &'a PgConnection,
169 my_person_id: PersonId,
172 community_id: Option<CommunityId>,
175 unresolved_only: Option<bool>,
178 impl<'a> CommentReportQuery<'a> {
179 pub fn list(self) -> Result<Vec<CommentReportView>, Error> {
180 let mut query = comment_report::table
181 .inner_join(comment::table)
182 .inner_join(post::table.on(comment::post_id.eq(post::id)))
183 .inner_join(community::table.on(post::community_id.eq(community::id)))
184 .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
185 .inner_join(person_alias_1::table.on(comment::creator_id.eq(person_alias_1::id)))
187 comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)),
190 community_person_ban::table.on(
192 .eq(community_person_ban::community_id)
193 .and(community_person_ban::person_id.eq(comment::creator_id))
195 community_person_ban::expires
197 .or(community_person_ban::expires.gt(now)),
202 comment_like::table.on(
204 .eq(comment_like::comment_id)
205 .and(comment_like::person_id.eq(self.my_person_id)),
209 person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())),
212 comment_report::all_columns,
213 comment::all_columns,
215 Community::safe_columns_tuple(),
216 Person::safe_columns_tuple(),
217 PersonAlias1::safe_columns_tuple(),
218 comment_aggregates::all_columns,
219 community_person_ban::all_columns.nullable(),
220 comment_like::score.nullable(),
221 PersonAlias2::safe_columns_tuple().nullable(),
225 if let Some(community_id) = self.community_id {
226 query = query.filter(post::community_id.eq(community_id));
229 if self.unresolved_only.unwrap_or(true) {
230 query = query.filter(comment_report::resolved.eq(false));
233 let (limit, offset) = limit_and_offset(self.page, self.limit)?;
236 .order_by(comment_report::published.desc())
240 // If its not an admin, get only the ones you mod
241 let res = if !self.admin {
244 community_moderator::table.on(
245 community_moderator::community_id
246 .eq(post::community_id)
247 .and(community_moderator::person_id.eq(self.my_person_id)),
250 .load::<CommentReportViewTuple>(self.conn)?
252 query.load::<CommentReportViewTuple>(self.conn)?
255 Ok(CommentReportView::from_tuple_to_vec(res))
259 impl ViewToVec for CommentReportView {
260 type DbTuple = CommentReportViewTuple;
261 fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
270 comment_creator: a.5,
272 creator_banned_from_community: a.7.is_some(),
276 .collect::<Vec<Self>>()
282 use crate::comment_report_view::{CommentReportQuery, CommentReportView};
283 use lemmy_db_schema::{
284 aggregates::structs::CommentAggregates,
285 source::{comment::*, comment_report::*, community::*, person::*, post::*},
286 traits::{Crud, Joinable, Reportable},
287 utils::establish_unpooled_connection,
289 use serial_test::serial;
294 let conn = establish_unpooled_connection();
296 let new_person = PersonForm {
297 name: "timmy_crv".into(),
298 public_key: Some("pubkey".to_string()),
299 ..PersonForm::default()
302 let inserted_timmy = Person::create(&conn, &new_person).unwrap();
304 let new_person_2 = PersonForm {
305 name: "sara_crv".into(),
306 public_key: Some("pubkey".to_string()),
307 ..PersonForm::default()
310 let inserted_sara = Person::create(&conn, &new_person_2).unwrap();
312 // Add a third person, since new ppl can only report something once.
313 let new_person_3 = PersonForm {
314 name: "jessica_crv".into(),
315 public_key: Some("pubkey".to_string()),
316 ..PersonForm::default()
319 let inserted_jessica = Person::create(&conn, &new_person_3).unwrap();
321 let new_community = CommunityForm {
322 name: "test community crv".to_string(),
323 title: "nada".to_owned(),
324 public_key: Some("pubkey".to_string()),
325 ..CommunityForm::default()
328 let inserted_community = Community::create(&conn, &new_community).unwrap();
331 let timmy_moderator_form = CommunityModeratorForm {
332 community_id: inserted_community.id,
333 person_id: inserted_timmy.id,
336 let _inserted_moderator = CommunityModerator::join(&conn, &timmy_moderator_form).unwrap();
338 let new_post = PostForm {
339 name: "A test post crv".into(),
340 creator_id: inserted_timmy.id,
341 community_id: inserted_community.id,
342 ..PostForm::default()
345 let inserted_post = Post::create(&conn, &new_post).unwrap();
347 let comment_form = CommentForm {
348 content: "A test comment 32".into(),
349 creator_id: inserted_timmy.id,
350 post_id: inserted_post.id,
351 ..CommentForm::default()
354 let inserted_comment = Comment::create(&conn, &comment_form, None).unwrap();
357 let sara_report_form = CommentReportForm {
358 creator_id: inserted_sara.id,
359 comment_id: inserted_comment.id,
360 original_comment_text: "this was it at time of creation".into(),
361 reason: "from sara".into(),
364 let inserted_sara_report = CommentReport::report(&conn, &sara_report_form).unwrap();
367 let jessica_report_form = CommentReportForm {
368 creator_id: inserted_jessica.id,
369 comment_id: inserted_comment.id,
370 original_comment_text: "this was it at time of creation".into(),
371 reason: "from jessica".into(),
374 let inserted_jessica_report = CommentReport::report(&conn, &jessica_report_form).unwrap();
376 let agg = CommentAggregates::read(&conn, inserted_comment.id).unwrap();
378 let read_jessica_report_view =
379 CommentReportView::read(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
380 let expected_jessica_report_view = CommentReportView {
381 comment_report: inserted_jessica_report.to_owned(),
382 comment: inserted_comment.to_owned(),
384 community: CommunitySafe {
385 id: inserted_community.id,
386 name: inserted_community.name,
391 actor_id: inserted_community.actor_id.to_owned(),
393 title: inserted_community.title,
398 posting_restricted_to_mods: false,
399 published: inserted_community.published,
401 creator: PersonSafe {
402 id: inserted_jessica.id,
403 name: inserted_jessica.name,
405 published: inserted_jessica.published,
407 actor_id: inserted_jessica.actor_id.to_owned(),
416 inbox_url: inserted_jessica.inbox_url.to_owned(),
417 shared_inbox_url: None,
418 matrix_user_id: None,
421 comment_creator: PersonSafeAlias1 {
422 id: inserted_timmy.id,
423 name: inserted_timmy.name.to_owned(),
425 published: inserted_timmy.published,
427 actor_id: inserted_timmy.actor_id.to_owned(),
436 inbox_url: inserted_timmy.inbox_url.to_owned(),
437 shared_inbox_url: None,
438 matrix_user_id: None,
441 creator_banned_from_community: false,
442 counts: CommentAggregates {
444 comment_id: inserted_comment.id,
448 published: agg.published,
455 assert_eq!(read_jessica_report_view, expected_jessica_report_view);
457 let mut expected_sara_report_view = expected_jessica_report_view.clone();
458 expected_sara_report_view.comment_report = inserted_sara_report;
459 expected_sara_report_view.creator = PersonSafe {
460 id: inserted_sara.id,
461 name: inserted_sara.name,
463 published: inserted_sara.published,
465 actor_id: inserted_sara.actor_id.to_owned(),
474 inbox_url: inserted_sara.inbox_url.to_owned(),
475 shared_inbox_url: None,
476 matrix_user_id: None,
480 // Do a batch read of timmys reports
481 let reports = CommentReportQuery::builder()
483 .my_person_id(inserted_timmy.id)
492 expected_jessica_report_view.to_owned(),
493 expected_sara_report_view.to_owned()
497 // Make sure the counts are correct
499 CommentReportView::get_report_count(&conn, inserted_timmy.id, false, None).unwrap();
500 assert_eq!(2, report_count);
502 // Try to resolve the report
503 CommentReport::resolve(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
504 let read_jessica_report_view_after_resolve =
505 CommentReportView::read(&conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
507 let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
508 expected_jessica_report_view_after_resolve
511 expected_jessica_report_view_after_resolve
513 .resolver_id = Some(inserted_timmy.id);
514 expected_jessica_report_view_after_resolve
516 .updated = read_jessica_report_view_after_resolve
519 expected_jessica_report_view_after_resolve.resolver = Some(PersonSafeAlias2 {
520 id: inserted_timmy.id,
521 name: inserted_timmy.name.to_owned(),
523 published: inserted_timmy.published,
525 actor_id: inserted_timmy.actor_id.to_owned(),
534 inbox_url: inserted_timmy.inbox_url.to_owned(),
535 shared_inbox_url: None,
536 matrix_user_id: None,
541 read_jessica_report_view_after_resolve,
542 expected_jessica_report_view_after_resolve
545 // Do a batch read of timmys reports
546 // It should only show saras, which is unresolved
547 let reports_after_resolve = CommentReportQuery::builder()
549 .my_person_id(inserted_timmy.id)
554 assert_eq!(reports_after_resolve[0], expected_sara_report_view);
555 assert_eq!(reports_after_resolve.len(), 1);
557 // Make sure the counts are correct
558 let report_count_after_resolved =
559 CommentReportView::get_report_count(&conn, inserted_timmy.id, false, None).unwrap();
560 assert_eq!(1, report_count_after_resolved);
562 Person::delete(&conn, inserted_timmy.id).unwrap();
563 Person::delete(&conn, inserted_sara.id).unwrap();
564 Person::delete(&conn, inserted_jessica.id).unwrap();
565 Community::delete(&conn, inserted_community.id).unwrap();