diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex index 0aa249c4c..6beeca225 100644 --- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex @@ -9,9 +9,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Object.Fetcher import Ecto.Changeset + require Logger + @primary_key false @derive Jason.Encoder @@ -63,6 +66,18 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do defp fix_replies(%{"replies" => replies} = data) when is_bitstring(replies), do: Map.drop(data, ["replies"]) + defp fix_replies(%{"replies" => %{"first" => first}} = data) do + with {:ok, %{"orderedItems" => replies}} <- + Fetcher.fetch_and_contain_remote_object_from_id(first) do + Map.put(data, "replies", replies) + else + {:error, e} -> + Logger.error("Could not fetch replies for #{first}") + IO.inspect(e) + Map.put(data, "replies", []) + end + end + defp fix_replies(data), do: data defp fix(data) do diff --git a/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex b/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex index 751021585..77aaf7f29 100644 --- a/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex @@ -68,6 +68,36 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do |> validate_required([:type, :name, :icon]) end + def changeset(struct, %{"type" => "Book"} = data) do + data = Map.put(data, "name", data["title"]) + + struct + |> cast(data, [:type, :name]) + |> validate_required([:type, :name]) + end + + def changeset(struct, %{"type" => "Edition"} = data) do + data = Map.put(data, "name", data["work"]) + + struct + |> cast(data, [:type, :name]) + |> validate_required([:type, :name]) + end + + def changeset(struct, %{"type" => "Work"} = data) do + data = Map.put(data, "name", data["lccn"]) + + struct + |> cast(data, [:type, :name]) + |> validate_required([:type, :name]) + end + + def changeset(struct, %{"type" => "Author"} = data) do + struct + |> cast(data, [:type, :name]) + |> validate_required([:type, :name]) + end + def icon_changeset(struct, data) do struct |> cast(data, [:type, :url]) diff --git a/test/fixtures/bookwyrm-article.json b/test/fixtures/bookwyrm-article.json new file mode 100644 index 000000000..66b34b688 --- /dev/null +++ b/test/fixtures/bookwyrm-article.json @@ -0,0 +1,35 @@ +{ + "@context": "https://www.w3.org/ns/activitystreams", + "attachment": [ + { + "id": null, + "name": "Death's End (The Three-Body Problem) (2018, Head of Zeus)", + "type": "Document", + "url": "https://bookwyrm.com/images/covers/e7a6a777-b3fa-44be-a819-33f3aa5187dd.jpeg" + } + ], + "attributedTo": "https://bookwyrm.com/user/TestUser", + "cc": [ + "https://bookwyrm.com/user/TestUser/followers" + ], + "content": "
review
", + "id": "https://bookwyrm.com/user/TestUser/review/17", + "inReplyToBook": "https://bookwyrm.com/book/2", + "name": "Review of \"Death's End (The Three-Body Problem)\": ab", + "published": "2022-01-07T16:07:43.665392+00:00", + "replies": { + "@context": "https://www.w3.org/ns/activitystreams", + "first": "https://bookwyrm.com/user/TestUser/review/17/replies?page=1", + "id": "https://bookwyrm.com/user/TestUser/review/17/replies", + "last": "https://bookwyrm.com/user/TestUser/review/17/replies?page=1", + "totalItems": 0, + "type": "OrderedCollection" + }, + "sensitive": false, + "tag": [], + "to": [ + "https://www.w3.org/ns/activitystreams#Public" + ], + "type": "Article", + "updated": "2022-01-07T16:14:08.267337+00:00" +} diff --git a/test/fixtures/bookwyrm-replies-collection.json b/test/fixtures/bookwyrm-replies-collection.json new file mode 100644 index 000000000..3f6d722f0 --- /dev/null +++ b/test/fixtures/bookwyrm-replies-collection.json @@ -0,0 +1,41 @@ +{ + "id": "https://bookwyrm.com/user/TestUser/review/17/replies?page=1", + "type": "OrderedCollectionPage", + "partOf": "https://bookwyrm.com/user/TestUser/review/17/replies", + "orderedItems": [ + { + "id": "https://bookwyrm.com/user/TestUser/status/18", + "type": "Note", + "published": "2022-01-07T16:07:51.111523+00:00", + "attributedTo": "https://bookwyrm.com/user/TestUser", + "content": "reply
", + "to": [ + "https://www.w3.org/ns/activitystreams#Public" + ], + "cc": [ + "https://bookwyrm.com/user/TestUser/followers", + "https://bookwyrm.com/user/TestUser" + ], + "replies": { + "id": "https://bookwyrm.com/user/TestUser/status/18/replies", + "type": "OrderedCollection", + "totalItems": 0, + "first": "https://bookwyrm.com/user/TestUser/status/18/replies?page=1", + "last": "https://bookwyrm.com/user/TestUser/status/18/replies?page=1", + "@context": "https://www.w3.org/ns/activitystreams" + }, + "inReplyTo": "https://bookwyrm.com/user/TestUser/review/17", + "tag": [ + { + "href": "https://bookwyrm.com/user/TestUser", + "name": "TestUser@bookwyrm.com", + "type": "Mention" + } + ], + "attachment": [], + "sensitive": false, + "@context": "https://www.w3.org/ns/activitystreams" + } + ], + "@context": "https://www.w3.org/ns/activitystreams" +} diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs index 720c17d8d..2bd1e46c1 100644 --- a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs @@ -31,5 +31,26 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest test "a basic note validates", %{note: note} do %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note) end + + test "a note with a remote replies collection should validate", _ do + insert(:user, %{ap_id: "https://bookwyrm.com/user/TestUser"}) + collection = File.read!("test/fixtures/bookwyrm-replies-collection.json") + + Tesla.Mock.mock(fn %{ + method: :get, + url: "https://bookwyrm.com/user/TestUser/review/17/replies?page=1" + } -> + %Tesla.Env{ + status: 200, + body: collection, + headers: HttpRequestMock.activitypub_object_headers() + } + end) + + note = Jason.decode!(File.read!("test/fixtures/bookwyrm-article.json")) + + %{valid?: true, changes: %{replies: ["https://bookwyrm.com/user/TestUser/status/18"]}} = + ArticleNotePageValidator.cast_and_validate(note) + end end end