diff --git a/lemmy_apub/src/activities/receive/delete.rs b/lemmy_apub/src/activities/receive/delete.rs index a1985881e..579c6e7ea 100644 --- a/lemmy_apub/src/activities/receive/delete.rs +++ b/lemmy_apub/src/activities/receive/delete.rs @@ -1,27 +1,19 @@ -use crate::{ - activities::receive::{ - announce_if_community_is_local, - get_actor_as_user, - receive_unhandled_activity, - }, - fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post}, - ActorType, - FromApub, - GroupExt, - PageExt, +use crate::activities::receive::{ + announce_if_community_is_local, + find_by_id, + get_actor_as_user, + FindResults, }; -use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*}; +use activitystreams::{activity::Delete, base::AnyBase, prelude::*}; use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ - comment::{Comment, CommentForm}, + comment::Comment, comment_view::CommentView, - community::{Community, CommunityForm}, + community::Community, community_view::CommunityView, - naive_now, - post::{Post, PostForm}, + post::Post, post_view::PostView, - Crud, }; use lemmy_structs::{ blocking, @@ -41,108 +33,66 @@ pub async fn receive_delete( context: &LemmyContext, ) -> Result { let delete = Delete::from_any_base(activity)?.context(location_info!())?; - match delete.object().as_single_kind_str() { - Some("Page") => receive_delete_post(delete, context).await, - Some("Note") => receive_delete_comment(delete, context).await, - Some("Group") => receive_delete_community(delete, context).await, - _ => receive_unhandled_activity(delete), + + let object = delete + .object() + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + + // Ensure that delete activity comes from the same domain as the object + delete.id(object.domain().context(location_info!())?)?; + + match find_by_id(context, object).await { + Ok(FindResults::Post(p)) => receive_delete_post(context, delete, p).await, + Ok(FindResults::Comment(c)) => receive_delete_comment(context, delete, c).await, + Ok(FindResults::Community(c)) => receive_delete_community(context, delete, c).await, + // if we dont have the object, no need to do anything + Err(_) => Ok(HttpResponse::Ok().finish()), } } async fn receive_delete_post( - delete: Delete, context: &LemmyContext, + delete: Delete, + post: Post, ) -> Result { - let user = get_actor_as_user(&delete, context).await?; - let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?)) - .await? - .get_ap_id()?; - - let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; - - let post_form = PostForm { - name: post.name.to_owned(), - url: post.url.to_owned(), - body: post.body.to_owned(), - creator_id: post.creator_id.to_owned(), - community_id: post.community_id, - removed: None, - deleted: Some(true), - nsfw: post.nsfw, - locked: None, - stickied: None, - updated: Some(naive_now()), - embed_title: post.embed_title, - embed_description: post.embed_description, - embed_html: post.embed_html, - thumbnail_url: post.thumbnail_url, - ap_id: Some(post.ap_id), - local: post.local, - published: None, - }; - let post_id = post.id; - blocking(context.pool(), move |conn| { - Post::update(conn, post_id, &post_form) + let deleted_post = blocking(context.pool(), move |conn| { + Post::update_deleted(conn, post.id, true) }) .await??; // Refetch the view - let post_id = post.id; + let post_id = deleted_post.id; let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) .await??; let res = PostResponse { post: post_view }; - context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, websocket_id: None, }); + let user = get_actor_as_user(&delete, context).await?; announce_if_community_is_local(delete, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_delete_comment( - delete: Delete, context: &LemmyContext, + delete: Delete, + comment: Comment, ) -> Result { - let user = get_actor_as_user(&delete, context).await?; - let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let comment_ap_id = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)) - .await? - .get_ap_id()?; - - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; - - let comment_form = CommentForm { - content: comment.content.to_owned(), - parent_id: comment.parent_id, - post_id: comment.post_id, - creator_id: comment.creator_id, - removed: None, - deleted: Some(true), - read: None, - published: None, - updated: Some(naive_now()), - ap_id: Some(comment.ap_id), - local: comment.local, - }; - let comment_id = comment.id; - blocking(context.pool(), move |conn| { - Comment::update(conn, comment_id, &comment_form) + let deleted_comment = blocking(context.pool(), move |conn| { + Comment::update_deleted(conn, comment.id, true) }) .await??; // Refetch the view - let comment_id = comment.id; + let comment_id = deleted_comment.id; let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, comment_id, None) }) @@ -155,62 +105,28 @@ async fn receive_delete_comment( recipient_ids, form_id: None, }; - context.chat_server().do_send(SendComment { op: UserOperation::EditComment, comment: res, websocket_id: None, }); + let user = get_actor_as_user(&delete, context).await?; announce_if_community_is_local(delete, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_delete_community( - delete: Delete, context: &LemmyContext, + delete: Delete, + community: Community, ) -> Result { - let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - let user = get_actor_as_user(&delete, context).await?; - - let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?)) - .await? - .actor_id - .context(location_info!())?; - - let community = blocking(context.pool(), move |conn| { - Community::read_from_actor_id(conn, &community_actor_id) + let deleted_community = blocking(context.pool(), move |conn| { + Community::update_deleted(conn, community.id, true) }) .await??; - let community_form = CommunityForm { - name: community.name.to_owned(), - title: community.title.to_owned(), - description: community.description.to_owned(), - category_id: community.category_id, // Note: need to keep this due to foreign key constraint - creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint - removed: None, - published: None, - updated: Some(naive_now()), - deleted: Some(true), - nsfw: community.nsfw, - actor_id: Some(community.actor_id), - local: community.local, - private_key: community.private_key, - public_key: community.public_key, - last_refreshed_at: None, - icon: Some(community.icon.to_owned()), - banner: Some(community.banner.to_owned()), - }; - - let community_id = community.id; - blocking(context.pool(), move |conn| { - Community::update(conn, community_id, &community_form) - }) - .await??; - - let community_id = community.id; + let community_id = deleted_community.id; let res = CommunityResponse { community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) @@ -219,7 +135,6 @@ async fn receive_delete_community( }; let community_id = res.community.id; - context.chat_server().do_send(SendCommunityRoomMessage { op: UserOperation::EditCommunity, response: res, @@ -227,6 +142,7 @@ async fn receive_delete_community( websocket_id: None, }); + let user = get_actor_as_user(&delete, context).await?; announce_if_community_is_local(delete, &user, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/lemmy_apub/src/activities/receive/mod.rs b/lemmy_apub/src/activities/receive/mod.rs index 06c5f291a..730454b4e 100644 --- a/lemmy_apub/src/activities/receive/mod.rs +++ b/lemmy_apub/src/activities/receive/mod.rs @@ -9,7 +9,9 @@ use activitystreams::{ }; use actix_web::HttpResponse; use anyhow::Context; -use lemmy_db::user::User_; +use diesel::result::Error::NotFound; +use lemmy_db::{comment::Comment, community::Community, post::Post, user::User_}; +use lemmy_structs::blocking; use lemmy_utils::{location_info, LemmyError}; use lemmy_websocket::LemmyContext; use log::debug; @@ -68,7 +70,7 @@ where Ok(()) } -pub(in crate) async fn get_actor_as_user( +pub(crate) async fn get_actor_as_user( activity: &T, context: &LemmyContext, ) -> Result @@ -79,3 +81,43 @@ where let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?; get_or_fetch_and_upsert_user(&user_uri, context).await } + +pub(crate) enum FindResults { + Comment(Comment), + Community(Community), + Post(Post), +} + +pub(crate) async fn find_by_id( + context: &LemmyContext, + apub_id: Url, +) -> Result { + let ap_id = apub_id.to_string(); + let community = blocking(context.pool(), move |conn| { + Community::read_from_actor_id(conn, &ap_id) + }) + .await?; + if let Ok(c) = community { + return Ok(FindResults::Community(c)); + } + + let ap_id = apub_id.to_string(); + let post = blocking(context.pool(), move |conn| { + Post::read_from_apub_id(conn, &ap_id) + }) + .await?; + if let Ok(p) = post { + return Ok(FindResults::Post(p)); + } + + let ap_id = apub_id.to_string(); + let comment = blocking(context.pool(), move |conn| { + Comment::read_from_apub_id(conn, &ap_id) + }) + .await?; + if let Ok(c) = comment { + return Ok(FindResults::Comment(c)); + } + + return Err(NotFound.into()); +} diff --git a/lemmy_apub/src/activities/receive/remove.rs b/lemmy_apub/src/activities/receive/remove.rs index dfd166e6c..c9f248d64 100644 --- a/lemmy_apub/src/activities/receive/remove.rs +++ b/lemmy_apub/src/activities/receive/remove.rs @@ -1,27 +1,17 @@ use crate::{ - activities::receive::{ - announce_if_community_is_local, - get_actor_as_user, - receive_unhandled_activity, - }, - fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post}, + activities::receive::{find_by_id, get_actor_as_user, FindResults}, ActorType, - FromApub, - GroupExt, - PageExt, }; -use activitystreams::{activity::Remove, base::AnyBase, object::Note, prelude::*}; +use activitystreams::{activity::Remove, base::AnyBase, error::DomainError, prelude::*}; use actix_web::HttpResponse; -use anyhow::{anyhow, Context}; +use anyhow::Context; use lemmy_db::{ - comment::{Comment, CommentForm}, + comment::Comment, comment_view::CommentView, - community::{Community, CommunityForm}, + community::Community, community_view::CommunityView, - naive_now, - post::{Post, PostForm}, + post::Post, post_view::PostView, - Crud, }; use lemmy_structs::{ blocking, @@ -52,112 +42,69 @@ pub async fn receive_remove( .map(|c| c.as_xsd_any_uri()) .flatten() .context(location_info!())?; + + let object = remove + .object() + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + + // Ensure that remove comes from the same domain as the community if actor.actor_id()?.domain() != community_id.domain() { - return Err(anyhow!("Remove receive are only allowed on local objects").into()); + return Err(DomainError.into()); } - match remove.object().as_single_kind_str() { - Some("Page") => receive_remove_post(remove, context).await, - Some("Note") => receive_remove_comment(remove, context).await, - Some("Group") => receive_remove_community(remove, context).await, - _ => receive_unhandled_activity(remove), + // Ensure that remove activity comes from the same domain as the community + remove.id(community_id.domain().context(location_info!())?)?; + + match find_by_id(context, object).await { + Ok(FindResults::Post(p)) => receive_remove_post(context, remove, p).await, + Ok(FindResults::Comment(c)) => receive_remove_comment(context, remove, c).await, + Ok(FindResults::Community(c)) => receive_remove_community(context, remove, c).await, + // if we dont have the object, no need to do anything + Err(_) => Ok(HttpResponse::Ok().finish()), } } async fn receive_remove_post( - remove: Remove, context: &LemmyContext, + _remove: Remove, + post: Post, ) -> Result { - let mod_ = get_actor_as_user(&remove, context).await?; - let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let post_ap_id = PostForm::from_apub(&page, context, None) - .await? - .get_ap_id()?; - - let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; - - let post_form = PostForm { - name: post.name.to_owned(), - url: post.url.to_owned(), - body: post.body.to_owned(), - creator_id: post.creator_id.to_owned(), - community_id: post.community_id, - removed: Some(true), - deleted: None, - nsfw: post.nsfw, - locked: None, - stickied: None, - updated: Some(naive_now()), - embed_title: post.embed_title, - embed_description: post.embed_description, - embed_html: post.embed_html, - thumbnail_url: post.thumbnail_url, - ap_id: Some(post.ap_id), - local: post.local, - published: None, - }; - let post_id = post.id; - blocking(context.pool(), move |conn| { - Post::update(conn, post_id, &post_form) + let removed_post = blocking(context.pool(), move |conn| { + Post::update_removed(conn, post.id, true) }) .await??; // Refetch the view - let post_id = post.id; + let post_id = removed_post.id; let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) .await??; let res = PostResponse { post: post_view }; - context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, websocket_id: None, }); - announce_if_community_is_local(remove, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_remove_comment( - remove: Remove, context: &LemmyContext, + _remove: Remove, + comment: Comment, ) -> Result { - let mod_ = get_actor_as_user(&remove, context).await?; - let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let comment_ap_id = CommentForm::from_apub(¬e, context, None) - .await? - .get_ap_id()?; - - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; - - let comment_form = CommentForm { - content: comment.content.to_owned(), - parent_id: comment.parent_id, - post_id: comment.post_id, - creator_id: comment.creator_id, - removed: Some(true), - deleted: None, - read: None, - published: None, - updated: Some(naive_now()), - ap_id: Some(comment.ap_id), - local: comment.local, - }; - let comment_id = comment.id; - blocking(context.pool(), move |conn| { - Comment::update(conn, comment_id, &comment_form) + let removed_comment = blocking(context.pool(), move |conn| { + Comment::update_removed(conn, comment.id, true) }) .await??; // Refetch the view - let comment_id = comment.id; + let comment_id = removed_comment.id; let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, comment_id, None) }) @@ -170,62 +117,26 @@ async fn receive_remove_comment( recipient_ids, form_id: None, }; - context.chat_server().do_send(SendComment { op: UserOperation::EditComment, comment: res, websocket_id: None, }); - announce_if_community_is_local(remove, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_remove_community( - remove: Remove, context: &LemmyContext, + _remove: Remove, + community: Community, ) -> Result { - let mod_ = get_actor_as_user(&remove, context).await?; - let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let community_actor_id = CommunityForm::from_apub(&group, context, Some(mod_.actor_id()?)) - .await? - .actor_id - .context(location_info!())?; - - let community = blocking(context.pool(), move |conn| { - Community::read_from_actor_id(conn, &community_actor_id) + let removed_community = blocking(context.pool(), move |conn| { + Community::update_removed(conn, community.id, true) }) .await??; - let community_form = CommunityForm { - name: community.name.to_owned(), - title: community.title.to_owned(), - description: community.description.to_owned(), - category_id: community.category_id, // Note: need to keep this due to foreign key constraint - creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint - removed: Some(true), - published: None, - updated: Some(naive_now()), - deleted: None, - nsfw: community.nsfw, - actor_id: Some(community.actor_id), - local: community.local, - private_key: community.private_key, - public_key: community.public_key, - last_refreshed_at: None, - icon: Some(community.icon.to_owned()), - banner: Some(community.banner.to_owned()), - }; - - let community_id = community.id; - blocking(context.pool(), move |conn| { - Community::update(conn, community_id, &community_form) - }) - .await??; - - let community_id = community.id; + let community_id = removed_community.id; let res = CommunityResponse { community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) @@ -234,7 +145,6 @@ async fn receive_remove_community( }; let community_id = res.community.id; - context.chat_server().do_send(SendCommunityRoomMessage { op: UserOperation::EditCommunity, response: res, @@ -242,6 +152,5 @@ async fn receive_remove_community( websocket_id: None, }); - announce_if_community_is_local(remove, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/lemmy_apub/src/activities/receive/undo.rs b/lemmy_apub/src/activities/receive/undo.rs index 95a739505..9c5dc01a9 100644 --- a/lemmy_apub/src/activities/receive/undo.rs +++ b/lemmy_apub/src/activities/receive/undo.rs @@ -1,14 +1,11 @@ -use crate::{ - activities::receive::{ - announce_if_community_is_local, - get_actor_as_user, - receive_unhandled_activity, - undo_comment::*, - undo_post::*, - }, - ActorType, - FromApub, - GroupExt, +use crate::activities::receive::{ + announce_if_community_is_local, + find_by_id, + get_actor_as_user, + receive_unhandled_activity, + undo_comment::*, + undo_post::*, + FindResults, }; use activitystreams::{ activity::*, @@ -17,12 +14,7 @@ use activitystreams::{ }; use actix_web::HttpResponse; use anyhow::{anyhow, Context}; -use lemmy_db::{ - community::{Community, CommunityForm}, - community_view::CommunityView, - naive_now, - Crud, -}; +use lemmy_db::{community::Community, community_view::CommunityView}; use lemmy_structs::{blocking, community::CommunityResponse}; use lemmy_utils::{location_info, LemmyError}; use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation}; @@ -69,15 +61,18 @@ async fn receive_undo_delete( let delete = Delete::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; check_is_undo_valid(&undo, &delete)?; - let type_ = delete + + let object = delete .object() - .as_single_kind_str() + .to_owned() + .single_xsd_any_uri() .context(location_info!())?; - match type_ { - "Note" => receive_undo_delete_comment(undo, &delete, context).await, - "Page" => receive_undo_delete_post(undo, &delete, context).await, - "Group" => receive_undo_delete_community(undo, &delete, context).await, - d => Err(anyhow!("Undo Delete type {} not supported", d).into()), + match find_by_id(context, object).await { + Ok(FindResults::Post(p)) => receive_undo_delete_post(context, undo, p).await, + Ok(FindResults::Comment(c)) => receive_undo_delete_comment(context, undo, c).await, + Ok(FindResults::Community(c)) => receive_undo_delete_community(context, undo, c).await, + // if we dont have the object, no need to do anything + Err(_) => Ok(HttpResponse::Ok().finish()), } } @@ -89,15 +84,17 @@ async fn receive_undo_remove( .context(location_info!())?; check_is_undo_valid(&undo, &remove)?; - let type_ = remove + let object = remove .object() - .as_single_kind_str() + .to_owned() + .single_xsd_any_uri() .context(location_info!())?; - match type_ { - "Note" => receive_undo_remove_comment(undo, &remove, context).await, - "Page" => receive_undo_remove_post(undo, &remove, context).await, - "Group" => receive_undo_remove_community(undo, &remove, context).await, - d => Err(anyhow!("Undo Delete type {} not supported", d).into()), + match find_by_id(context, object).await { + Ok(FindResults::Post(p)) => receive_undo_remove_post(context, undo, p).await, + Ok(FindResults::Comment(c)) => receive_undo_remove_comment(context, undo, c).await, + Ok(FindResults::Community(c)) => receive_undo_remove_community(context, undo, c).await, + // if we dont have the object, no need to do anything + Err(_) => Ok(HttpResponse::Ok().finish()), } } @@ -137,51 +134,16 @@ async fn receive_undo_dislike( } async fn receive_undo_delete_community( - undo: Undo, - delete: &Delete, context: &LemmyContext, + undo: Undo, + community: Community, ) -> Result { - let user = get_actor_as_user(delete, context).await?; - let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let community_actor_id = CommunityForm::from_apub(&group, context, Some(user.actor_id()?)) - .await? - .actor_id - .context(location_info!())?; - - let community = blocking(context.pool(), move |conn| { - Community::read_from_actor_id(conn, &community_actor_id) + let deleted_community = blocking(context.pool(), move |conn| { + Community::update_deleted(conn, community.id, false) }) .await??; - let community_form = CommunityForm { - name: community.name.to_owned(), - title: community.title.to_owned(), - description: community.description.to_owned(), - category_id: community.category_id, // Note: need to keep this due to foreign key constraint - creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint - removed: None, - published: None, - updated: Some(naive_now()), - deleted: Some(false), - nsfw: community.nsfw, - actor_id: Some(community.actor_id), - local: community.local, - private_key: community.private_key, - public_key: community.public_key, - last_refreshed_at: None, - icon: Some(community.icon.to_owned()), - banner: Some(community.banner.to_owned()), - }; - - let community_id = community.id; - blocking(context.pool(), move |conn| { - Community::update(conn, community_id, &community_form) - }) - .await??; - - let community_id = community.id; + let community_id = deleted_community.id; let res = CommunityResponse { community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) @@ -190,7 +152,6 @@ async fn receive_undo_delete_community( }; let community_id = res.community.id; - context.chat_server().do_send(SendCommunityRoomMessage { op: UserOperation::EditCommunity, response: res, @@ -198,56 +159,22 @@ async fn receive_undo_delete_community( websocket_id: None, }); + let user = get_actor_as_user(&undo, context).await?; announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } async fn receive_undo_remove_community( - undo: Undo, - remove: &Remove, context: &LemmyContext, + undo: Undo, + community: Community, ) -> Result { - let mod_ = get_actor_as_user(remove, context).await?; - let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let community_actor_id = CommunityForm::from_apub(&group, context, Some(mod_.actor_id()?)) - .await? - .actor_id - .context(location_info!())?; - - let community = blocking(context.pool(), move |conn| { - Community::read_from_actor_id(conn, &community_actor_id) + let removed_community = blocking(context.pool(), move |conn| { + Community::update_removed(conn, community.id, false) }) .await??; - let community_form = CommunityForm { - name: community.name.to_owned(), - title: community.title.to_owned(), - description: community.description.to_owned(), - category_id: community.category_id, // Note: need to keep this due to foreign key constraint - creator_id: community.creator_id, // Note: need to keep this due to foreign key constraint - removed: Some(false), - published: None, - updated: Some(naive_now()), - deleted: None, - nsfw: community.nsfw, - actor_id: Some(community.actor_id), - local: community.local, - private_key: community.private_key, - public_key: community.public_key, - last_refreshed_at: None, - icon: Some(community.icon.to_owned()), - banner: Some(community.banner.to_owned()), - }; - - let community_id = community.id; - blocking(context.pool(), move |conn| { - Community::update(conn, community_id, &community_form) - }) - .await??; - - let community_id = community.id; + let community_id = removed_community.id; let res = CommunityResponse { community: blocking(context.pool(), move |conn| { CommunityView::read(conn, community_id, None) @@ -264,6 +191,7 @@ async fn receive_undo_remove_community( websocket_id: None, }); + let mod_ = get_actor_as_user(&undo, context).await?; announce_if_community_is_local(undo, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/lemmy_apub/src/activities/receive/undo_comment.rs b/lemmy_apub/src/activities/receive/undo_comment.rs index d7566827d..4c046b6fe 100644 --- a/lemmy_apub/src/activities/receive/undo_comment.rs +++ b/lemmy_apub/src/activities/receive/undo_comment.rs @@ -1,7 +1,6 @@ use crate::{ activities::receive::{announce_if_community_is_local, get_actor_as_user}, fetcher::get_or_fetch_and_insert_comment, - ActorType, FromApub, }; use activitystreams::{activity::*, object::Note, prelude::*}; @@ -10,8 +9,6 @@ use anyhow::Context; use lemmy_db::{ comment::{Comment, CommentForm, CommentLike}, comment_view::CommentView, - naive_now, - Crud, Likeable, }; use lemmy_structs::{blocking, comment::CommentResponse}; @@ -115,41 +112,17 @@ pub(crate) async fn receive_undo_dislike_comment( } pub(crate) async fn receive_undo_delete_comment( - undo: Undo, - delete: &Delete, context: &LemmyContext, + undo: Undo, + comment: Comment, ) -> Result { - let user = get_actor_as_user(delete, context).await?; - let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let comment_ap_id = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)) - .await? - .get_ap_id()?; - - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; - - let comment_form = CommentForm { - content: comment.content.to_owned(), - parent_id: comment.parent_id, - post_id: comment.post_id, - creator_id: comment.creator_id, - removed: None, - deleted: Some(false), - read: None, - published: None, - updated: Some(naive_now()), - ap_id: Some(comment.ap_id), - local: comment.local, - }; - let comment_id = comment.id; - blocking(context.pool(), move |conn| { - Comment::update(conn, comment_id, &comment_form) + let deleted_comment = blocking(context.pool(), move |conn| { + Comment::update_deleted(conn, comment.id, false) }) .await??; // Refetch the view - let comment_id = comment.id; + let comment_id = deleted_comment.id; let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, comment_id, None) }) @@ -169,46 +142,23 @@ pub(crate) async fn receive_undo_delete_comment( websocket_id: None, }); + let user = get_actor_as_user(&undo, context).await?; announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } pub(crate) async fn receive_undo_remove_comment( - undo: Undo, - remove: &Remove, context: &LemmyContext, + undo: Undo, + comment: Comment, ) -> Result { - let mod_ = get_actor_as_user(remove, context).await?; - let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let comment_ap_id = CommentForm::from_apub(¬e, context, None) - .await? - .get_ap_id()?; - - let comment = get_or_fetch_and_insert_comment(&comment_ap_id, context).await?; - - let comment_form = CommentForm { - content: comment.content.to_owned(), - parent_id: comment.parent_id, - post_id: comment.post_id, - creator_id: comment.creator_id, - removed: Some(false), - deleted: None, - read: None, - published: None, - updated: Some(naive_now()), - ap_id: Some(comment.ap_id), - local: comment.local, - }; - let comment_id = comment.id; - blocking(context.pool(), move |conn| { - Comment::update(conn, comment_id, &comment_form) + let removed_comment = blocking(context.pool(), move |conn| { + Comment::update_removed(conn, comment.id, false) }) .await??; // Refetch the view - let comment_id = comment.id; + let comment_id = removed_comment.id; let comment_view = blocking(context.pool(), move |conn| { CommentView::read(conn, comment_id, None) }) @@ -228,6 +178,7 @@ pub(crate) async fn receive_undo_remove_comment( websocket_id: None, }); + let mod_ = get_actor_as_user(&undo, context).await?; announce_if_community_is_local(undo, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/lemmy_apub/src/activities/receive/undo_post.rs b/lemmy_apub/src/activities/receive/undo_post.rs index 3eebb08ec..e1638bc4c 100644 --- a/lemmy_apub/src/activities/receive/undo_post.rs +++ b/lemmy_apub/src/activities/receive/undo_post.rs @@ -1,7 +1,6 @@ use crate::{ activities::receive::{announce_if_community_is_local, get_actor_as_user}, fetcher::get_or_fetch_and_insert_post, - ActorType, FromApub, PageExt, }; @@ -9,10 +8,8 @@ use activitystreams::{activity::*, prelude::*}; use actix_web::HttpResponse; use anyhow::Context; use lemmy_db::{ - naive_now, post::{Post, PostForm, PostLike}, post_view::PostView, - Crud, Likeable, }; use lemmy_structs::{blocking, post::PostResponse}; @@ -104,108 +101,46 @@ pub(crate) async fn receive_undo_dislike_post( } pub(crate) async fn receive_undo_delete_post( - undo: Undo, - delete: &Delete, context: &LemmyContext, + undo: Undo, + post: Post, ) -> Result { - let user = get_actor_as_user(delete, context).await?; - let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let post_ap_id = PostForm::from_apub(&page, context, Some(user.actor_id()?)) - .await? - .get_ap_id()?; - - let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; - - let post_form = PostForm { - name: post.name.to_owned(), - url: post.url.to_owned(), - body: post.body.to_owned(), - creator_id: post.creator_id.to_owned(), - community_id: post.community_id, - removed: None, - deleted: Some(false), - nsfw: post.nsfw, - locked: None, - stickied: None, - updated: Some(naive_now()), - embed_title: post.embed_title, - embed_description: post.embed_description, - embed_html: post.embed_html, - thumbnail_url: post.thumbnail_url, - ap_id: Some(post.ap_id), - local: post.local, - published: None, - }; - let post_id = post.id; - blocking(context.pool(), move |conn| { - Post::update(conn, post_id, &post_form) + let deleted_post = blocking(context.pool(), move |conn| { + Post::update_deleted(conn, post.id, false) }) .await??; // Refetch the view - let post_id = post.id; + let post_id = deleted_post.id; let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) .await??; let res = PostResponse { post: post_view }; - context.chat_server().do_send(SendPost { op: UserOperation::EditPost, post: res, websocket_id: None, }); + let user = get_actor_as_user(&undo, context).await?; announce_if_community_is_local(undo, &user, context).await?; Ok(HttpResponse::Ok().finish()) } pub(crate) async fn receive_undo_remove_post( - undo: Undo, - remove: &Remove, context: &LemmyContext, + undo: Undo, + post: Post, ) -> Result { - let mod_ = get_actor_as_user(remove, context).await?; - let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let post_ap_id = PostForm::from_apub(&page, context, None) - .await? - .get_ap_id()?; - - let post = get_or_fetch_and_insert_post(&post_ap_id, context).await?; - - let post_form = PostForm { - name: post.name.to_owned(), - url: post.url.to_owned(), - body: post.body.to_owned(), - creator_id: post.creator_id.to_owned(), - community_id: post.community_id, - removed: Some(false), - deleted: None, - nsfw: post.nsfw, - locked: None, - stickied: None, - updated: Some(naive_now()), - embed_title: post.embed_title, - embed_description: post.embed_description, - embed_html: post.embed_html, - thumbnail_url: post.thumbnail_url, - ap_id: Some(post.ap_id), - local: post.local, - published: None, - }; - let post_id = post.id; - blocking(context.pool(), move |conn| { - Post::update(conn, post_id, &post_form) + let removed_post = blocking(context.pool(), move |conn| { + Post::update_removed(conn, post.id, false) }) .await??; // Refetch the view - let post_id = post.id; + let post_id = removed_post.id; let post_view = blocking(context.pool(), move |conn| { PostView::read(conn, post_id, None) }) @@ -219,6 +154,7 @@ pub(crate) async fn receive_undo_remove_post( websocket_id: None, }); + let mod_ = get_actor_as_user(&undo, context).await?; announce_if_community_is_local(undo, &mod_, context).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/lemmy_apub/src/activities/send/comment.rs b/lemmy_apub/src/activities/send/comment.rs index 092d7ef3d..bbf3adb17 100644 --- a/lemmy_apub/src/activities/send/comment.rs +++ b/lemmy_apub/src/activities/send/comment.rs @@ -106,8 +106,6 @@ impl ApubObjectType for Comment { } async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let note = self.to_apub(context.pool()).await?; - let post_id = self.post_id; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -117,7 +115,7 @@ impl ApubObjectType for Comment { }) .await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); delete .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) @@ -133,8 +131,6 @@ impl ApubObjectType for Comment { creator: &User_, context: &LemmyContext, ) -> Result<(), LemmyError> { - let note = self.to_apub(context.pool()).await?; - let post_id = self.post_id; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -145,7 +141,7 @@ impl ApubObjectType for Comment { .await??; // Generate a fake delete activity, with the correct object - let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); delete .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) @@ -165,8 +161,6 @@ impl ApubObjectType for Comment { } async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let note = self.to_apub(context.pool()).await?; - let post_id = self.post_id; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -176,7 +170,7 @@ impl ApubObjectType for Comment { }) .await??; - let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?); + let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); remove .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) @@ -188,8 +182,6 @@ impl ApubObjectType for Comment { } async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let note = self.to_apub(context.pool()).await?; - let post_id = self.post_id; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -200,7 +192,7 @@ impl ApubObjectType for Comment { .await??; // Generate a fake delete activity, with the correct object - let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?); + let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); remove .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) diff --git a/lemmy_apub/src/activities/send/community.rs b/lemmy_apub/src/activities/send/community.rs index 0d16d6361..3bed1a2ae 100644 --- a/lemmy_apub/src/activities/send/community.rs +++ b/lemmy_apub/src/activities/send/community.rs @@ -124,9 +124,7 @@ impl ActorType for Community { } async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let group = self.to_apub(context.pool()).await?; - - let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?); + let mut remove = Remove::new(mod_.actor_id.to_owned(), self.actor_id()?); remove .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) @@ -138,9 +136,7 @@ impl ActorType for Community { } async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let group = self.to_apub(context.pool()).await?; - - let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?); + let mut remove = Remove::new(mod_.actor_id.to_owned(), self.actor_id()?); remove .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) diff --git a/lemmy_apub/src/activities/send/post.rs b/lemmy_apub/src/activities/send/post.rs index 81d1a954c..568a5f571 100644 --- a/lemmy_apub/src/activities/send/post.rs +++ b/lemmy_apub/src/activities/send/post.rs @@ -24,6 +24,7 @@ use lemmy_db::{community::Community, post::Post, user::User_, Crud}; use lemmy_structs::blocking; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; +use url::Url; #[async_trait::async_trait(?Send)] impl ApubObjectType for Post { @@ -70,15 +71,13 @@ impl ApubObjectType for Post { } async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let page = self.to_apub(context.pool()).await?; - let community_id = self.community_id; let community = blocking(context.pool(), move |conn| { Community::read(conn, community_id) }) .await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?); + let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); delete .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) @@ -94,15 +93,13 @@ impl ApubObjectType for Post { creator: &User_, context: &LemmyContext, ) -> Result<(), LemmyError> { - let page = self.to_apub(context.pool()).await?; - let community_id = self.community_id; let community = blocking(context.pool(), move |conn| { Community::read(conn, community_id) }) .await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?); + let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); delete .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) @@ -122,15 +119,13 @@ impl ApubObjectType for Post { } async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let page = self.to_apub(context.pool()).await?; - let community_id = self.community_id; let community = blocking(context.pool(), move |conn| { Community::read(conn, community_id) }) .await??; - let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?); + let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); remove .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) @@ -142,15 +137,13 @@ impl ApubObjectType for Post { } async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let page = self.to_apub(context.pool()).await?; - let community_id = self.community_id; let community = blocking(context.pool(), move |conn| { Community::read(conn, community_id) }) .await??; - let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?); + let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); remove .set_context(activitystreams::context()) .set_id(generate_activity_id(RemoveType::Remove)?) diff --git a/lemmy_apub/src/activities/send/private_message.rs b/lemmy_apub/src/activities/send/private_message.rs index fc3e52252..89b654041 100644 --- a/lemmy_apub/src/activities/send/private_message.rs +++ b/lemmy_apub/src/activities/send/private_message.rs @@ -19,6 +19,7 @@ use lemmy_db::{private_message::PrivateMessage, user::User_, Crud}; use lemmy_structs::blocking; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; +use url::Url; #[async_trait::async_trait(?Send)] impl ApubObjectType for PrivateMessage { @@ -58,12 +59,10 @@ impl ApubObjectType for PrivateMessage { } async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { - let note = self.to_apub(context.pool()).await?; - let recipient_id = self.recipient_id; let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); delete .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) @@ -78,12 +77,10 @@ impl ApubObjectType for PrivateMessage { creator: &User_, context: &LemmyContext, ) -> Result<(), LemmyError> { - let note = self.to_apub(context.pool()).await?; - let recipient_id = self.recipient_id; let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); delete .set_context(activitystreams::context()) .set_id(generate_activity_id(DeleteType::Delete)?) diff --git a/lemmy_apub/src/inbox/user_inbox.rs b/lemmy_apub/src/inbox/user_inbox.rs index db6a6cea9..7bc36a0ff 100644 --- a/lemmy_apub/src/inbox/user_inbox.rs +++ b/lemmy_apub/src/inbox/user_inbox.rs @@ -8,6 +8,7 @@ use crate::{ use activitystreams::{ activity::{Accept, ActorAndObject, Create, Delete, Undo, Update}, base::AnyBase, + error::DomainError, object::Note, prelude::*, }; @@ -15,7 +16,6 @@ use actix_web::{web, HttpRequest, HttpResponse}; use anyhow::Context; use lemmy_db::{ community::{CommunityFollower, CommunityFollowerForm}, - naive_now, private_message::{PrivateMessage, PrivateMessageForm}, private_message_view::PrivateMessageView, user::User_, @@ -131,7 +131,17 @@ async fn receive_create_private_message( )? .context(location_info!())?; - let domain = Some(create.id_unchecked().context(location_info!())?.to_owned()); + let actor = create + .actor()? + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + let domain = Some( + create + .id(actor.domain().context(location_info!())?)? + .context(location_info!())? + .to_owned(), + ); let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?; let inserted_private_message = blocking(&context.pool(), move |conn| { @@ -172,7 +182,17 @@ async fn receive_update_private_message( )? .context(location_info!())?; - let domain = Some(update.id_unchecked().context(location_info!())?.to_owned()); + let actor = update + .actor()? + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + let domain = Some( + update + .id(actor.domain().context(location_info!())?)? + .context(location_info!())? + .to_owned(), + ); let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?; let private_message_ap_id = private_message_form @@ -216,52 +236,39 @@ async fn receive_delete_private_message( context: &LemmyContext, ) -> Result { let delete = Delete::from_any_base(activity)?.context(location_info!())?; - let note = Note::from_any_base( - delete - .object() - .as_one() - .context(location_info!())? - .to_owned(), - )? - .context(location_info!())?; - - let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned()); - let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?; - - let private_message_ap_id = private_message_form.ap_id.context(location_info!())?; - let private_message = blocking(&context.pool(), move |conn| { - PrivateMessage::read_from_apub_id(conn, &private_message_ap_id) + let private_message_id = delete + .object() + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + let actor = delete + .actor()? + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + let delete_id = delete + .id(actor.domain().context(location_info!())?)? + .map(|i| i.domain()) + .flatten(); + if private_message_id.domain() != delete_id { + return Err(DomainError.into()); + } + let private_message = blocking(context.pool(), move |conn| { + PrivateMessage::read_from_apub_id(conn, private_message_id.as_str()) + }) + .await??; + let deleted_private_message = blocking(context.pool(), move |conn| { + PrivateMessage::update_deleted(conn, private_message.id, true) }) .await??; - let private_message_form = PrivateMessageForm { - content: private_message_form.content, - recipient_id: private_message.recipient_id, - creator_id: private_message.creator_id, - deleted: Some(true), - read: None, - ap_id: Some(private_message.ap_id), - local: private_message.local, - published: None, - updated: Some(naive_now()), - }; - - let private_message_id = private_message.id; - blocking(&context.pool(), move |conn| { - PrivateMessage::update(conn, private_message_id, &private_message_form) - }) - .await??; - - let private_message_id = private_message.id; let message = blocking(&context.pool(), move |conn| { - PrivateMessageView::read(&conn, private_message_id) + PrivateMessageView::read(&conn, deleted_private_message.id) }) .await??; let res = PrivateMessageResponse { message }; - let recipient_id = res.message.recipient_id; - context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::EditPrivateMessage, response: res, @@ -279,47 +286,35 @@ async fn receive_undo_delete_private_message( let undo = Undo::from_any_base(activity)?.context(location_info!())?; let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())? .context(location_info!())?; - let note = Note::from_any_base( - delete - .object() - .as_one() - .context(location_info!())? - .to_owned(), - )? - .context(location_info!())?; + let private_message_id = delete + .object() + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + let actor = undo + .actor()? + .to_owned() + .single_xsd_any_uri() + .context(location_info!())?; + let undo_id = undo + .id(actor.domain().context(location_info!())?)? + .map(|i| i.domain()) + .flatten(); + if private_message_id.domain() != undo_id { + return Err(DomainError.into()); + } - let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned()); - let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?; - - let private_message_ap_id = private_message - .ap_id - .as_ref() - .context(location_info!())? - .clone(); - let private_message_id = blocking(&context.pool(), move |conn| { - PrivateMessage::read_from_apub_id(conn, &private_message_ap_id).map(|pm| pm.id) + let private_message = blocking(context.pool(), move |conn| { + PrivateMessage::read_from_apub_id(conn, private_message_id.as_str()) }) .await??; - - let private_message_form = PrivateMessageForm { - content: private_message.content, - recipient_id: private_message.recipient_id, - creator_id: private_message.creator_id, - deleted: Some(false), - read: None, - ap_id: private_message.ap_id, - local: private_message.local, - published: None, - updated: Some(naive_now()), - }; - - blocking(&context.pool(), move |conn| { - PrivateMessage::update(conn, private_message_id, &private_message_form) + let deleted_private_message = blocking(context.pool(), move |conn| { + PrivateMessage::update_deleted(conn, private_message.id, false) }) .await??; let message = blocking(&context.pool(), move |conn| { - PrivateMessageView::read(&conn, private_message_id) + PrivateMessageView::read(&conn, deleted_private_message.id) }) .await??;