]> Untitled Git - lemmy.git/blob - crates/api/src/comment_report.rs
Rewrite fetcher (#1792)
[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 = blocking(context.pool(), move |conn| {
63       CommentReport::report(conn, &report_form)
64     })
65     .await?
66     .map_err(|_| ApiError::err("couldnt_create_report"))?;
67
68     let res = CreateCommentReportResponse { success: true };
69
70     context.chat_server().do_send(SendUserRoomMessage {
71       op: UserOperation::CreateCommentReport,
72       response: res.clone(),
73       local_recipient_id: local_user_view.local_user.id,
74       websocket_id,
75     });
76
77     context.chat_server().do_send(SendModRoomMessage {
78       op: UserOperation::CreateCommentReport,
79       response: report,
80       community_id: comment_view.community.id,
81       websocket_id,
82     });
83
84     Ok(res)
85   }
86 }
87
88 /// Resolves or unresolves a comment report and notifies the moderators of the community
89 #[async_trait::async_trait(?Send)]
90 impl Perform for ResolveCommentReport {
91   type Response = ResolveCommentReportResponse;
92
93   async fn perform(
94     &self,
95     context: &Data<LemmyContext>,
96     websocket_id: Option<ConnectionId>,
97   ) -> Result<ResolveCommentReportResponse, LemmyError> {
98     let data: &ResolveCommentReport = self;
99     let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
100
101     let report_id = data.report_id;
102     let report = blocking(context.pool(), move |conn| {
103       CommentReportView::read(conn, report_id)
104     })
105     .await??;
106
107     let person_id = local_user_view.person.id;
108     is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
109
110     let resolved = data.resolved;
111     let resolve_fun = move |conn: &'_ _| {
112       if resolved {
113         CommentReport::resolve(conn, report_id, person_id)
114       } else {
115         CommentReport::unresolve(conn, report_id, person_id)
116       }
117     };
118
119     if blocking(context.pool(), resolve_fun).await?.is_err() {
120       return Err(ApiError::err("couldnt_resolve_report").into());
121     };
122
123     let report_id = data.report_id;
124     let res = ResolveCommentReportResponse {
125       report_id,
126       resolved,
127     };
128
129     context.chat_server().do_send(SendModRoomMessage {
130       op: UserOperation::ResolveCommentReport,
131       response: res.clone(),
132       community_id: report.community.id,
133       websocket_id,
134     });
135
136     Ok(res)
137   }
138 }
139
140 /// Lists comment reports for a community if an id is supplied
141 /// or returns all comment reports for communities a user moderates
142 #[async_trait::async_trait(?Send)]
143 impl Perform for ListCommentReports {
144   type Response = ListCommentReportsResponse;
145
146   async fn perform(
147     &self,
148     context: &Data<LemmyContext>,
149     websocket_id: Option<ConnectionId>,
150   ) -> Result<ListCommentReportsResponse, LemmyError> {
151     let data: &ListCommentReports = self;
152     let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
153
154     let person_id = local_user_view.person.id;
155     let community_id = data.community;
156     let community_ids =
157       collect_moderated_communities(person_id, community_id, context.pool()).await?;
158
159     let page = data.page;
160     let limit = data.limit;
161     let comments = blocking(context.pool(), move |conn| {
162       CommentReportQueryBuilder::create(conn)
163         .community_ids(community_ids)
164         .page(page)
165         .limit(limit)
166         .list()
167     })
168     .await??;
169
170     let res = ListCommentReportsResponse { comments };
171
172     context.chat_server().do_send(SendUserRoomMessage {
173       op: UserOperation::ListCommentReports,
174       response: res.clone(),
175       local_recipient_id: local_user_view.local_user.id,
176       websocket_id,
177     });
178
179     Ok(res)
180   }
181 }