X-Git-Url: http://these/git/?a=blobdiff_plain;f=crates%2Fapub%2Fsrc%2Factivity_lists.rs;h=4cce3372fa01a6cba14e67efb7e959e97fe05cf3;hb=92568956353f21649ed9aff68b42699c9d036f30;hp=dbd185bddebf2bdc3cb913a8aac0aa0ad7d06c60;hpb=a85334c675e4f68b3ff01808d0cf96339cea5fa0;p=lemmy.git diff --git a/crates/apub/src/activity_lists.rs b/crates/apub/src/activity_lists.rs index dbd185bd..4cce3372 100644 --- a/crates/apub/src/activity_lists.rs +++ b/crates/apub/src/activity_lists.rs @@ -1,82 +1,88 @@ use crate::{ - activities::{community::announce::GetCommunity, verify_person_in_community}, objects::community::ApubCommunity, protocol::{ activities::{ block::{block_user::BlockUser, undo_block_user::UndoBlockUser}, community::{ - add_mod::AddMod, - announce::AnnounceActivity, - remove_mod::RemoveMod, + announce::{AnnounceActivity, RawAnnouncableActivities}, + collection_add::CollectionAdd, + collection_remove::CollectionRemove, + lock_page::{LockPage, UndoLockPage}, report::Report, update::UpdateCommunity, }, create_or_update::{ - comment::CreateOrUpdateComment, - post::CreateOrUpdatePost, - private_message::CreateOrUpdatePrivateMessage, + chat_message::CreateOrUpdateChatMessage, + note::CreateOrUpdateNote, + page::CreateOrUpdatePage, }, deletion::{delete::Delete, delete_user::DeleteUser, undo_delete::UndoDelete}, - following::{ - accept::AcceptFollowCommunity, - follow::FollowCommunity, - undo_follow::UndoFollowCommunity, - }, + following::{accept::AcceptFollow, follow::Follow, undo_follow::UndoFollow}, voting::{undo_vote::UndoVote, vote::Vote}, }, objects::page::Page, - Id, + InCommunity, }, }; use activitypub_federation::{ - core::object_id::ObjectId, - data::Data, - deser::context::WithContext, - traits::{activity_handler, ActivityHandler}, + config::Data, + protocol::context::WithContext, + traits::ActivityHandler, }; +use lemmy_api_common::context::LemmyContext; use lemmy_utils::error::LemmyError; -use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use url::Url; #[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext, LemmyError)] +#[enum_delegate::implement(ActivityHandler)] pub enum SharedInboxActivities { - GroupInboxActivities(Box>), - // Note, pm activities need to be at the end, otherwise comments will end up here. We can probably - // avoid this problem by replacing createpm.object with our own struct, instead of NoteExt. PersonInboxActivities(Box>), + GroupInboxActivities(Box>), } #[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] +#[enum_delegate::implement(ActivityHandler)] pub enum GroupInboxActivities { - FollowCommunity(FollowCommunity), - UndoFollowCommunity(UndoFollowCommunity), - AnnouncableActivities(Box), + Follow(Follow), + UndoFollow(UndoFollow), Report(Report), + // This is a catch-all and needs to be last + AnnouncableActivities(RawAnnouncableActivities), } #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext, LemmyError)] +#[enum_delegate::implement(ActivityHandler)] pub enum PersonInboxActivities { - AcceptFollowCommunity(AcceptFollowCommunity), - /// Some activities can also be sent from user to user, eg a comment with mentions - AnnouncableActivities(AnnouncableActivities), - CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage), + Follow(Follow), + AcceptFollow(AcceptFollow), + UndoFollow(UndoFollow), + CreateOrUpdatePrivateMessage(CreateOrUpdateChatMessage), Delete(Delete), UndoDelete(UndoDelete), AnnounceActivity(AnnounceActivity), } +/// This is necessary for user inbox, which can also receive some "announcable" activities, +/// eg a comment mention. This needs to be a separate enum so that announcables received in shared +/// inbox can fall through to be parsed as GroupInboxActivities::AnnouncableActivities. +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] +#[enum_delegate::implement(ActivityHandler)] +pub enum PersonInboxActivitiesWithAnnouncable { + PersonInboxActivities(Box), + AnnouncableActivities(Box), +} + #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext, LemmyError)] +#[enum_delegate::implement(ActivityHandler)] pub enum AnnouncableActivities { - CreateOrUpdateComment(CreateOrUpdateComment), - CreateOrUpdatePost(Box), + CreateOrUpdateComment(CreateOrUpdateNote), + CreateOrUpdatePost(CreateOrUpdatePage), Vote(Vote), UndoVote(UndoVote), Delete(Delete), @@ -84,15 +90,17 @@ pub enum AnnouncableActivities { UpdateCommunity(UpdateCommunity), BlockUser(BlockUser), UndoBlockUser(UndoBlockUser), - AddMod(AddMod), - RemoveMod(RemoveMod), + CollectionAdd(CollectionAdd), + CollectionRemove(CollectionRemove), + LockPost(LockPage), + UndoLockPost(UndoLockPage), // For compatibility with Pleroma/Mastodon (send only) Page(Page), } #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext, LemmyError)] +#[enum_delegate::implement(ActivityHandler)] #[allow(clippy::enum_variant_names)] pub enum SiteInboxActivities { BlockUser(BlockUser), @@ -100,109 +108,43 @@ pub enum SiteInboxActivities { DeleteUser(DeleteUser), } -#[async_trait::async_trait(?Send)] -impl GetCommunity for AnnouncableActivities { +#[async_trait::async_trait] +impl InCommunity for AnnouncableActivities { #[tracing::instrument(skip(self, context))] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { + async fn community(&self, context: &Data) -> Result { use AnnouncableActivities::*; - let community = match self { - CreateOrUpdateComment(a) => a.get_community(context, request_counter).await?, - CreateOrUpdatePost(a) => a.get_community(context, request_counter).await?, - Vote(a) => a.get_community(context, request_counter).await?, - UndoVote(a) => a.get_community(context, request_counter).await?, - Delete(a) => a.get_community(context, request_counter).await?, - UndoDelete(a) => a.get_community(context, request_counter).await?, - UpdateCommunity(a) => a.get_community(context, request_counter).await?, - BlockUser(a) => a.get_community(context, request_counter).await?, - UndoBlockUser(a) => a.get_community(context, request_counter).await?, - AddMod(a) => a.get_community(context, request_counter).await?, - RemoveMod(a) => a.get_community(context, request_counter).await?, - Page(_) => unimplemented!(), - }; - Ok(community) - } -} - -impl Id for AnnouncableActivities { - fn object_id(&self) -> &Url { - ActivityHandler::id(self) - } -} - -// Need to implement this manually to announce matching activities -#[async_trait::async_trait(?Send)] -impl ActivityHandler for GroupInboxActivities { - type DataType = LemmyContext; - type Error = LemmyError; - - fn id(&self) -> &Url { match self { - GroupInboxActivities::FollowCommunity(a) => a.id(), - GroupInboxActivities::UndoFollowCommunity(a) => a.id(), - GroupInboxActivities::AnnouncableActivities(a) => a.object_id(), - GroupInboxActivities::Report(a) => a.id(), - } - } - - fn actor(&self) -> &Url { - match self { - GroupInboxActivities::FollowCommunity(a) => a.actor(), - GroupInboxActivities::UndoFollowCommunity(a) => a.actor(), - GroupInboxActivities::AnnouncableActivities(a) => a.actor(), - GroupInboxActivities::Report(a) => a.actor(), - } - } - - async fn verify( - &self, - data: &Data, - request_counter: &mut i32, - ) -> Result<(), LemmyError> { - match self { - GroupInboxActivities::FollowCommunity(a) => a.verify(data, request_counter).await, - GroupInboxActivities::UndoFollowCommunity(a) => a.verify(data, request_counter).await, - GroupInboxActivities::AnnouncableActivities(a) => a.verify(data, request_counter).await, - GroupInboxActivities::Report(a) => a.verify(data, request_counter).await, - } - } - - async fn receive( - self, - data: &Data, - request_counter: &mut i32, - ) -> Result<(), LemmyError> { - match self { - GroupInboxActivities::FollowCommunity(a) => a.receive(data, request_counter).await, - GroupInboxActivities::UndoFollowCommunity(a) => a.receive(data, request_counter).await, - GroupInboxActivities::AnnouncableActivities(activity) => { - activity.clone().receive(data, request_counter).await?; - - // Ignore failures in get_community(). those happen because Delete/PrivateMessage is not in a - // community, but looks identical to Delete/Post or Delete/Comment which are in a community. - let community = activity.get_community(data, &mut 0).await; - if let Ok(community) = community { - if community.local { - let actor_id = ObjectId::new(activity.actor().clone()); - verify_person_in_community(&actor_id, &community, data, &mut 0).await?; - AnnounceActivity::send(*activity, &community, data).await?; - } - } - Ok(()) - } - GroupInboxActivities::Report(a) => a.receive(data, request_counter).await, + CreateOrUpdateComment(a) => a.community(context).await, + CreateOrUpdatePost(a) => a.community(context).await, + Vote(a) => a.community(context).await, + UndoVote(a) => a.community(context).await, + Delete(a) => a.community(context).await, + UndoDelete(a) => a.community(context).await, + UpdateCommunity(a) => a.community(context).await, + BlockUser(a) => a.community(context).await, + UndoBlockUser(a) => a.community(context).await, + CollectionAdd(a) => a.community(context).await, + CollectionRemove(a) => a.community(context).await, + LockPost(a) => a.community(context).await, + UndoLockPost(a) => a.community(context).await, + Page(_) => unimplemented!(), } } } #[cfg(test)] mod tests { + #![allow(clippy::unwrap_used)] + #![allow(clippy::indexing_slicing)] + use crate::{ - activity_lists::{GroupInboxActivities, PersonInboxActivities, SiteInboxActivities}, - protocol::tests::test_parse_lemmy_item, + activity_lists::{ + GroupInboxActivities, + PersonInboxActivities, + PersonInboxActivitiesWithAnnouncable, + SiteInboxActivities, + }, + protocol::tests::{test_json, test_parse_lemmy_item}, }; #[test] @@ -219,14 +161,16 @@ mod tests { fn test_person_inbox() { test_parse_lemmy_item::("assets/lemmy/activities/following/accept.json") .unwrap(); - test_parse_lemmy_item::( + test_parse_lemmy_item::( "assets/lemmy/activities/create_or_update/create_note.json", ) .unwrap(); - test_parse_lemmy_item::( + test_parse_lemmy_item::( "assets/lemmy/activities/create_or_update/create_private_message.json", ) .unwrap(); + test_json::("assets/mastodon/activities/follow.json") + .unwrap(); } #[test]