X-Git-Url: http://these/git/?a=blobdiff_plain;f=crates%2Fapub%2Fsrc%2Factivity_lists.rs;h=4cce3372fa01a6cba14e67efb7e959e97fe05cf3;hb=92568956353f21649ed9aff68b42699c9d036f30;hp=9fd1a9dc187ae5cdf1b70ccd79459e432e046532;hpb=03d8ac75efa9badfb476a54d026c5511e028b2b6;p=lemmy.git diff --git a/crates/apub/src/activity_lists.rs b/crates/apub/src/activity_lists.rs index 9fd1a9dc..4cce3372 100644 --- a/crates/apub/src/activity_lists.rs +++ b/crates/apub/src/activity_lists.rs @@ -1,113 +1,183 @@ -use serde::{Deserialize, Serialize}; - -use lemmy_apub_lib::{ - traits::{ActivityFields, ActivityHandler, ActorType}, - verify::verify_urls_match, -}; -use lemmy_utils::LemmyError; -use lemmy_websocket::LemmyContext; - use crate::{ - activities::community::announce::GetCommunity, objects::community::ApubCommunity, - protocol::activities::{ - community::{ - add_mod::AddMod, - announce::AnnounceActivity, - block_user::BlockUserFromCommunity, - remove_mod::RemoveMod, - report::Report, - undo_block_user::UndoBlockUserFromCommunity, - update::UpdateCommunity, + protocol::{ + activities::{ + block::{block_user::BlockUser, undo_block_user::UndoBlockUser}, + community::{ + announce::{AnnounceActivity, RawAnnouncableActivities}, + collection_add::CollectionAdd, + collection_remove::CollectionRemove, + lock_page::{LockPage, UndoLockPage}, + report::Report, + update::UpdateCommunity, + }, + create_or_update::{ + chat_message::CreateOrUpdateChatMessage, + note::CreateOrUpdateNote, + page::CreateOrUpdatePage, + }, + deletion::{delete::Delete, delete_user::DeleteUser, undo_delete::UndoDelete}, + following::{accept::AcceptFollow, follow::Follow, undo_follow::UndoFollow}, + voting::{undo_vote::UndoVote, vote::Vote}, }, - create_or_update::{comment::CreateOrUpdateComment, post::CreateOrUpdatePost}, - deletion::{delete::Delete, undo_delete::UndoDelete}, - following::{ - accept::AcceptFollowCommunity, - follow::FollowCommunity, - undo_follow::UndoFollowCommunity, - }, - private_message::{ - create_or_update::CreateOrUpdatePrivateMessage, - delete::DeletePrivateMessage, - undo_delete::UndoDeletePrivateMessage, - }, - voting::{undo_vote::UndoVote, vote::Vote}, + objects::page::Page, + InCommunity, }, }; +use activitypub_federation::{ + config::Data, + protocol::context::WithContext, + traits::ActivityHandler, +}; +use lemmy_api_common::context::LemmyContext; +use lemmy_utils::error::LemmyError; +use serde::{Deserialize, Serialize}; +use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)] +#[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext)] +#[enum_delegate::implement(ActivityHandler)] pub enum SharedInboxActivities { - GroupInboxActivities(GroupInboxActivities), - // 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(PersonInboxActivities), + PersonInboxActivities(Box>), + GroupInboxActivities(Box>), } -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)] +#[derive(Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext)] +#[enum_delegate::implement(ActivityHandler)] pub enum GroupInboxActivities { - FollowCommunity(FollowCommunity), - UndoFollowCommunity(UndoFollowCommunity), - AnnouncableActivities(AnnouncableActivities), + Follow(Follow), + UndoFollow(UndoFollow), Report(Report), + // This is a catch-all and needs to be last + AnnouncableActivities(RawAnnouncableActivities), } -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext)] +#[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), - DeletePrivateMessage(DeletePrivateMessage), - UndoDeletePrivateMessage(UndoDeletePrivateMessage), - AnnounceActivity(Box), + 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, ActivityHandler, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(untagged)] -#[activity_handler(LemmyContext)] +#[enum_delegate::implement(ActivityHandler)] pub enum AnnouncableActivities { - CreateOrUpdateComment(CreateOrUpdateComment), - CreateOrUpdatePost(Box), + CreateOrUpdateComment(CreateOrUpdateNote), + CreateOrUpdatePost(CreateOrUpdatePage), Vote(Vote), UndoVote(UndoVote), Delete(Delete), UndoDelete(UndoDelete), - UpdateCommunity(Box), - BlockUserFromCommunity(BlockUserFromCommunity), - UndoBlockUserFromCommunity(UndoBlockUserFromCommunity), - AddMod(AddMod), - RemoveMod(RemoveMod), + UpdateCommunity(UpdateCommunity), + BlockUser(BlockUser), + UndoBlockUser(UndoBlockUser), + CollectionAdd(CollectionAdd), + CollectionRemove(CollectionRemove), + LockPost(LockPage), + UndoLockPost(UndoLockPage), + // For compatibility with Pleroma/Mastodon (send only) + Page(Page), } -#[async_trait::async_trait(?Send)] -impl GetCommunity for AnnouncableActivities { - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] +#[enum_delegate::implement(ActivityHandler)] +#[allow(clippy::enum_variant_names)] +pub enum SiteInboxActivities { + BlockUser(BlockUser), + UndoBlockUser(UndoBlockUser), + DeleteUser(DeleteUser), +} + +#[async_trait::async_trait] +impl InCommunity for AnnouncableActivities { + #[tracing::instrument(skip(self, context))] + 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?, - BlockUserFromCommunity(a) => a.get_community(context, request_counter).await?, - UndoBlockUserFromCommunity(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?, - }; - verify_urls_match(self.actor(), &community.actor_id())?; - Ok(community) + match self { + 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, + PersonInboxActivitiesWithAnnouncable, + SiteInboxActivities, + }, + protocol::tests::{test_json, test_parse_lemmy_item}, + }; + + #[test] + fn test_group_inbox() { + test_parse_lemmy_item::("assets/lemmy/activities/following/follow.json") + .unwrap(); + test_parse_lemmy_item::( + "assets/lemmy/activities/create_or_update/create_note.json", + ) + .unwrap(); + } + + #[test] + fn test_person_inbox() { + test_parse_lemmy_item::("assets/lemmy/activities/following/accept.json") + .unwrap(); + test_parse_lemmy_item::( + "assets/lemmy/activities/create_or_update/create_note.json", + ) + .unwrap(); + test_parse_lemmy_item::( + "assets/lemmy/activities/create_or_update/create_private_message.json", + ) + .unwrap(); + test_json::("assets/mastodon/activities/follow.json") + .unwrap(); + } + + #[test] + fn test_site_inbox() { + test_parse_lemmy_item::( + "assets/lemmy/activities/deletion/delete_user.json", + ) + .unwrap(); } }