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