1 use crate::structs::CommentReportView;
8 NullableExpressionMethods,
11 use diesel_async::RunQueryDsl;
12 use lemmy_db_schema::{
13 aggregates::structs::CommentAggregates,
14 newtypes::{CommentReportId, CommunityId, PersonId},
28 comment_report::CommentReport,
29 community::{Community, CommunityPersonBan, CommunitySafe},
30 person::{Person, PersonSafe},
33 traits::{ToSafe, ViewToVec},
34 utils::{get_conn, limit_and_offset, DbPool},
36 use typed_builder::TypedBuilder;
38 type CommentReportViewTuple = (
46 Option<CommunityPersonBan>,
51 impl CommentReportView {
52 /// returns the CommentReportView for the provided report_id
54 /// * `report_id` - the report id to obtain
57 report_id: CommentReportId,
58 my_person_id: PersonId,
59 ) -> Result<Self, Error> {
60 let conn = &mut get_conn(pool).await?;
62 let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
72 creator_banned_from_community,
75 ) = comment_report::table
77 .inner_join(comment::table)
78 .inner_join(post::table.on(comment::post_id.eq(post::id)))
79 .inner_join(community::table.on(post::community_id.eq(community::id)))
80 .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
81 .inner_join(person_alias_1.on(comment::creator_id.eq(person_alias_1.field(person::id))))
83 comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)),
86 community_person_ban::table.on(
88 .eq(community_person_ban::community_id)
89 .and(community_person_ban::person_id.eq(comment::creator_id))
91 community_person_ban::expires
93 .or(community_person_ban::expires.gt(now)),
98 comment_like::table.on(
100 .eq(comment_like::comment_id)
101 .and(comment_like::person_id.eq(my_person_id)),
106 .on(comment_report::resolver_id.eq(person_alias_2.field(person::id).nullable())),
109 comment_report::all_columns,
110 comment::all_columns,
112 Community::safe_columns_tuple(),
113 Person::safe_columns_tuple(),
114 person_alias_1.fields(Person::safe_columns_tuple()),
115 comment_aggregates::all_columns,
116 community_person_ban::all_columns.nullable(),
117 comment_like::score.nullable(),
119 .fields(Person::safe_columns_tuple())
122 .first::<CommentReportViewTuple>(conn)
125 let my_vote = comment_like;
135 creator_banned_from_community: creator_banned_from_community.is_some(),
141 /// Returns the current unresolved post report count for the communities you mod
142 pub async fn get_report_count(
144 my_person_id: PersonId,
146 community_id: Option<CommunityId>,
147 ) -> Result<i64, Error> {
150 let conn = &mut get_conn(pool).await?;
152 let mut query = comment_report::table
153 .inner_join(comment::table)
154 .inner_join(post::table.on(comment::post_id.eq(post::id)))
155 .filter(comment_report::resolved.eq(false))
158 if let Some(community_id) = community_id {
159 query = query.filter(post::community_id.eq(community_id))
162 // If its not an admin, get only the ones you mod
166 community_moderator::table.on(
167 community_moderator::community_id
168 .eq(post::community_id)
169 .and(community_moderator::person_id.eq(my_person_id)),
172 .select(count(comment_report::id))
177 .select(count(comment_report::id))
184 #[derive(TypedBuilder)]
185 #[builder(field_defaults(default))]
186 pub struct CommentReportQuery<'a> {
190 my_person_id: PersonId,
193 community_id: Option<CommunityId>,
196 unresolved_only: Option<bool>,
199 impl<'a> CommentReportQuery<'a> {
200 pub async fn list(self) -> Result<Vec<CommentReportView>, Error> {
201 let conn = &mut get_conn(self.pool).await?;
203 let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
205 let mut query = comment_report::table
206 .inner_join(comment::table)
207 .inner_join(post::table.on(comment::post_id.eq(post::id)))
208 .inner_join(community::table.on(post::community_id.eq(community::id)))
209 .inner_join(person::table.on(comment_report::creator_id.eq(person::id)))
210 .inner_join(person_alias_1.on(comment::creator_id.eq(person_alias_1.field(person::id))))
212 comment_aggregates::table.on(comment_report::comment_id.eq(comment_aggregates::comment_id)),
215 community_person_ban::table.on(
217 .eq(community_person_ban::community_id)
218 .and(community_person_ban::person_id.eq(comment::creator_id))
220 community_person_ban::expires
222 .or(community_person_ban::expires.gt(now)),
227 comment_like::table.on(
229 .eq(comment_like::comment_id)
230 .and(comment_like::person_id.eq(self.my_person_id)),
235 .on(comment_report::resolver_id.eq(person_alias_2.field(person::id).nullable())),
238 comment_report::all_columns,
239 comment::all_columns,
241 Community::safe_columns_tuple(),
242 Person::safe_columns_tuple(),
243 person_alias_1.fields(Person::safe_columns_tuple()),
244 comment_aggregates::all_columns,
245 community_person_ban::all_columns.nullable(),
246 comment_like::score.nullable(),
248 .fields(Person::safe_columns_tuple())
253 if let Some(community_id) = self.community_id {
254 query = query.filter(post::community_id.eq(community_id));
257 if self.unresolved_only.unwrap_or(true) {
258 query = query.filter(comment_report::resolved.eq(false));
261 let (limit, offset) = limit_and_offset(self.page, self.limit)?;
264 .order_by(comment_report::published.desc())
268 // If its not an admin, get only the ones you mod
269 let res = if !self.admin {
272 community_moderator::table.on(
273 community_moderator::community_id
274 .eq(post::community_id)
275 .and(community_moderator::person_id.eq(self.my_person_id)),
278 .load::<CommentReportViewTuple>(conn)
281 query.load::<CommentReportViewTuple>(conn).await?
284 Ok(CommentReportView::from_tuple_to_vec(res))
288 impl ViewToVec for CommentReportView {
289 type DbTuple = CommentReportViewTuple;
290 fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
299 comment_creator: a.5,
301 creator_banned_from_community: a.7.is_some(),
305 .collect::<Vec<Self>>()
311 use crate::comment_report_view::{CommentReportQuery, CommentReportView};
312 use lemmy_db_schema::{
313 aggregates::structs::CommentAggregates,
314 source::{comment::*, comment_report::*, community::*, instance::Instance, person::*, post::*},
315 traits::{Crud, Joinable, Reportable},
316 utils::build_db_pool_for_tests,
318 use serial_test::serial;
322 async fn test_crud() {
323 let pool = &build_db_pool_for_tests().await;
325 let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
327 let new_person = PersonInsertForm::builder()
328 .name("timmy_crv".into())
329 .public_key("pubkey".to_string())
330 .instance_id(inserted_instance.id)
333 let inserted_timmy = Person::create(pool, &new_person).await.unwrap();
335 let new_person_2 = PersonInsertForm::builder()
336 .name("sara_crv".into())
337 .public_key("pubkey".to_string())
338 .instance_id(inserted_instance.id)
341 let inserted_sara = Person::create(pool, &new_person_2).await.unwrap();
343 // Add a third person, since new ppl can only report something once.
344 let new_person_3 = PersonInsertForm::builder()
345 .name("jessica_crv".into())
346 .public_key("pubkey".to_string())
347 .instance_id(inserted_instance.id)
350 let inserted_jessica = Person::create(pool, &new_person_3).await.unwrap();
352 let new_community = CommunityInsertForm::builder()
353 .name("test community crv".to_string())
354 .title("nada".to_owned())
355 .public_key("pubkey".to_string())
356 .instance_id(inserted_instance.id)
359 let inserted_community = Community::create(pool, &new_community).await.unwrap();
362 let timmy_moderator_form = CommunityModeratorForm {
363 community_id: inserted_community.id,
364 person_id: inserted_timmy.id,
367 let _inserted_moderator = CommunityModerator::join(pool, &timmy_moderator_form)
371 let new_post = PostInsertForm::builder()
372 .name("A test post crv".into())
373 .creator_id(inserted_timmy.id)
374 .community_id(inserted_community.id)
377 let inserted_post = Post::create(pool, &new_post).await.unwrap();
379 let comment_form = CommentInsertForm::builder()
380 .content("A test comment 32".into())
381 .creator_id(inserted_timmy.id)
382 .post_id(inserted_post.id)
385 let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
388 let sara_report_form = CommentReportForm {
389 creator_id: inserted_sara.id,
390 comment_id: inserted_comment.id,
391 original_comment_text: "this was it at time of creation".into(),
392 reason: "from sara".into(),
395 let inserted_sara_report = CommentReport::report(pool, &sara_report_form)
400 let jessica_report_form = CommentReportForm {
401 creator_id: inserted_jessica.id,
402 comment_id: inserted_comment.id,
403 original_comment_text: "this was it at time of creation".into(),
404 reason: "from jessica".into(),
407 let inserted_jessica_report = CommentReport::report(pool, &jessica_report_form)
411 let agg = CommentAggregates::read(pool, inserted_comment.id)
415 let read_jessica_report_view =
416 CommentReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
419 let expected_jessica_report_view = CommentReportView {
420 comment_report: inserted_jessica_report.to_owned(),
421 comment: inserted_comment.to_owned(),
423 community: CommunitySafe {
424 id: inserted_community.id,
425 name: inserted_community.name,
430 actor_id: inserted_community.actor_id.to_owned(),
432 title: inserted_community.title,
437 posting_restricted_to_mods: false,
438 published: inserted_community.published,
439 instance_id: inserted_instance.id,
441 creator: PersonSafe {
442 id: inserted_jessica.id,
443 name: inserted_jessica.name,
445 published: inserted_jessica.published,
447 actor_id: inserted_jessica.actor_id.to_owned(),
456 inbox_url: inserted_jessica.inbox_url.to_owned(),
457 shared_inbox_url: None,
458 matrix_user_id: None,
460 instance_id: inserted_instance.id,
462 comment_creator: PersonSafe {
463 id: inserted_timmy.id,
464 name: inserted_timmy.name.to_owned(),
466 published: inserted_timmy.published,
468 actor_id: inserted_timmy.actor_id.to_owned(),
477 inbox_url: inserted_timmy.inbox_url.to_owned(),
478 shared_inbox_url: None,
479 matrix_user_id: None,
481 instance_id: inserted_instance.id,
483 creator_banned_from_community: false,
484 counts: CommentAggregates {
486 comment_id: inserted_comment.id,
490 published: agg.published,
497 assert_eq!(read_jessica_report_view, expected_jessica_report_view);
499 let mut expected_sara_report_view = expected_jessica_report_view.clone();
500 expected_sara_report_view.comment_report = inserted_sara_report;
501 expected_sara_report_view.creator = PersonSafe {
502 id: inserted_sara.id,
503 name: inserted_sara.name,
505 published: inserted_sara.published,
507 actor_id: inserted_sara.actor_id.to_owned(),
516 inbox_url: inserted_sara.inbox_url.to_owned(),
517 shared_inbox_url: None,
518 matrix_user_id: None,
520 instance_id: inserted_instance.id,
523 // Do a batch read of timmys reports
524 let reports = CommentReportQuery::builder()
526 .my_person_id(inserted_timmy.id)
536 expected_jessica_report_view.to_owned(),
537 expected_sara_report_view.to_owned()
541 // Make sure the counts are correct
542 let report_count = CommentReportView::get_report_count(pool, inserted_timmy.id, false, None)
545 assert_eq!(2, report_count);
547 // Try to resolve the report
548 CommentReport::resolve(pool, inserted_jessica_report.id, inserted_timmy.id)
551 let read_jessica_report_view_after_resolve =
552 CommentReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
556 let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
557 expected_jessica_report_view_after_resolve
560 expected_jessica_report_view_after_resolve
562 .resolver_id = Some(inserted_timmy.id);
563 expected_jessica_report_view_after_resolve
565 .updated = read_jessica_report_view_after_resolve
568 expected_jessica_report_view_after_resolve.resolver = Some(PersonSafe {
569 id: inserted_timmy.id,
570 name: inserted_timmy.name.to_owned(),
572 published: inserted_timmy.published,
574 actor_id: inserted_timmy.actor_id.to_owned(),
583 inbox_url: inserted_timmy.inbox_url.to_owned(),
584 shared_inbox_url: None,
585 matrix_user_id: None,
587 instance_id: inserted_instance.id,
591 read_jessica_report_view_after_resolve,
592 expected_jessica_report_view_after_resolve
595 // Do a batch read of timmys reports
596 // It should only show saras, which is unresolved
597 let reports_after_resolve = CommentReportQuery::builder()
599 .my_person_id(inserted_timmy.id)
605 assert_eq!(reports_after_resolve[0], expected_sara_report_view);
606 assert_eq!(reports_after_resolve.len(), 1);
608 // Make sure the counts are correct
609 let report_count_after_resolved =
610 CommentReportView::get_report_count(pool, inserted_timmy.id, false, None)
613 assert_eq!(1, report_count_after_resolved);
615 Person::delete(pool, inserted_timmy.id).await.unwrap();
616 Person::delete(pool, inserted_sara.id).await.unwrap();
617 Person::delete(pool, inserted_jessica.id).await.unwrap();
618 Community::delete(pool, inserted_community.id)
621 Instance::delete(pool, inserted_instance.id).await.unwrap();