]> Untitled Git - lemmy.git/blob - lemmy_apub/src/inbox/activities/delete.rs
Fix nginx config for local federation setup (#104)
[lemmy.git] / lemmy_apub / src / inbox / activities / delete.rs
1 use crate::{
2   fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
3   inbox::shared_inbox::{
4     announce_if_community_is_local,
5     get_user_from_activity,
6     receive_unhandled_activity,
7   },
8   ActorType,
9   FromApub,
10   GroupExt,
11   PageExt,
12 };
13 use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*};
14 use actix_web::HttpResponse;
15 use anyhow::Context;
16 use lemmy_db::{
17   comment::{Comment, CommentForm},
18   comment_view::CommentView,
19   community::{Community, CommunityForm},
20   community_view::CommunityView,
21   naive_now,
22   post::{Post, PostForm},
23   post_view::PostView,
24   Crud,
25 };
26 use lemmy_structs::{
27   blocking,
28   comment::CommentResponse,
29   community::CommunityResponse,
30   post::PostResponse,
31 };
32 use lemmy_utils::{location_info, LemmyError};
33 use lemmy_websocket::{
34   messages::{SendComment, SendCommunityRoomMessage, SendPost},
35   LemmyContext,
36   UserOperation,
37 };
38
39 pub async fn receive_delete(
40   activity: AnyBase,
41   context: &LemmyContext,
42 ) -> Result<HttpResponse, LemmyError> {
43   let delete = Delete::from_any_base(activity)?.context(location_info!())?;
44   match delete.object().as_single_kind_str() {
45     Some("Page") => receive_delete_post(delete, context).await,
46     Some("Note") => receive_delete_comment(delete, context).await,
47     Some("Group") => receive_delete_community(delete, context).await,
48     _ => receive_unhandled_activity(delete),
49   }
50 }
51
52 async fn receive_delete_post(
53   delete: Delete,
54   context: &LemmyContext,
55 ) -> Result<HttpResponse, LemmyError> {
56   let user = get_user_from_activity(&delete, context).await?;
57   let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
58     .context(location_info!())?;
59
60   let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?))
61     .await?
62     .get_ap_id()?;
63
64   let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?;
65
66   let post_form = PostForm {
67     name: post.name.to_owned(),
68     url: post.url.to_owned(),
69     body: post.body.to_owned(),
70     creator_id: post.creator_id.to_owned(),
71     community_id: post.community_id,
72     removed: None,
73     deleted: Some(true),
74     nsfw: post.nsfw,
75     locked: None,
76     stickied: None,
77     updated: Some(naive_now()),
78     embed_title: post.embed_title,
79     embed_description: post.embed_description,
80     embed_html: post.embed_html,
81     thumbnail_url: post.thumbnail_url,
82     ap_id: Some(post.ap_id),
83     local: post.local,
84     published: None,
85   };
86   let post_id = post.id;
87   blocking(context.pool(), move |conn| {
88     Post::update(conn, post_id, &post_form)
89   })
90   .await??;
91
92   // Refetch the view
93   let post_id = post.id;
94   let post_view = blocking(context.pool(), move |conn| {
95     PostView::read(conn, post_id, None)
96   })
97   .await??;
98
99   let res = PostResponse { post: post_view };
100
101   context.chat_server().do_send(SendPost {
102     op: UserOperation::EditPost,
103     post: res,
104     websocket_id: None,
105   });
106
107   announce_if_community_is_local(delete, &user, context).await?;
108   Ok(HttpResponse::Ok().finish())
109 }
110
111 async fn receive_delete_comment(
112   delete: Delete,
113   context: &LemmyContext,
114 ) -> Result<HttpResponse, LemmyError> {
115   let user = get_user_from_activity(&delete, context).await?;
116   let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
117     .context(location_info!())?;
118
119   let comment_ap_id = CommentForm::from_apub(&note, context, Some(user.actor_id()?))
120     .await?
121     .get_ap_id()?;
122
123   let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?;
124
125   let comment_form = CommentForm {
126     content: comment.content.to_owned(),
127     parent_id: comment.parent_id,
128     post_id: comment.post_id,
129     creator_id: comment.creator_id,
130     removed: None,
131     deleted: Some(true),
132     read: None,
133     published: None,
134     updated: Some(naive_now()),
135     ap_id: Some(comment.ap_id),
136     local: comment.local,
137   };
138   let comment_id = comment.id;
139   blocking(context.pool(), move |conn| {
140     Comment::update(conn, comment_id, &comment_form)
141   })
142   .await??;
143
144   // Refetch the view
145   let comment_id = comment.id;
146   let comment_view = blocking(context.pool(), move |conn| {
147     CommentView::read(conn, comment_id, None)
148   })
149   .await??;
150
151   // TODO get those recipient actor ids from somewhere
152   let recipient_ids = vec![];
153   let res = CommentResponse {
154     comment: comment_view,
155     recipient_ids,
156     form_id: None,
157   };
158
159   context.chat_server().do_send(SendComment {
160     op: UserOperation::EditComment,
161     comment: res,
162     websocket_id: None,
163   });
164
165   announce_if_community_is_local(delete, &user, context).await?;
166   Ok(HttpResponse::Ok().finish())
167 }
168
169 async fn receive_delete_community(
170   delete: Delete,
171   context: &LemmyContext,
172 ) -> Result<HttpResponse, LemmyError> {
173   let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
174     .context(location_info!())?;
175   let user = get_user_from_activity(&delete, context).await?;
176
177   let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?))
178     .await?
179     .actor_id
180     .context(location_info!())?;
181
182   let community = blocking(context.pool(), move |conn| {
183     Community::read_from_actor_id(conn, &community_actor_id)
184   })
185   .await??;
186
187   let community_form = CommunityForm {
188     name: community.name.to_owned(),
189     title: community.title.to_owned(),
190     description: community.description.to_owned(),
191     category_id: community.category_id, // Note: need to keep this due to foreign key constraint
192     creator_id: community.creator_id,   // Note: need to keep this due to foreign key constraint
193     removed: None,
194     published: None,
195     updated: Some(naive_now()),
196     deleted: Some(true),
197     nsfw: community.nsfw,
198     actor_id: Some(community.actor_id),
199     local: community.local,
200     private_key: community.private_key,
201     public_key: community.public_key,
202     last_refreshed_at: None,
203     icon: Some(community.icon.to_owned()),
204     banner: Some(community.banner.to_owned()),
205   };
206
207   let community_id = community.id;
208   blocking(context.pool(), move |conn| {
209     Community::update(conn, community_id, &community_form)
210   })
211   .await??;
212
213   let community_id = community.id;
214   let res = CommunityResponse {
215     community: blocking(context.pool(), move |conn| {
216       CommunityView::read(conn, community_id, None)
217     })
218     .await??,
219   };
220
221   let community_id = res.community.id;
222
223   context.chat_server().do_send(SendCommunityRoomMessage {
224     op: UserOperation::EditCommunity,
225     response: res,
226     community_id,
227     websocket_id: None,
228   });
229
230   announce_if_community_is_local(delete, &user, context).await?;
231   Ok(HttpResponse::Ok().finish())
232 }