Pipeline Ingestion: Page
authorHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Wed, 21 Oct 2020 08:23:10 +0000 (10:23 +0200)
committerHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Fri, 4 Jun 2021 18:06:33 +0000 (20:06 +0200)
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/object_validator.ex
lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex [moved from lib/pleroma/web/activity_pub/object_validators/article_note_validator.ex with 96% similarity]
lib/pleroma/web/activity_pub/side_effects.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
test/fixtures/tesla_mock/lemmy-page.json [new file with mode: 0644]
test/fixtures/tesla_mock/lemmy-user.json [new file with mode: 0644]
test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs [moved from test/pleroma/web/activity_pub/object_validators/article_note_validator_test.exs with 76% similarity]
test/pleroma/web/activity_pub/transmogrifier/page_handling_test.exs [new file with mode: 0644]

index 18368943d1a910bbfe213e5ba6b8ccef96798ed8..30b4f65d31845b22859781b33347eb20c3ced285 100644 (file)
@@ -88,7 +88,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   defp increase_replies_count_if_reply(_create_data), do: :noop
 
-  @object_types ~w[ChatMessage Question Answer Audio Video Event Article Note]
+  @object_types ~w[ChatMessage Question Answer Audio Video Event Article Note Page]
   @impl true
   def persist(%{"type" => type} = object, meta) when type in @object_types do
     with {:ok, object} <- Object.create(object) do
index 248a12a36827ec26c6274f65871737734776ecfa..e642916d8f9addcfca20504a59fb9a3c7a29a928 100644 (file)
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
   alias Pleroma.Web.ActivityPub.ObjectValidators.AddRemoveValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator
-  alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator
+  alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator
@@ -102,7 +102,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
         %{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity,
         meta
       )
-      when objtype in ~w[Question Answer Audio Video Event Article Note] do
+      when objtype in ~w[Question Answer Audio Video Event Article Note Page] do
     with {:ok, object_data} <- cast_and_apply(object),
          meta = Keyword.put(meta, :object_data, object_data |> stringify_keys),
          {:ok, create_activity} <-
@@ -115,15 +115,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
   end
 
   def validate(%{"type" => type} = object, meta)
-      when type in ~w[Event Question Audio Video Article Note] do
+      when type in ~w[Event Question Audio Video Article Note Page] do
     validator =
       case type do
         "Event" -> EventValidator
         "Question" -> QuestionValidator
         "Audio" -> AudioVideoValidator
         "Video" -> AudioVideoValidator
-        "Article" -> ArticleNoteValidator
-        "Note" -> ArticleNoteValidator
+        "Article" -> ArticleNotePageValidator
+        "Note" -> ArticleNotePageValidator
+        "Page" -> ArticleNotePageValidator
       end
 
     with {:ok, object} <-
@@ -195,8 +196,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
     EventValidator.cast_and_apply(object)
   end
 
-  def cast_and_apply(%{"type" => type} = object) when type in ~w[Article Note] do
-    ArticleNoteValidator.cast_and_apply(object)
+  def cast_and_apply(%{"type" => type} = object) when type in ~w[Article Note Page] do
+    ArticleNotePageValidator.cast_and_apply(object)
   end
 
   def cast_and_apply(o), do: {:error, {:validator_not_set, o}}
similarity index 96%
rename from lib/pleroma/web/activity_pub/object_validators/article_note_validator.ex
rename to lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
index 193f85f49292750bebcb60acdce1677cc6b44bf0..0d987116c8b00e9d88201a86ffdb5282800e78e7 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator do
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
   use Ecto.Schema
 
   alias Pleroma.EctoType.ActivityPub.ObjectValidators
@@ -113,7 +113,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator do
 
   defp validate_data(data_cng) do
     data_cng
-    |> validate_inclusion(:type, ["Article", "Note"])
+    |> validate_inclusion(:type, ["Article", "Note", "Page"])
     |> validate_required([:id, :actor, :attributedTo, :type, :context, :context_id])
     |> CommonValidations.validate_any_presence([:cc, :to])
     |> CommonValidations.validate_fields_match([:actor, :attributedTo])
index 674356d9a8a09e2df08d38541fa59c5bff70d7e8..3670de45c81f1f73a9a46a886b6d8f7ce2d1ff55 100644 (file)
@@ -436,7 +436,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
   end
 
   def handle_object_creation(%{"type" => objtype} = object, meta)
-      when objtype in ~w[Audio Video Question Event Article Note] do
+      when objtype in ~w[Audio Video Question Event Article Note Page] do
     with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do
       {:ok, object, meta}
     end
index 51c0cc86026a961b5045c611535831bd2af2dbc2..142af1a13bb9ca0e6e212332ee15323979c282b5 100644 (file)
@@ -353,29 +353,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     end)
   end
 
-  # Compatibility wrapper for Mastodon votes
-  defp handle_create(%{"object" => %{"type" => "Answer"}} = data, _user) do
-    handle_incoming(data)
-  end
-
-  defp handle_create(%{"object" => object} = data, user) do
-    %{
-      to: data["to"],
-      object: object,
-      actor: user,
-      context: object["context"],
-      local: false,
-      published: data["published"],
-      additional:
-        Map.take(data, [
-          "cc",
-          "directMessage",
-          "id"
-        ])
-    }
-    |> ActivityPub.create()
-  end
-
   def handle_incoming(data, options \\ [])
 
   # Flag objects are placed ahead of the ID check because Mastodon 2.8 and earlier send them
@@ -407,43 +384,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   def handle_incoming(%{"id" => id}, _options) when is_binary(id) and byte_size(id) < 8,
     do: :error
 
-  # TODO: validate those with a Ecto scheme
-  # - tags
-  # - emoji
-  def handle_incoming(
-        %{"type" => "Create", "object" => %{"type" => "Page"} = object} = data,
-        options
-      ) do
-    actor = Containment.get_actor(data)
-
-    with nil <- Activity.get_create_by_object_ap_id(object["id"]),
-         {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(actor) do
-      data =
-        data
-        |> Map.put("object", fix_object(object, options))
-        |> Map.put("actor", actor)
-        |> fix_addressing()
-
-      with {:ok, created_activity} <- handle_create(data, user) do
-        reply_depth = (options[:depth] || 0) + 1
-
-        if Federator.allowed_thread_distance?(reply_depth) do
-          for reply_id <- replies(object) do
-            Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
-              "id" => reply_id,
-              "depth" => reply_depth
-            })
-          end
-        end
-
-        {:ok, created_activity}
-      end
-    else
-      %Activity{} = activity -> {:ok, activity}
-      _e -> :error
-    end
-  end
-
   def handle_incoming(
         %{"type" => "Listen", "object" => %{"type" => "Audio"} = object} = data,
         options
@@ -507,7 +447,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
         %{"type" => "Create", "object" => %{"type" => objtype, "id" => obj_id}} = data,
         options
       )
-      when objtype in ~w{Question Answer ChatMessage Audio Video Event Article Note} do
+      when objtype in ~w{Question Answer ChatMessage Audio Video Event Article Note Page} do
     fetch_options = Keyword.put(options, :depth, (options[:depth] || 0) + 1)
 
     object =
diff --git a/test/fixtures/tesla_mock/lemmy-page.json b/test/fixtures/tesla_mock/lemmy-page.json
new file mode 100644 (file)
index 0000000..f07097a
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "commentsEnabled": true,
+  "sensitive": false,
+  "stickied": false,
+  "attributedTo": "https://enterprise.lemmy.ml/u/nutomic",
+  "summary": "Hello Federation!",
+  "url": "https://enterprise.lemmy.ml/pictrs/image/US52d9DPvf.jpg",
+  "image": {
+    "type": "Image",
+    "url": "https://enterprise.lemmy.ml/pictrs/image/lwFAcXHUjS.jpg"
+  },
+  "published": "2020-09-14T15:03:11.909105+00:00",
+  "to": "https://enterprise.lemmy.ml/c/main",
+  "@context": "https://www.w3.org/ns/activitystreams",
+  "id": "https://enterprise.lemmy.ml/post/3",
+  "type": "Page"
+}
diff --git a/test/fixtures/tesla_mock/lemmy-user.json b/test/fixtures/tesla_mock/lemmy-user.json
new file mode 100644 (file)
index 0000000..d0e9066
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  "publicKey": {
+    "id": "https://enterprise.lemmy.ml/u/nutomic#main-key",
+    "owner": "https://enterprise.lemmy.ml/u/nutomic",
+    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvfwAYPxp1gOk2HcCRoUd\nupoecvmnpzRc5Gu6/N3YQyOyRsrYuiYLNQq2cgM3kcU80ZeEetkwkYgXkRJOKu/b\nBWb7i1zt2tdr5k6lUdW8dfCyjht8ooFPQdov8J3QYHfgBHyUYxuCNfSujryxx2wu\nLQcdjRQa5NIWcomSO8OXmCF5/Yhg2XWCbtnlxEq6Y+AFddr1mAlTOy5pBr5d+xZz\njLw/U3CioNJ79yGi/sJhgp6IyJqtUSoN3b4BgRIEts2QVvn44W1rQy9wCbRYQrO1\nBcB9Wel4k3rJJK8uHg+LpHVMaZppkNaWGkMBhMbzr8qmIlcNWNi7cbMK/p5vyviy\nSwIDAQAB\n-----END PUBLIC KEY-----\n"
+  },
+  "inbox": "https://enterprise.lemmy.ml/u/nutomic/inbox",
+  "preferredUsername": "Nutomic",
+  "endpoints": {
+    "sharedInbox": "https://enterprise.lemmy.ml/inbox"
+  },
+  "summary": "some bio",
+  "icon": {
+    "type": "Image",
+    "url": "https://enterprise.lemmy.ml/pictrs/image/F6Z7QcWZRJ.jpg"
+  },
+  "image": {
+    "type": "Image",
+    "url": "https://enterprise.lemmy.ml:/pictrs/image/Q79N9oCDEG.png"
+  },
+  "published": "2020-09-14T14:54:53.080949+00:00",
+  "updated": "2020-10-14T10:58:28.139178+00:00",
+  "@context": "https://www.w3.org/ns/activitystreams",
+  "id": "https://enterprise.lemmy.ml/u/nutomic",
+  "type": "Person",
+  "name": "nutomic"
+}
similarity index 76%
rename from test/pleroma/web/activity_pub/object_validators/article_note_validator_test.exs
rename to test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
index e408c85c3e48f6ee76c88e1e4839fd3b8b31333c..720c17d8da7e731da5c134dfce4699c274ecf48e 100644 (file)
@@ -2,10 +2,10 @@
 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
-defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidatorTest do
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest do
   use Pleroma.DataCase, async: true
 
-  alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator
+  alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
   alias Pleroma.Web.ActivityPub.Utils
 
   import Pleroma.Factory
@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidatorTest do
     end
 
     test "a basic note validates", %{note: note} do
-      %{valid?: true} = ArticleNoteValidator.cast_and_validate(note)
+      %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
     end
   end
 end
diff --git a/test/pleroma/web/activity_pub/transmogrifier/page_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/page_handling_test.exs
new file mode 100644 (file)
index 0000000..4ac71e0
--- /dev/null
@@ -0,0 +1,36 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.PageHandlingTest do
+  use Oban.Testing, repo: Pleroma.Repo
+  use Pleroma.DataCase
+
+  alias Pleroma.Object.Fetcher
+
+  test "Lemmy Page" do
+    Tesla.Mock.mock(fn
+      %{url: "https://enterprise.lemmy.ml/post/3"} ->
+        %Tesla.Env{
+          status: 200,
+          headers: [{"content-type", "application/activity+json"}],
+          body: File.read!("test/fixtures/tesla_mock/lemmy-page.json")
+        }
+
+      %{url: "https://enterprise.lemmy.ml/u/nutomic"} ->
+        %Tesla.Env{
+          status: 200,
+          headers: [{"content-type", "application/activity+json"}],
+          body: File.read!("test/fixtures/tesla_mock/lemmy-user.json")
+        }
+    end)
+
+    {:ok, object} = Fetcher.fetch_object_from_id("https://enterprise.lemmy.ml/post/3")
+
+    assert object.data["summary"] == "Hello Federation!"
+    assert object.data["published"] == "2020-09-14T15:03:11.909105Z"
+
+    # WAT
+    assert object.data["url"] == "https://enterprise.lemmy.ml/pictrs/image/US52d9DPvf.jpg"
+  end
+end