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::*, instance::Instance, 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 inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
306 let new_person = PersonInsertForm::builder()
307 .name("timmy_crv".into())
308 .public_key("pubkey".to_string())
309 .instance_id(inserted_instance.id)
312 let inserted_timmy = Person::create(conn, &new_person).unwrap();
314 let new_person_2 = PersonInsertForm::builder()
315 .name("sara_crv".into())
316 .public_key("pubkey".to_string())
317 .instance_id(inserted_instance.id)
320 let inserted_sara = Person::create(conn, &new_person_2).unwrap();
322 // Add a third person, since new ppl can only report something once.
323 let new_person_3 = PersonInsertForm::builder()
324 .name("jessica_crv".into())
325 .public_key("pubkey".to_string())
326 .instance_id(inserted_instance.id)
329 let inserted_jessica = Person::create(conn, &new_person_3).unwrap();
331 let new_community = CommunityInsertForm::builder()
332 .name("test community crv".to_string())
333 .title("nada".to_owned())
334 .public_key("pubkey".to_string())
335 .instance_id(inserted_instance.id)
338 let inserted_community = Community::create(conn, &new_community).unwrap();
341 let timmy_moderator_form = CommunityModeratorForm {
342 community_id: inserted_community.id,
343 person_id: inserted_timmy.id,
346 let _inserted_moderator = CommunityModerator::join(conn, &timmy_moderator_form).unwrap();
348 let new_post = PostInsertForm::builder()
349 .name("A test post crv".into())
350 .creator_id(inserted_timmy.id)
351 .community_id(inserted_community.id)
354 let inserted_post = Post::create(conn, &new_post).unwrap();
356 let comment_form = CommentInsertForm::builder()
357 .content("A test comment 32".into())
358 .creator_id(inserted_timmy.id)
359 .post_id(inserted_post.id)
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,
408 instance_id: inserted_instance.id,
410 creator: PersonSafe {
411 id: inserted_jessica.id,
412 name: inserted_jessica.name,
414 published: inserted_jessica.published,
416 actor_id: inserted_jessica.actor_id.to_owned(),
425 inbox_url: inserted_jessica.inbox_url.to_owned(),
426 shared_inbox_url: None,
427 matrix_user_id: None,
429 instance_id: inserted_instance.id,
431 comment_creator: PersonSafe {
432 id: inserted_timmy.id,
433 name: inserted_timmy.name.to_owned(),
435 published: inserted_timmy.published,
437 actor_id: inserted_timmy.actor_id.to_owned(),
446 inbox_url: inserted_timmy.inbox_url.to_owned(),
447 shared_inbox_url: None,
448 matrix_user_id: None,
450 instance_id: inserted_instance.id,
452 creator_banned_from_community: false,
453 counts: CommentAggregates {
455 comment_id: inserted_comment.id,
459 published: agg.published,
466 assert_eq!(read_jessica_report_view, expected_jessica_report_view);
468 let mut expected_sara_report_view = expected_jessica_report_view.clone();
469 expected_sara_report_view.comment_report = inserted_sara_report;
470 expected_sara_report_view.creator = PersonSafe {
471 id: inserted_sara.id,
472 name: inserted_sara.name,
474 published: inserted_sara.published,
476 actor_id: inserted_sara.actor_id.to_owned(),
485 inbox_url: inserted_sara.inbox_url.to_owned(),
486 shared_inbox_url: None,
487 matrix_user_id: None,
489 instance_id: inserted_instance.id,
492 // Do a batch read of timmys reports
493 let reports = CommentReportQuery::builder()
495 .my_person_id(inserted_timmy.id)
504 expected_jessica_report_view.to_owned(),
505 expected_sara_report_view.to_owned()
509 // Make sure the counts are correct
511 CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
512 assert_eq!(2, report_count);
514 // Try to resolve the report
515 CommentReport::resolve(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
516 let read_jessica_report_view_after_resolve =
517 CommentReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
519 let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
520 expected_jessica_report_view_after_resolve
523 expected_jessica_report_view_after_resolve
525 .resolver_id = Some(inserted_timmy.id);
526 expected_jessica_report_view_after_resolve
528 .updated = read_jessica_report_view_after_resolve
531 expected_jessica_report_view_after_resolve.resolver = Some(PersonSafe {
532 id: inserted_timmy.id,
533 name: inserted_timmy.name.to_owned(),
535 published: inserted_timmy.published,
537 actor_id: inserted_timmy.actor_id.to_owned(),
546 inbox_url: inserted_timmy.inbox_url.to_owned(),
547 shared_inbox_url: None,
548 matrix_user_id: None,
550 instance_id: inserted_instance.id,
554 read_jessica_report_view_after_resolve,
555 expected_jessica_report_view_after_resolve
558 // Do a batch read of timmys reports
559 // It should only show saras, which is unresolved
560 let reports_after_resolve = CommentReportQuery::builder()
562 .my_person_id(inserted_timmy.id)
567 assert_eq!(reports_after_resolve[0], expected_sara_report_view);
568 assert_eq!(reports_after_resolve.len(), 1);
570 // Make sure the counts are correct
571 let report_count_after_resolved =
572 CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
573 assert_eq!(1, report_count_after_resolved);
575 Person::delete(conn, inserted_timmy.id).unwrap();
576 Person::delete(conn, inserted_sara.id).unwrap();
577 Person::delete(conn, inserted_jessica.id).unwrap();
578 Community::delete(conn, inserted_community.id).unwrap();
579 Instance::delete(conn, inserted_instance.id).unwrap();