1 use crate::structs::PostReportView;
8 NullableExpressionMethods,
11 use diesel_async::RunQueryDsl;
12 use lemmy_db_schema::{
13 aggregates::structs::PostAggregates,
15 newtypes::{CommunityId, PersonId, PostReportId},
26 source::{community::Community, person::Person, post::Post, post_report::PostReport},
28 utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn},
31 type PostReportViewTuple = (
43 fn queries<'a>() -> Queries<
44 impl ReadFn<'a, PostReportView, (PostReportId, PersonId)>,
45 impl ListFn<'a, PostReportView, (PostReportQuery, &'a Person)>,
47 let all_joins = |query: post_report::BoxedQuery<'a, Pg>, my_person_id: PersonId| {
49 .inner_join(post::table)
50 .inner_join(community::table.on(post::community_id.eq(community::id)))
51 .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
52 .inner_join(aliases::person1.on(post::creator_id.eq(aliases::person1.field(person::id))))
54 community_person_ban::table.on(
56 .eq(community_person_ban::community_id)
57 .and(community_person_ban::person_id.eq(post::creator_id)),
63 .eq(post_like::post_id)
64 .and(post_like::person_id.eq(my_person_id)),
67 .inner_join(post_aggregates::table.on(post_report::post_id.eq(post_aggregates::post_id)))
70 .on(post_report::resolver_id.eq(aliases::person2.field(person::id).nullable())),
73 post_report::all_columns,
75 community::all_columns,
77 aliases::person1.fields(person::all_columns),
78 community_person_ban::id.nullable().is_not_null(),
79 post_like::score.nullable(),
80 post_aggregates::all_columns,
81 aliases::person2.fields(person::all_columns.nullable()),
85 let read = move |mut conn: DbConn<'a>, (report_id, my_person_id): (PostReportId, PersonId)| async move {
87 post_report::table.find(report_id).into_boxed(),
90 .first::<PostReportViewTuple>(&mut conn)
94 let list = move |mut conn: DbConn<'a>, (options, my_person): (PostReportQuery, &'a Person)| async move {
95 let mut query = all_joins(post_report::table.into_boxed(), my_person.id);
97 if let Some(community_id) = options.community_id {
98 query = query.filter(post::community_id.eq(community_id));
101 if options.unresolved_only.unwrap_or(false) {
102 query = query.filter(post_report::resolved.eq(false));
105 let (limit, offset) = limit_and_offset(options.page, options.limit)?;
108 .order_by(post_report::published.desc())
112 // If its not an admin, get only the ones you mod
113 if !my_person.admin {
116 community_moderator::table.on(
117 community_moderator::community_id
118 .eq(post::community_id)
119 .and(community_moderator::person_id.eq(my_person.id)),
122 .load::<PostReportViewTuple>(&mut conn)
125 query.load::<PostReportViewTuple>(&mut conn).await
129 Queries::new(read, list)
132 impl PostReportView {
133 /// returns the PostReportView for the provided report_id
135 /// * `report_id` - the report id to obtain
137 pool: &mut DbPool<'_>,
138 report_id: PostReportId,
139 my_person_id: PersonId,
140 ) -> Result<Self, Error> {
141 queries().read(pool, (report_id, my_person_id)).await
144 /// returns the current unresolved post report count for the communities you mod
145 pub async fn get_report_count(
146 pool: &mut DbPool<'_>,
147 my_person_id: PersonId,
149 community_id: Option<CommunityId>,
150 ) -> Result<i64, Error> {
151 use diesel::dsl::count;
152 let conn = &mut get_conn(pool).await?;
153 let mut query = post_report::table
154 .inner_join(post::table)
155 .filter(post_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(post_report::id))
177 .select(count(post_report::id))
185 pub struct PostReportQuery {
186 pub community_id: Option<CommunityId>,
187 pub page: Option<i64>,
188 pub limit: Option<i64>,
189 pub unresolved_only: Option<bool>,
192 impl PostReportQuery {
195 pool: &mut DbPool<'_>,
197 ) -> Result<Vec<PostReportView>, Error> {
198 queries().list(pool, (self, my_person)).await
202 impl JoinView for PostReportView {
203 type JoinTuple = PostReportViewTuple;
204 fn from_tuple(a: Self::JoinTuple) -> Self {
211 creator_banned_from_community: a.5,
221 #![allow(clippy::unwrap_used)]
222 #![allow(clippy::indexing_slicing)]
224 use crate::post_report_view::{PostReportQuery, PostReportView};
225 use lemmy_db_schema::{
226 aggregates::structs::PostAggregates,
228 community::{Community, CommunityInsertForm, CommunityModerator, CommunityModeratorForm},
230 person::{Person, PersonInsertForm},
231 post::{Post, PostInsertForm},
232 post_report::{PostReport, PostReportForm},
234 traits::{Crud, Joinable, Reportable},
235 utils::build_db_pool_for_tests,
237 use serial_test::serial;
241 async fn test_crud() {
242 let pool = &build_db_pool_for_tests().await;
243 let pool = &mut pool.into();
245 let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
249 let new_person = PersonInsertForm::builder()
250 .name("timmy_prv".into())
251 .public_key("pubkey".to_string())
252 .instance_id(inserted_instance.id)
255 let inserted_timmy = Person::create(pool, &new_person).await.unwrap();
257 let new_person_2 = PersonInsertForm::builder()
258 .name("sara_prv".into())
259 .public_key("pubkey".to_string())
260 .instance_id(inserted_instance.id)
263 let inserted_sara = Person::create(pool, &new_person_2).await.unwrap();
265 // Add a third person, since new ppl can only report something once.
266 let new_person_3 = PersonInsertForm::builder()
267 .name("jessica_prv".into())
268 .public_key("pubkey".to_string())
269 .instance_id(inserted_instance.id)
272 let inserted_jessica = Person::create(pool, &new_person_3).await.unwrap();
274 let new_community = CommunityInsertForm::builder()
275 .name("test community prv".to_string())
276 .title("nada".to_owned())
277 .public_key("pubkey".to_string())
278 .instance_id(inserted_instance.id)
281 let inserted_community = Community::create(pool, &new_community).await.unwrap();
284 let timmy_moderator_form = CommunityModeratorForm {
285 community_id: inserted_community.id,
286 person_id: inserted_timmy.id,
289 let _inserted_moderator = CommunityModerator::join(pool, &timmy_moderator_form)
293 let new_post = PostInsertForm::builder()
294 .name("A test post crv".into())
295 .creator_id(inserted_timmy.id)
296 .community_id(inserted_community.id)
299 let inserted_post = Post::create(pool, &new_post).await.unwrap();
302 let sara_report_form = PostReportForm {
303 creator_id: inserted_sara.id,
304 post_id: inserted_post.id,
305 original_post_name: "Orig post".into(),
306 original_post_url: None,
307 original_post_body: None,
308 reason: "from sara".into(),
311 let inserted_sara_report = PostReport::report(pool, &sara_report_form).await.unwrap();
314 let jessica_report_form = PostReportForm {
315 creator_id: inserted_jessica.id,
316 post_id: inserted_post.id,
317 original_post_name: "Orig post".into(),
318 original_post_url: None,
319 original_post_body: None,
320 reason: "from jessica".into(),
323 let inserted_jessica_report = PostReport::report(pool, &jessica_report_form)
327 let agg = PostAggregates::read(pool, inserted_post.id).await.unwrap();
329 let read_jessica_report_view =
330 PostReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
333 let expected_jessica_report_view = PostReportView {
334 post_report: inserted_jessica_report.clone(),
335 post: inserted_post.clone(),
336 community: Community {
337 id: inserted_community.id,
338 name: inserted_community.name,
343 actor_id: inserted_community.actor_id.clone(),
345 title: inserted_community.title,
350 posting_restricted_to_mods: false,
351 published: inserted_community.published,
352 instance_id: inserted_instance.id,
353 private_key: inserted_community.private_key.clone(),
354 public_key: inserted_community.public_key.clone(),
355 last_refreshed_at: inserted_community.last_refreshed_at,
356 followers_url: inserted_community.followers_url.clone(),
357 inbox_url: inserted_community.inbox_url.clone(),
358 shared_inbox_url: inserted_community.shared_inbox_url.clone(),
359 moderators_url: inserted_community.moderators_url.clone(),
360 featured_url: inserted_community.featured_url.clone(),
363 id: inserted_jessica.id,
364 name: inserted_jessica.name,
366 published: inserted_jessica.published,
368 actor_id: inserted_jessica.actor_id.clone(),
377 inbox_url: inserted_jessica.inbox_url.clone(),
378 shared_inbox_url: None,
379 matrix_user_id: None,
381 instance_id: inserted_instance.id,
382 private_key: inserted_jessica.private_key,
383 public_key: inserted_jessica.public_key,
384 last_refreshed_at: inserted_jessica.last_refreshed_at,
386 post_creator: Person {
387 id: inserted_timmy.id,
388 name: inserted_timmy.name.clone(),
390 published: inserted_timmy.published,
392 actor_id: inserted_timmy.actor_id.clone(),
401 inbox_url: inserted_timmy.inbox_url.clone(),
402 shared_inbox_url: None,
403 matrix_user_id: None,
405 instance_id: inserted_instance.id,
406 private_key: inserted_timmy.private_key.clone(),
407 public_key: inserted_timmy.public_key.clone(),
408 last_refreshed_at: inserted_timmy.last_refreshed_at,
410 creator_banned_from_community: false,
412 counts: PostAggregates {
414 post_id: inserted_post.id,
419 published: agg.published,
420 newest_comment_time_necro: inserted_post.published,
421 newest_comment_time: inserted_post.published,
422 featured_community: false,
423 featured_local: false,
425 hot_rank_active: 1728,
426 controversy_rank: 0.0,
427 community_id: inserted_post.community_id,
428 creator_id: inserted_post.creator_id,
433 assert_eq!(read_jessica_report_view, expected_jessica_report_view);
435 let mut expected_sara_report_view = expected_jessica_report_view.clone();
436 expected_sara_report_view.post_report = inserted_sara_report;
437 expected_sara_report_view.my_vote = None;
438 expected_sara_report_view.creator = Person {
439 id: inserted_sara.id,
440 name: inserted_sara.name,
442 published: inserted_sara.published,
444 actor_id: inserted_sara.actor_id.clone(),
453 inbox_url: inserted_sara.inbox_url.clone(),
454 shared_inbox_url: None,
455 matrix_user_id: None,
457 instance_id: inserted_instance.id,
458 private_key: inserted_sara.private_key,
459 public_key: inserted_sara.public_key,
460 last_refreshed_at: inserted_sara.last_refreshed_at,
463 // Do a batch read of timmys reports
464 let reports = PostReportQuery::default()
465 .list(pool, &inserted_timmy)
472 expected_jessica_report_view.clone(),
473 expected_sara_report_view.clone()
477 // Make sure the counts are correct
478 let report_count = PostReportView::get_report_count(pool, inserted_timmy.id, false, None)
481 assert_eq!(2, report_count);
483 // Try to resolve the report
484 PostReport::resolve(pool, inserted_jessica_report.id, inserted_timmy.id)
487 let read_jessica_report_view_after_resolve =
488 PostReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
492 let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
493 expected_jessica_report_view_after_resolve
496 expected_jessica_report_view_after_resolve
498 .resolver_id = Some(inserted_timmy.id);
499 expected_jessica_report_view_after_resolve
501 .updated = read_jessica_report_view_after_resolve.post_report.updated;
502 expected_jessica_report_view_after_resolve.resolver = Some(Person {
503 id: inserted_timmy.id,
504 name: inserted_timmy.name.clone(),
506 published: inserted_timmy.published,
508 actor_id: inserted_timmy.actor_id.clone(),
517 inbox_url: inserted_timmy.inbox_url.clone(),
518 shared_inbox_url: None,
519 matrix_user_id: None,
521 instance_id: inserted_instance.id,
522 private_key: inserted_timmy.private_key.clone(),
523 public_key: inserted_timmy.public_key.clone(),
524 last_refreshed_at: inserted_timmy.last_refreshed_at,
528 read_jessica_report_view_after_resolve,
529 expected_jessica_report_view_after_resolve
532 // Do a batch read of timmys reports
533 // It should only show saras, which is unresolved
534 let reports_after_resolve = PostReportQuery {
535 unresolved_only: (Some(true)),
538 .list(pool, &inserted_timmy)
541 assert_eq!(reports_after_resolve[0], expected_sara_report_view);
543 // Make sure the counts are correct
544 let report_count_after_resolved =
545 PostReportView::get_report_count(pool, inserted_timmy.id, false, None)
548 assert_eq!(1, report_count_after_resolved);
550 Person::delete(pool, inserted_timmy.id).await.unwrap();
551 Person::delete(pool, inserted_sara.id).await.unwrap();
552 Person::delete(pool, inserted_jessica.id).await.unwrap();
553 Community::delete(pool, inserted_community.id)
556 Instance::delete(pool, inserted_instance.id).await.unwrap();