]> Untitled Git - lemmy.git/blob - crates/api/src/post_report.rs
8f5c72afa5e0ec0a1713758231f081434eeeae2c
[lemmy.git] / crates / api / src / post_report.rs
1 use crate::Perform;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   blocking,
5   check_community_ban,
6   get_local_user_view_from_jwt,
7   is_mod_or_admin,
8   post::{
9     CreatePostReport,
10     ListPostReports,
11     ListPostReportsResponse,
12     PostReportResponse,
13     ResolvePostReport,
14   },
15 };
16 use lemmy_db_queries::Reportable;
17 use lemmy_db_schema::source::post_report::{PostReport, PostReportForm};
18 use lemmy_db_views::{
19   post_report_view::{PostReportQueryBuilder, PostReportView},
20   post_view::PostView,
21 };
22 use lemmy_utils::{ApiError, ConnectionId, LemmyError};
23 use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
24
25 /// Creates a post report and notifies the moderators of the community
26 #[async_trait::async_trait(?Send)]
27 impl Perform for CreatePostReport {
28   type Response = PostReportResponse;
29
30   async fn perform(
31     &self,
32     context: &Data<LemmyContext>,
33     websocket_id: Option<ConnectionId>,
34   ) -> Result<PostReportResponse, LemmyError> {
35     let data: &CreatePostReport = self;
36     let local_user_view =
37       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
38
39     // check size of report and check for whitespace
40     let reason = data.reason.trim();
41     if reason.is_empty() {
42       return Err(ApiError::err("report_reason_required").into());
43     }
44     if reason.chars().count() > 1000 {
45       return Err(ApiError::err("report_too_long").into());
46     }
47
48     let person_id = local_user_view.person.id;
49     let post_id = data.post_id;
50     let post_view = blocking(context.pool(), move |conn| {
51       PostView::read(conn, post_id, None)
52     })
53     .await??;
54
55     check_community_ban(person_id, post_view.community.id, context.pool()).await?;
56
57     let report_form = PostReportForm {
58       creator_id: person_id,
59       post_id,
60       original_post_name: post_view.post.name,
61       original_post_url: post_view.post.url,
62       original_post_body: post_view.post.body,
63       reason: data.reason.to_owned(),
64     };
65
66     let report = blocking(context.pool(), move |conn| {
67       PostReport::report(conn, &report_form)
68     })
69     .await?
70     .map_err(|_| ApiError::err("couldnt_create_report"))?;
71
72     let post_report_view = blocking(context.pool(), move |conn| {
73       PostReportView::read(conn, report.id, person_id)
74     })
75     .await??;
76
77     let res = PostReportResponse { post_report_view };
78
79     context.chat_server().do_send(SendModRoomMessage {
80       op: UserOperation::CreatePostReport,
81       response: res.clone(),
82       community_id: post_view.community.id,
83       websocket_id,
84     });
85
86     Ok(res)
87   }
88 }
89
90 /// Resolves or unresolves a post report and notifies the moderators of the community
91 #[async_trait::async_trait(?Send)]
92 impl Perform for ResolvePostReport {
93   type Response = PostReportResponse;
94
95   async fn perform(
96     &self,
97     context: &Data<LemmyContext>,
98     websocket_id: Option<ConnectionId>,
99   ) -> Result<PostReportResponse, LemmyError> {
100     let data: &ResolvePostReport = self;
101     let local_user_view =
102       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
103
104     let report_id = data.report_id;
105     let person_id = local_user_view.person.id;
106     let report = blocking(context.pool(), move |conn| {
107       PostReportView::read(conn, report_id, person_id)
108     })
109     .await??;
110
111     let person_id = local_user_view.person.id;
112     is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
113
114     let resolved = data.resolved;
115     let resolve_fun = move |conn: &'_ _| {
116       if resolved {
117         PostReport::resolve(conn, report_id, person_id)
118       } else {
119         PostReport::unresolve(conn, report_id, person_id)
120       }
121     };
122
123     if blocking(context.pool(), resolve_fun).await?.is_err() {
124       return Err(ApiError::err("couldnt_resolve_report").into());
125     };
126
127     let post_report_view = blocking(context.pool(), move |conn| {
128       PostReportView::read(conn, report_id, person_id)
129     })
130     .await??;
131
132     let res = PostReportResponse { post_report_view };
133
134     context.chat_server().do_send(SendModRoomMessage {
135       op: UserOperation::ResolvePostReport,
136       response: res.clone(),
137       community_id: report.community.id,
138       websocket_id,
139     });
140
141     Ok(res)
142   }
143 }
144
145 /// Lists post reports for a community if an id is supplied
146 /// or returns all post reports for communities a user moderates
147 #[async_trait::async_trait(?Send)]
148 impl Perform for ListPostReports {
149   type Response = ListPostReportsResponse;
150
151   async fn perform(
152     &self,
153     context: &Data<LemmyContext>,
154     _websocket_id: Option<ConnectionId>,
155   ) -> Result<ListPostReportsResponse, LemmyError> {
156     let data: &ListPostReports = self;
157     let local_user_view =
158       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
159
160     let person_id = local_user_view.person.id;
161     let admin = local_user_view.person.admin;
162     let community_id = data.community_id;
163     let unresolved_only = data.unresolved_only;
164
165     let page = data.page;
166     let limit = data.limit;
167     let post_reports = blocking(context.pool(), move |conn| {
168       PostReportQueryBuilder::create(conn, person_id, admin)
169         .community_id(community_id)
170         .unresolved_only(unresolved_only)
171         .page(page)
172         .limit(limit)
173         .list()
174     })
175     .await??;
176
177     let res = ListPostReportsResponse { post_reports };
178
179     Ok(res)
180   }
181 }