From: Colin Reeder Date: Sat, 27 Nov 2021 04:55:33 +0000 (-0700) Subject: Allow single item for to, cc, and @context X-Git-Url: http://these/git/%7Bthis.getImage%28%29%7D?a=commitdiff_plain;h=a91c0c8feb9ecbc692384bc39fc36658f63fb987;p=lemmy.git Allow single item for to, cc, and @context --- diff --git a/crates/apub/src/context.rs b/crates/apub/src/context.rs index 3ec444e3..9d2d3d42 100644 --- a/crates/apub/src/context.rs +++ b/crates/apub/src/context.rs @@ -8,6 +8,7 @@ static CONTEXT: Lazy> = Lazy::new(|| { #[derive(Serialize, Deserialize, Debug)] pub(crate) struct WithContext { #[serde(rename = "@context")] + #[serde(deserialize_with = "crate::deserialize_one_or_many")] context: Vec, #[serde(flatten)] inner: T, diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index 984d722e..b3c7eff7 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -3,6 +3,7 @@ use anyhow::{anyhow, Context}; use lemmy_api_common::blocking; use lemmy_db_schema::{newtypes::DbUrl, source::activity::Activity, DbPool}; use lemmy_utils::{location_info, settings::structs::Settings, LemmyError}; +use serde::{Deserialize, Deserializer}; use std::net::IpAddr; use url::{ParseError, Url}; @@ -85,6 +86,25 @@ pub(crate) fn check_is_apub_id_valid( Ok(()) } +pub(crate) fn deserialize_one_or_many<'de, T, D>(deserializer: D) -> Result, D::Error> +where + T: Deserialize<'de>, + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + #[serde(untagged)] + enum OneOrMany { + One(T), + Many(Vec), + } + + let result: OneOrMany = Deserialize::deserialize(deserializer)?; + Ok(match result { + OneOrMany::Many(list) => list, + OneOrMany::One(value) => vec![value], + }) +} + pub enum EndpointType { Community, Person, diff --git a/crates/apub/src/protocol/activities/community/add_mod.rs b/crates/apub/src/protocol/activities/community/add_mod.rs index 0d6edc0a..915c2466 100644 --- a/crates/apub/src/protocol/activities/community/add_mod.rs +++ b/crates/apub/src/protocol/activities/community/add_mod.rs @@ -8,9 +8,11 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct AddMod { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, pub(crate) target: Url, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: AddType, diff --git a/crates/apub/src/protocol/activities/community/announce.rs b/crates/apub/src/protocol/activities/community/announce.rs index 11890c68..0bda9ebc 100644 --- a/crates/apub/src/protocol/activities/community/announce.rs +++ b/crates/apub/src/protocol/activities/community/announce.rs @@ -12,8 +12,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct AnnounceActivity { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: AnnouncableActivities, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: AnnounceType, diff --git a/crates/apub/src/protocol/activities/community/block_user.rs b/crates/apub/src/protocol/activities/community/block_user.rs index c904fc21..ecde0ce3 100644 --- a/crates/apub/src/protocol/activities/community/block_user.rs +++ b/crates/apub/src/protocol/activities/community/block_user.rs @@ -11,8 +11,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct BlockUserFromCommunity { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, pub(crate) target: ObjectId, #[serde(rename = "type")] diff --git a/crates/apub/src/protocol/activities/community/remove_mod.rs b/crates/apub/src/protocol/activities/community/remove_mod.rs index dc456b0b..74619c81 100644 --- a/crates/apub/src/protocol/activities/community/remove_mod.rs +++ b/crates/apub/src/protocol/activities/community/remove_mod.rs @@ -8,8 +8,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct RemoveMod { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: RemoveType, diff --git a/crates/apub/src/protocol/activities/community/undo_block_user.rs b/crates/apub/src/protocol/activities/community/undo_block_user.rs index f08e0c35..02218367 100644 --- a/crates/apub/src/protocol/activities/community/undo_block_user.rs +++ b/crates/apub/src/protocol/activities/community/undo_block_user.rs @@ -11,8 +11,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct UndoBlockUserFromCommunity { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: BlockUserFromCommunity, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UndoType, diff --git a/crates/apub/src/protocol/activities/community/update.rs b/crates/apub/src/protocol/activities/community/update.rs index 9bdcded9..bb9b5611 100644 --- a/crates/apub/src/protocol/activities/community/update.rs +++ b/crates/apub/src/protocol/activities/community/update.rs @@ -13,9 +13,11 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct UpdateCommunity { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, // TODO: would be nice to use a separate struct here, which only contains the fields updated here pub(crate) object: Box, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UpdateType, diff --git a/crates/apub/src/protocol/activities/create_or_update/comment.rs b/crates/apub/src/protocol/activities/create_or_update/comment.rs index deef4c86..091c0f97 100644 --- a/crates/apub/src/protocol/activities/create_or_update/comment.rs +++ b/crates/apub/src/protocol/activities/create_or_update/comment.rs @@ -11,8 +11,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct CreateOrUpdateComment { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Note, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(default)] pub(crate) tag: Vec, diff --git a/crates/apub/src/protocol/activities/create_or_update/post.rs b/crates/apub/src/protocol/activities/create_or_update/post.rs index db159c86..2061c881 100644 --- a/crates/apub/src/protocol/activities/create_or_update/post.rs +++ b/crates/apub/src/protocol/activities/create_or_update/post.rs @@ -10,8 +10,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct CreateOrUpdatePost { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Page, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: CreateOrUpdateType, diff --git a/crates/apub/src/protocol/activities/deletion/delete.rs b/crates/apub/src/protocol/activities/deletion/delete.rs index 49adb6e6..a999e58e 100644 --- a/crates/apub/src/protocol/activities/deletion/delete.rs +++ b/crates/apub/src/protocol/activities/deletion/delete.rs @@ -13,6 +13,7 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct Delete { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Tombstone, #[serde(rename = "type")] diff --git a/crates/apub/src/protocol/activities/deletion/undo_delete.rs b/crates/apub/src/protocol/activities/deletion/undo_delete.rs index d7608017..ebd51f96 100644 --- a/crates/apub/src/protocol/activities/deletion/undo_delete.rs +++ b/crates/apub/src/protocol/activities/deletion/undo_delete.rs @@ -11,8 +11,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct UndoDelete { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Delete, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UndoType, diff --git a/crates/apub/src/protocol/activities/voting/undo_vote.rs b/crates/apub/src/protocol/activities/voting/undo_vote.rs index 9a1767f2..d3f4fb33 100644 --- a/crates/apub/src/protocol/activities/voting/undo_vote.rs +++ b/crates/apub/src/protocol/activities/voting/undo_vote.rs @@ -11,8 +11,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct UndoVote { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Vote, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UndoType, diff --git a/crates/apub/src/protocol/activities/voting/vote.rs b/crates/apub/src/protocol/activities/voting/vote.rs index 065e3b31..ba5c629c 100644 --- a/crates/apub/src/protocol/activities/voting/vote.rs +++ b/crates/apub/src/protocol/activities/voting/vote.rs @@ -15,8 +15,10 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct Vote { pub(crate) actor: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: VoteType, diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index be21f8f5..39c606b0 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -23,8 +23,10 @@ pub struct Note { pub(crate) r#type: NoteType, pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, #[serde(default)] + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, pub(crate) content: String, pub(crate) media_type: Option, diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index 2bd5cc6d..1fca51e4 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -24,8 +24,10 @@ pub struct Page { pub(crate) r#type: PageType, pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) to: Vec, #[serde(default)] + #[serde(deserialize_with = "crate::deserialize_one_or_many")] pub(crate) cc: Vec, pub(crate) name: String, pub(crate) content: Option,