]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/report.rs
67b84644e6b473078d7833823cdcb4780828178c
[lemmy.git] / crates / apub / src / activities / community / report.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity, verify_person_in_community},
3   insert_received_activity,
4   objects::{community::ApubCommunity, person::ApubPerson},
5   protocol::{activities::community::report::Report, InCommunity},
6   PostOrComment,
7   SendActivity,
8 };
9 use activitypub_federation::{
10   config::Data,
11   fetch::object_id::ObjectId,
12   kinds::activity::FlagType,
13   traits::{ActivityHandler, Actor},
14 };
15 use lemmy_api_common::{
16   comment::{CommentReportResponse, CreateCommentReport},
17   context::LemmyContext,
18   post::{CreatePostReport, PostReportResponse},
19   utils::local_user_view_from_jwt,
20 };
21 use lemmy_db_schema::{
22   source::{
23     comment_report::{CommentReport, CommentReportForm},
24     post_report::{PostReport, PostReportForm},
25   },
26   traits::Reportable,
27 };
28 use lemmy_utils::error::LemmyError;
29 use url::Url;
30
31 #[async_trait::async_trait]
32 impl SendActivity for CreatePostReport {
33   type Response = PostReportResponse;
34
35   async fn send_activity(
36     request: &Self,
37     response: &Self::Response,
38     context: &Data<LemmyContext>,
39   ) -> Result<(), LemmyError> {
40     let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
41     Report::send(
42       ObjectId::from(response.post_report_view.post.ap_id.clone()),
43       &local_user_view.person.into(),
44       ObjectId::from(response.post_report_view.community.actor_id.clone()),
45       request.reason.to_string(),
46       context,
47     )
48     .await
49   }
50 }
51
52 #[async_trait::async_trait]
53 impl SendActivity for CreateCommentReport {
54   type Response = CommentReportResponse;
55
56   async fn send_activity(
57     request: &Self,
58     response: &Self::Response,
59     context: &Data<LemmyContext>,
60   ) -> Result<(), LemmyError> {
61     let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
62     Report::send(
63       ObjectId::from(response.comment_report_view.comment.ap_id.clone()),
64       &local_user_view.person.into(),
65       ObjectId::from(response.comment_report_view.community.actor_id.clone()),
66       request.reason.to_string(),
67       context,
68     )
69     .await
70   }
71 }
72
73 impl Report {
74   #[tracing::instrument(skip_all)]
75   async fn send(
76     object_id: ObjectId<PostOrComment>,
77     actor: &ApubPerson,
78     community_id: ObjectId<ApubCommunity>,
79     reason: String,
80     context: &Data<LemmyContext>,
81   ) -> Result<(), LemmyError> {
82     let community = community_id.dereference_local(context).await?;
83     let kind = FlagType::Flag;
84     let id = generate_activity_id(
85       kind.clone(),
86       &context.settings().get_protocol_and_hostname(),
87     )?;
88     let report = Report {
89       actor: actor.id().into(),
90       to: [community.id().into()],
91       object: object_id,
92       summary: reason,
93       kind,
94       id: id.clone(),
95       audience: Some(community.id().into()),
96     };
97
98     let inbox = vec![community.shared_inbox_or_inbox()];
99     send_lemmy_activity(context, report, actor, inbox, false).await
100   }
101 }
102
103 #[async_trait::async_trait]
104 impl ActivityHandler for Report {
105   type DataType = LemmyContext;
106   type Error = LemmyError;
107
108   fn id(&self) -> &Url {
109     &self.id
110   }
111
112   fn actor(&self) -> &Url {
113     self.actor.inner()
114   }
115
116   #[tracing::instrument(skip_all)]
117   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
118     insert_received_activity(&self.id, context).await?;
119     let community = self.community(context).await?;
120     verify_person_in_community(&self.actor, &community, context).await?;
121     Ok(())
122   }
123
124   #[tracing::instrument(skip_all)]
125   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
126     let actor = self.actor.dereference(context).await?;
127     match self.object.dereference(context).await? {
128       PostOrComment::Post(post) => {
129         let report_form = PostReportForm {
130           creator_id: actor.id,
131           post_id: post.id,
132           original_post_name: post.name.clone(),
133           original_post_url: post.url.clone(),
134           reason: self.summary,
135           original_post_body: post.body.clone(),
136         };
137         PostReport::report(&mut context.pool(), &report_form).await?;
138       }
139       PostOrComment::Comment(comment) => {
140         let report_form = CommentReportForm {
141           creator_id: actor.id,
142           comment_id: comment.id,
143           original_comment_text: comment.content.clone(),
144           reason: self.summary,
145         };
146         CommentReport::report(&mut context.pool(), &report_form).await?;
147       }
148     };
149     Ok(())
150   }
151 }