Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into remake-remodel-dms
[akkoma] / test / web / activity_pub / object_validator_test.exs
index 4d90a0cf347abf5232ca1685949a11dd3d896416..da33d3dbc0b8b732c7a30e264cbc650ee91201a9 100644 (file)
@@ -2,18 +2,236 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
   use Pleroma.DataCase
 
   alias Pleroma.Object
   use Pleroma.DataCase
 
   alias Pleroma.Object
+  alias Pleroma.Web.ActivityPub.ActivityPub
   alias Pleroma.Web.ActivityPub.Builder
   alias Pleroma.Web.ActivityPub.ObjectValidator
   alias Pleroma.Web.ActivityPub.Builder
   alias Pleroma.Web.ActivityPub.ObjectValidator
+  alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
   alias Pleroma.Web.ActivityPub.Utils
   alias Pleroma.Web.CommonAPI
 
   import Pleroma.Factory
 
   alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
   alias Pleroma.Web.ActivityPub.Utils
   alias Pleroma.Web.CommonAPI
 
   import Pleroma.Factory
 
+  describe "attachments" do
+    test "it turns mastodon attachments into our attachments" do
+      attachment = %{
+        "url" =>
+          "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
+        "type" => "Document",
+        "name" => nil,
+        "mediaType" => "image/jpeg"
+      }
+
+      {:ok, attachment} =
+        AttachmentValidator.cast_and_validate(attachment)
+        |> Ecto.Changeset.apply_action(:insert)
+
+      assert [
+               %{
+                 href:
+                   "http://mastodon.example.org/system/media_attachments/files/000/000/002/original/334ce029e7bfb920.jpg",
+                 type: "Link",
+                 mediaType: "image/jpeg"
+               }
+             ] = attachment.url
+    end
+  end
+
+  describe "chat message create activities" do
+    test "it is invalid if the object already exists" do
+      user = insert(:user)
+      recipient = insert(:user)
+      {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "hey")
+      object = Object.normalize(activity, false)
+
+      {:ok, create_data, _} = Builder.create(user, object.data, [recipient.ap_id])
+
+      {:error, cng} = ObjectValidator.validate(create_data, [])
+
+      assert {:object, {"The object to create already exists", []}} in cng.errors
+    end
+
+    test "it is invalid if the object data has a different `to` or `actor` field" do
+      user = insert(:user)
+      recipient = insert(:user)
+      {:ok, object_data, _} = Builder.chat_message(recipient, user.ap_id, "Hey")
+
+      {:ok, create_data, _} = Builder.create(user, object_data, [recipient.ap_id])
+
+      {:error, cng} = ObjectValidator.validate(create_data, [])
+
+      assert {:to, {"Recipients don't match with object recipients", []}} in cng.errors
+      assert {:actor, {"Actor doesn't match with object actor", []}} in cng.errors
+    end
+  end
+
+  describe "chat messages" do
+    setup do
+      clear_config([:instance, :remote_limit])
+      user = insert(:user)
+      recipient = insert(:user, local: false)
+
+      {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey :firefox:")
+
+      %{user: user, recipient: recipient, valid_chat_message: valid_chat_message}
+    end
+
+    test "validates for a basic object we build", %{valid_chat_message: valid_chat_message} do
+      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
+
+      assert Map.put(valid_chat_message, "attachment", nil) == object
+    end
+
+    test "validates for a basic object with an attachment", %{
+      valid_chat_message: valid_chat_message,
+      user: user
+    } do
+      file = %Plug.Upload{
+        content_type: "image/jpg",
+        path: Path.absname("test/fixtures/image.jpg"),
+        filename: "an_image.jpg"
+      }
+
+      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
+
+      valid_chat_message =
+        valid_chat_message
+        |> Map.put("attachment", attachment.data)
+
+      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
+
+      assert object["attachment"]
+    end
+
+    test "validates for a basic object with an attachment but without content", %{
+      valid_chat_message: valid_chat_message,
+      user: user
+    } do
+      file = %Plug.Upload{
+        content_type: "image/jpg",
+        path: Path.absname("test/fixtures/image.jpg"),
+        filename: "an_image.jpg"
+      }
+
+      {:ok, attachment} = ActivityPub.upload(file, actor: user.ap_id)
+
+      valid_chat_message =
+        valid_chat_message
+        |> Map.put("attachment", attachment.data)
+        |> Map.delete("content")
+
+      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, [])
+
+      assert object["attachment"]
+    end
+
+    test "does not validate if the message has no content", %{
+      valid_chat_message: valid_chat_message
+    } do
+      contentless =
+        valid_chat_message
+        |> Map.delete("content")
+
+      refute match?({:ok, _object, _meta}, ObjectValidator.validate(contentless, []))
+    end
+
+    test "does not validate if the message is longer than the remote_limit", %{
+      valid_chat_message: valid_chat_message
+    } do
+      Pleroma.Config.put([:instance, :remote_limit], 2)
+      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
+    end
+
+    test "does not validate if the recipient is blocking the actor", %{
+      valid_chat_message: valid_chat_message,
+      user: user,
+      recipient: recipient
+    } do
+      Pleroma.User.block(recipient, user)
+      refute match?({:ok, _object, _meta}, ObjectValidator.validate(valid_chat_message, []))
+    end
+
+    test "does not validate if the actor or the recipient is not in our system", %{
+      valid_chat_message: valid_chat_message
+    } do
+      chat_message =
+        valid_chat_message
+        |> Map.put("actor", "https://raymoo.com/raymoo")
+
+      {:error, _} = ObjectValidator.validate(chat_message, [])
+
+      chat_message =
+        valid_chat_message
+        |> Map.put("to", ["https://raymoo.com/raymoo"])
+
+      {:error, _} = ObjectValidator.validate(chat_message, [])
+    end
+
+    test "does not validate for a message with multiple recipients", %{
+      valid_chat_message: valid_chat_message,
+      user: user,
+      recipient: recipient
+    } do
+      chat_message =
+        valid_chat_message
+        |> Map.put("to", [user.ap_id, recipient.ap_id])
+
+      assert {:error, _} = ObjectValidator.validate(chat_message, [])
+    end
+
+    test "does not validate if it doesn't concern local users" do
+      user = insert(:user, local: false)
+      recipient = insert(:user, local: false)
+
+      {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "hey")
+      assert {:error, _} = ObjectValidator.validate(valid_chat_message, [])
+    end
+  end
+
+  describe "EmojiReacts" do
+    setup do
+      user = insert(:user)
+      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
+
+      object = Pleroma.Object.get_by_ap_id(post_activity.data["object"])
+
+      {:ok, valid_emoji_react, []} = Builder.emoji_react(user, object, "👌")
+
+      %{user: user, post_activity: post_activity, valid_emoji_react: valid_emoji_react}
+    end
+
+    test "it validates a valid EmojiReact", %{valid_emoji_react: valid_emoji_react} do
+      assert {:ok, _, _} = ObjectValidator.validate(valid_emoji_react, [])
+    end
+
+    test "it is not valid without a 'content' field", %{valid_emoji_react: valid_emoji_react} do
+      without_content =
+        valid_emoji_react
+        |> Map.delete("content")
+
+      {:error, cng} = ObjectValidator.validate(without_content, [])
+
+      refute cng.valid?
+      assert {:content, {"can't be blank", [validation: :required]}} in cng.errors
+    end
+
+    test "it is not valid with a non-emoji content field", %{valid_emoji_react: valid_emoji_react} do
+      without_emoji_content =
+        valid_emoji_react
+        |> Map.put("content", "x")
+
+      {:error, cng} = ObjectValidator.validate(without_emoji_content, [])
+
+      refute cng.valid?
+
+      assert {:content, {"must be a single character emoji", []}} in cng.errors
+    end
+  end
+
   describe "Undos" do
     setup do
       user = insert(:user)
   describe "Undos" do
     setup do
       user = insert(:user)
-      {:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"})
+      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
       {:ok, like} = CommonAPI.favorite(user, post_activity.id)
       {:ok, valid_like_undo, []} = Builder.undo(user, like)
 
       {:ok, like} = CommonAPI.favorite(user, post_activity.id)
       {:ok, valid_like_undo, []} = Builder.undo(user, like)
 
@@ -53,7 +271,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
   describe "deletes" do
     setup do
       user = insert(:user)
   describe "deletes" do
     setup do
       user = insert(:user)
-      {:ok, post_activity} = CommonAPI.post(user, %{"status" => "cancel me daddy"})
+      {:ok, post_activity} = CommonAPI.post(user, %{status: "cancel me daddy"})
 
       {:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"])
       {:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id)
 
       {:ok, valid_post_delete, _} = Builder.delete(user, post_activity.data["object"])
       {:ok, valid_user_delete, _} = Builder.delete(user, user.ap_id)
@@ -107,7 +325,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
       {:error, cng} = ObjectValidator.validate(missing_object, [])
 
       assert {:object, {"can't find object", []}} in cng.errors
       {:error, cng} = ObjectValidator.validate(missing_object, [])
 
       assert {:object, {"can't find object", []}} in cng.errors
-      assert length(cng.errors) == 1
     end
 
     test "it's invalid if the actor of the object and the actor of delete are from different domains",
     end
 
     test "it's invalid if the actor of the object and the actor of delete are from different domains",
@@ -146,7 +363,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
   describe "likes" do
     setup do
       user = insert(:user)
   describe "likes" do
     setup do
       user = insert(:user)
-      {:ok, post_activity} = CommonAPI.post(user, %{"status" => "uguu"})
+      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"})
 
       valid_like = %{
         "to" => [user.ap_id],
 
       valid_like = %{
         "to" => [user.ap_id],