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