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