]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/post_report.rs
Automatically resolve report when post/comment is removed (#3850)
[lemmy.git] / crates / db_schema / src / impls / post_report.rs
1 use crate::{
2   newtypes::{PersonId, PostId, PostReportId},
3   schema::post_report::{
4     dsl::{post_report, resolved, resolver_id, updated},
5     post_id,
6   },
7   source::post_report::{PostReport, PostReportForm},
8   traits::Reportable,
9   utils::{get_conn, naive_now, DbPool},
10 };
11 use diesel::{
12   dsl::{insert_into, update},
13   result::Error,
14   ExpressionMethods,
15   QueryDsl,
16 };
17 use diesel_async::RunQueryDsl;
18
19 #[async_trait]
20 impl Reportable for PostReport {
21   type Form = PostReportForm;
22   type IdType = PostReportId;
23   type ObjectIdType = PostId;
24
25   async fn report(pool: &mut DbPool<'_>, post_report_form: &PostReportForm) -> Result<Self, Error> {
26     let conn = &mut get_conn(pool).await?;
27     insert_into(post_report)
28       .values(post_report_form)
29       .get_result::<Self>(conn)
30       .await
31   }
32
33   async fn resolve(
34     pool: &mut DbPool<'_>,
35     report_id: Self::IdType,
36     by_resolver_id: PersonId,
37   ) -> Result<usize, Error> {
38     let conn = &mut get_conn(pool).await?;
39     update(post_report.find(report_id))
40       .set((
41         resolved.eq(true),
42         resolver_id.eq(by_resolver_id),
43         updated.eq(naive_now()),
44       ))
45       .execute(conn)
46       .await
47   }
48
49   async fn resolve_all_for_object(
50     pool: &mut DbPool<'_>,
51     post_id_: PostId,
52     by_resolver_id: PersonId,
53   ) -> Result<usize, Error> {
54     let conn = &mut get_conn(pool).await?;
55     update(post_report.filter(post_id.eq(post_id_)))
56       .set((
57         resolved.eq(true),
58         resolver_id.eq(by_resolver_id),
59         updated.eq(naive_now()),
60       ))
61       .execute(conn)
62       .await
63   }
64
65   async fn unresolve(
66     pool: &mut DbPool<'_>,
67     report_id: Self::IdType,
68     by_resolver_id: PersonId,
69   ) -> Result<usize, Error> {
70     let conn = &mut get_conn(pool).await?;
71     update(post_report.find(report_id))
72       .set((
73         resolved.eq(false),
74         resolver_id.eq(by_resolver_id),
75         updated.eq(naive_now()),
76       ))
77       .execute(conn)
78       .await
79   }
80 }
81
82 #[cfg(test)]
83 mod tests {
84   #![allow(clippy::unwrap_used)]
85   #![allow(clippy::indexing_slicing)]
86
87   use super::*;
88   use crate::{
89     source::{
90       community::{Community, CommunityInsertForm},
91       instance::Instance,
92       person::{Person, PersonInsertForm},
93       post::{Post, PostInsertForm},
94     },
95     traits::Crud,
96     utils::build_db_pool_for_tests,
97   };
98   use serial_test::serial;
99
100   async fn init(pool: &mut DbPool<'_>) -> (Person, PostReport) {
101     let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
102       .await
103       .unwrap();
104     let person_form = PersonInsertForm::builder()
105       .name("jim".into())
106       .public_key("pubkey".to_string())
107       .instance_id(inserted_instance.id)
108       .build();
109     let person = Person::create(pool, &person_form).await.unwrap();
110
111     let community_form = CommunityInsertForm::builder()
112       .name("test community_4".to_string())
113       .title("nada".to_owned())
114       .public_key("pubkey".to_string())
115       .instance_id(inserted_instance.id)
116       .build();
117     let community = Community::create(pool, &community_form).await.unwrap();
118
119     let form = PostInsertForm::builder()
120       .name("A test post".into())
121       .creator_id(person.id)
122       .community_id(community.id)
123       .build();
124     let post = Post::create(pool, &form).await.unwrap();
125
126     let report_form = PostReportForm {
127       post_id: post.id,
128       creator_id: person.id,
129       reason: "my reason".to_string(),
130       ..Default::default()
131     };
132     let report = PostReport::report(pool, &report_form).await.unwrap();
133     (person, report)
134   }
135
136   #[tokio::test]
137   #[serial]
138   async fn test_resolve_post_report() {
139     let pool = &build_db_pool_for_tests().await;
140     let pool = &mut pool.into();
141
142     let (person, report) = init(pool).await;
143
144     let resolved_count = PostReport::resolve(pool, report.id, person.id)
145       .await
146       .unwrap();
147     assert_eq!(resolved_count, 1);
148
149     let unresolved_count = PostReport::unresolve(pool, report.id, person.id)
150       .await
151       .unwrap();
152     assert_eq!(unresolved_count, 1);
153
154     Person::delete(pool, person.id).await.unwrap();
155     Post::delete(pool, report.post_id).await.unwrap();
156   }
157
158   #[tokio::test]
159   #[serial]
160   async fn test_resolve_all_post_reports() {
161     let pool = &build_db_pool_for_tests().await;
162     let pool = &mut pool.into();
163
164     let (person, report) = init(pool).await;
165
166     let resolved_count = PostReport::resolve_all_for_object(pool, report.post_id, person.id)
167       .await
168       .unwrap();
169     assert_eq!(resolved_count, 1);
170
171     Person::delete(pool, person.id).await.unwrap();
172     Post::delete(pool, report.post_id).await.unwrap();
173   }
174 }