]> Untitled Git - lemmy.git/commitdiff
Allow single item for to, cc, and @context
authorColin Reeder <vpzomtrrfrt@gmail.com>
Sat, 27 Nov 2021 04:55:33 +0000 (21:55 -0700)
committerColin Reeder <vpzomtrrfrt@gmail.com>
Sat, 27 Nov 2021 04:55:33 +0000 (21:55 -0700)
16 files changed:
crates/apub/src/context.rs
crates/apub/src/lib.rs
crates/apub/src/protocol/activities/community/add_mod.rs
crates/apub/src/protocol/activities/community/announce.rs
crates/apub/src/protocol/activities/community/block_user.rs
crates/apub/src/protocol/activities/community/remove_mod.rs
crates/apub/src/protocol/activities/community/undo_block_user.rs
crates/apub/src/protocol/activities/community/update.rs
crates/apub/src/protocol/activities/create_or_update/comment.rs
crates/apub/src/protocol/activities/create_or_update/post.rs
crates/apub/src/protocol/activities/deletion/delete.rs
crates/apub/src/protocol/activities/deletion/undo_delete.rs
crates/apub/src/protocol/activities/voting/undo_vote.rs
crates/apub/src/protocol/activities/voting/vote.rs
crates/apub/src/protocol/objects/note.rs
crates/apub/src/protocol/objects/page.rs

index 3ec444e3392a8ce3bd8f9cf4645443fa8d4d3928..9d2d3d42cde5806029dfa471eb2dc404a0c1c891 100644 (file)
@@ -8,6 +8,7 @@ static CONTEXT: Lazy<Vec<serde_json::Value>> = Lazy::new(|| {
 #[derive(Serialize, Deserialize, Debug)]
 pub(crate) struct WithContext<T> {
   #[serde(rename = "@context")]
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   context: Vec<serde_json::Value>,
   #[serde(flatten)]
   inner: T,
index 984d722e8568066efc0a06b9f3aa7bb47cff8dd7..b3c7eff7218beff461f19189b6c8f49db824a41a 100644 (file)
@@ -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<Vec<T>, D::Error>
+where
+  T: Deserialize<'de>,
+  D: Deserializer<'de>,
+{
+  #[derive(Deserialize)]
+  #[serde(untagged)]
+  enum OneOrMany<T> {
+    One(T),
+    Many(Vec<T>),
+  }
+
+  let result: OneOrMany<T> = Deserialize::deserialize(deserializer)?;
+  Ok(match result {
+    OneOrMany::Many(list) => list,
+    OneOrMany::One(value) => vec![value],
+  })
+}
+
 pub enum EndpointType {
   Community,
   Person,
index 0d6edc0a6ba3a943d9aa3f50caaee1dec846b911..915c24668e8449ba930348c9f21fc44769698692 100644 (file)
@@ -8,9 +8,11 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct AddMod {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<ApubPerson>,
   pub(crate) target: Url,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: AddType,
index 11890c680d9ad630a4a996b0bc31fe98827b0b31..0bda9ebc5a036ed8c0b8f6a654b39a306f28374a 100644 (file)
@@ -12,8 +12,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct AnnounceActivity {
   pub(crate) actor: ObjectId<ApubCommunity>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: AnnouncableActivities,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: AnnounceType,
index c904fc2186e632b64a2d4ffcc66190389c448a77..ecde0ce3a6506dacf3fb91ee2120d656db76d693 100644 (file)
@@ -11,8 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct BlockUserFromCommunity {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   pub(crate) target: ObjectId<ApubCommunity>,
   #[serde(rename = "type")]
index dc456b0b038dc8468015ade9ae2b0bc3550cde68..74619c81d13131cf6132e4fe698712e0ddec5c2a 100644 (file)
@@ -8,8 +8,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct RemoveMod {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: RemoveType,
index f08e0c3523f0c29ea2e15704a3db3f4349974b39..02218367bd3d74c7847d749ae790d47c0b987ad0 100644 (file)
@@ -11,8 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UndoBlockUserFromCommunity {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: BlockUserFromCommunity,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: UndoType,
index 9bdcded9a61c0f3fa21396fa8bde6be5a5f03758..bb9b561142970703c3eff4b684d94d1264661a2d 100644 (file)
@@ -13,9 +13,11 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UpdateCommunity {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   // TODO: would be nice to use a separate struct here, which only contains the fields updated here
   pub(crate) object: Box<Group>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: UpdateType,
index deef4c86211e8f62aeb899a114a80a9e75ba617c..091c0f97cb1a87f18b8dd978cf32c0b4aae54c44 100644 (file)
@@ -11,8 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct CreateOrUpdateComment {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Note,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(default)]
   pub(crate) tag: Vec<Mention>,
index db159c8609cabdbd432a1a4f1aa186c1633dd870..2061c88151f0ba7ea17a0fd121408b53ea9f9ee4 100644 (file)
@@ -10,8 +10,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct CreateOrUpdatePost {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Page,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: CreateOrUpdateType,
index 49adb6e6514dfc95028cf8d333c287f3acdb8e1b..a999e58ec6f0a1ac55fdb1a82cc78c51a4395c9b 100644 (file)
@@ -13,6 +13,7 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct Delete {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Tombstone,
   #[serde(rename = "type")]
index d760801700e284d187e1e873fdad65b7b1d908a2..ebd51f9640328dd15e5fdf5480d9b92ab6f70fdc 100644 (file)
@@ -11,8 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UndoDelete {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Delete,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: UndoType,
index 9a1767f2a0793e5c373d61c7e5549ff16e8f4561..d3f4fb33780bc6b07d5c127cd06665ed92ddb831 100644 (file)
@@ -11,8 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UndoVote {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Vote,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: UndoType,
index 065e3b31f6d3e40a7017dfa2c110f6ac33527f6a..ba5c629ce75b7d1b7328a242824e232ea0a131be 100644 (file)
@@ -15,8 +15,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct Vote {
   pub(crate) actor: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<PostOrComment>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: VoteType,
index be21f8f5769184e7ff98c338b4ab612f3bdc4695..39c606b00942fbb2f5a6f7df3bc8a93a60257575 100644 (file)
@@ -23,8 +23,10 @@ pub struct Note {
   pub(crate) r#type: NoteType,
   pub(crate) id: ObjectId<ApubComment>,
   pub(crate) attributed_to: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   #[serde(default)]
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   pub(crate) content: String,
   pub(crate) media_type: Option<MediaTypeHtml>,
index 2bd5cc6dd416f6cc4ed7c5c861102735f87105e8..1fca51e454d80a3b236d1c68febf00f90c152bbc 100644 (file)
@@ -24,8 +24,10 @@ pub struct Page {
   pub(crate) r#type: PageType,
   pub(crate) id: ObjectId<ApubPost>,
   pub(crate) attributed_to: ObjectId<ApubPerson>,
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   #[serde(default)]
+  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   pub(crate) name: String,
   pub(crate) content: Option<String>,