diff options
Diffstat (limited to 'test/web')
11 files changed, 814 insertions, 684 deletions
| diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs deleted file mode 100644 index f38bf7e08..000000000 --- a/test/web/activity_pub/object_validator_test.exs +++ /dev/null @@ -1,684 +0,0 @@ -defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do -  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.ObjectValidators.AttachmentValidator -  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator -  alias Pleroma.Web.ActivityPub.Utils -  alias Pleroma.Web.CommonAPI - -  import Pleroma.Factory - -  describe "attachments" do -    test "works with honkerific attachments" do -      attachment = %{ -        "mediaType" => "", -        "name" => "", -        "summary" => "298p3RG7j27tfsZ9RQ.jpg", -        "type" => "Document", -        "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg" -      } - -      assert {:ok, attachment} = -               AttachmentValidator.cast_and_validate(attachment) -               |> Ecto.Changeset.apply_action(:insert) - -      assert attachment.mediaType == "application/octet-stream" -    end - -    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 - -      assert attachment.mediaType == "image/jpeg" -    end - -    test "it handles our own uploads" do -      user = insert(:user) - -      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) - -      {:ok, attachment} = -        attachment.data -        |> AttachmentValidator.cast_and_validate() -        |> Ecto.Changeset.apply_action(:insert) - -      assert attachment.mediaType == "image/jpeg" -    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 "let's through some basic html", %{user: user, recipient: recipient} do -      {:ok, valid_chat_message, _} = -        Builder.chat_message( -          user, -          recipient.ap_id, -          "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>" -        ) - -      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) - -      assert object["content"] == -               "hey <a href=\"https://example.org\">example</a> alert('uguu')" -    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 in an array", %{ -      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) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) -      {:ok, like} = CommonAPI.favorite(user, post_activity.id) -      {:ok, valid_like_undo, []} = Builder.undo(user, like) - -      %{user: user, like: like, valid_like_undo: valid_like_undo} -    end - -    test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do -      assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, []) -    end - -    test "it does not validate if the actor of the undo is not the actor of the object", %{ -      valid_like_undo: valid_like_undo -    } do -      other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo") - -      bad_actor = -        valid_like_undo -        |> Map.put("actor", other_user.ap_id) - -      {:error, cng} = ObjectValidator.validate(bad_actor, []) - -      assert {:actor, {"not the same as object actor", []}} in cng.errors -    end - -    test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do -      missing_object = -        valid_like_undo -        |> Map.put("object", "https://gensokyo.2hu/objects/1") - -      {:error, cng} = ObjectValidator.validate(missing_object, []) - -      assert {:object, {"can't find object", []}} in cng.errors -      assert length(cng.errors) == 1 -    end -  end - -  describe "deletes" do -    setup do -      user = insert(:user) -      {: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) - -      %{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete} -    end - -    test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do -      {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, []) - -      assert valid_post_delete["deleted_activity_id"] -    end - -    test "it is invalid if the object isn't in a list of certain types", %{ -      valid_post_delete: valid_post_delete -    } do -      object = Object.get_by_ap_id(valid_post_delete["object"]) - -      data = -        object.data -        |> Map.put("type", "Like") - -      {:ok, _object} = -        object -        |> Ecto.Changeset.change(%{data: data}) -        |> Object.update_and_set_cache() - -      {:error, cng} = ObjectValidator.validate(valid_post_delete, []) -      assert {:object, {"object not in allowed types", []}} in cng.errors -    end - -    test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do -      assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, [])) -    end - -    test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do -      no_id = -        valid_post_delete -        |> Map.delete("id") - -      {:error, cng} = ObjectValidator.validate(no_id, []) - -      assert {:id, {"can't be blank", [validation: :required]}} in cng.errors -    end - -    test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do -      missing_object = -        valid_post_delete -        |> Map.put("object", "http://does.not/exist") - -      {:error, cng} = ObjectValidator.validate(missing_object, []) - -      assert {:object, {"can't find object", []}} in cng.errors -    end - -    test "it's invalid if the actor of the object and the actor of delete are from different domains", -         %{valid_post_delete: valid_post_delete} do -      valid_user = insert(:user) - -      valid_other_actor = -        valid_post_delete -        |> Map.put("actor", valid_user.ap_id) - -      assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, [])) - -      invalid_other_actor = -        valid_post_delete -        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") - -      {:error, cng} = ObjectValidator.validate(invalid_other_actor, []) - -      assert {:actor, {"is not allowed to delete object", []}} in cng.errors -    end - -    test "it's valid if the actor of the object is a local superuser", -         %{valid_post_delete: valid_post_delete} do -      user = -        insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo") - -      valid_other_actor = -        valid_post_delete -        |> Map.put("actor", user.ap_id) - -      {:ok, _, meta} = ObjectValidator.validate(valid_other_actor, []) -      assert meta[:do_not_federate] -    end -  end - -  describe "likes" do -    setup do -      user = insert(:user) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) - -      valid_like = %{ -        "to" => [user.ap_id], -        "cc" => [], -        "type" => "Like", -        "id" => Utils.generate_activity_id(), -        "object" => post_activity.data["object"], -        "actor" => user.ap_id, -        "context" => "a context" -      } - -      %{valid_like: valid_like, user: user, post_activity: post_activity} -    end - -    test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do -      {:ok, object, _meta} = ObjectValidator.validate(valid_like, []) - -      assert "id" in Map.keys(object) -    end - -    test "is valid for a valid object", %{valid_like: valid_like} do -      assert LikeValidator.cast_and_validate(valid_like).valid? -    end - -    test "sets the 'to' field to the object actor if no recipients are given", %{ -      valid_like: valid_like, -      user: user -    } do -      without_recipients = -        valid_like -        |> Map.delete("to") - -      {:ok, object, _meta} = ObjectValidator.validate(without_recipients, []) - -      assert object["to"] == [user.ap_id] -    end - -    test "sets the context field to the context of the object if no context is given", %{ -      valid_like: valid_like, -      post_activity: post_activity -    } do -      without_context = -        valid_like -        |> Map.delete("context") - -      {:ok, object, _meta} = ObjectValidator.validate(without_context, []) - -      assert object["context"] == post_activity.data["context"] -    end - -    test "it errors when the actor is missing or not known", %{valid_like: valid_like} do -      without_actor = Map.delete(valid_like, "actor") - -      refute LikeValidator.cast_and_validate(without_actor).valid? - -      with_invalid_actor = Map.put(valid_like, "actor", "invalidactor") - -      refute LikeValidator.cast_and_validate(with_invalid_actor).valid? -    end - -    test "it errors when the object is missing or not known", %{valid_like: valid_like} do -      without_object = Map.delete(valid_like, "object") - -      refute LikeValidator.cast_and_validate(without_object).valid? - -      with_invalid_object = Map.put(valid_like, "object", "invalidobject") - -      refute LikeValidator.cast_and_validate(with_invalid_object).valid? -    end - -    test "it errors when the actor has already like the object", %{ -      valid_like: valid_like, -      user: user, -      post_activity: post_activity -    } do -      _like = CommonAPI.favorite(user, post_activity.id) - -      refute LikeValidator.cast_and_validate(valid_like).valid? -    end - -    test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do -      wrapped_like = -        valid_like -        |> Map.put("actor", %{"id" => valid_like["actor"]}) -        |> Map.put("object", %{"id" => valid_like["object"]}) - -      validated = LikeValidator.cast_and_validate(wrapped_like) - -      assert validated.valid? - -      assert {:actor, valid_like["actor"]} in validated.changes -      assert {:object, valid_like["object"]} in validated.changes -    end -  end - -  describe "announces" do -    setup do -      user = insert(:user) -      announcer = insert(:user) -      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) - -      object = Object.normalize(post_activity, false) -      {:ok, valid_announce, []} = Builder.announce(announcer, object) - -      %{ -        valid_announce: valid_announce, -        user: user, -        post_activity: post_activity, -        announcer: announcer -      } -    end - -    test "returns ok for a valid announce", %{valid_announce: valid_announce} do -      assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, []) -    end - -    test "returns an error if the object can't be found", %{valid_announce: valid_announce} do -      without_object = -        valid_announce -        |> Map.delete("object") - -      {:error, cng} = ObjectValidator.validate(without_object, []) - -      assert {:object, {"can't be blank", [validation: :required]}} in cng.errors - -      nonexisting_object = -        valid_announce -        |> Map.put("object", "https://gensokyo.2hu/objects/99999999") - -      {:error, cng} = ObjectValidator.validate(nonexisting_object, []) - -      assert {:object, {"can't find object", []}} in cng.errors -    end - -    test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do -      nonexisting_actor = -        valid_announce -        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") - -      {:error, cng} = ObjectValidator.validate(nonexisting_actor, []) - -      assert {:actor, {"can't find user", []}} in cng.errors -    end - -    test "returns an error if the actor already announced the object", %{ -      valid_announce: valid_announce, -      announcer: announcer, -      post_activity: post_activity -    } do -      _announce = CommonAPI.repeat(post_activity.id, announcer) - -      {:error, cng} = ObjectValidator.validate(valid_announce, []) - -      assert {:actor, {"already announced this object", []}} in cng.errors -      assert {:object, {"already announced by this actor", []}} in cng.errors -    end - -    test "returns an error if the actor can't announce the object", %{ -      announcer: announcer, -      user: user -    } do -      {:ok, post_activity} = -        CommonAPI.post(user, %{status: "a secret post", visibility: "private"}) - -      object = Object.normalize(post_activity, false) - -      # Another user can't announce it -      {:ok, announce, []} = Builder.announce(announcer, object, public: false) - -      {:error, cng} = ObjectValidator.validate(announce, []) - -      assert {:actor, {"can not announce this object", []}} in cng.errors - -      # The actor of the object can announce it -      {:ok, announce, []} = Builder.announce(user, object, public: false) - -      assert {:ok, _, _} = ObjectValidator.validate(announce, []) - -      # The actor of the object can not announce it publicly -      {:ok, announce, []} = Builder.announce(user, object, public: true) - -      {:error, cng} = ObjectValidator.validate(announce, []) - -      assert {:actor, {"can not announce this object publicly", []}} in cng.errors -    end -  end - -  describe "updates" do -    setup do -      user = insert(:user) - -      object = %{ -        "id" => user.ap_id, -        "name" => "A new name", -        "summary" => "A new bio" -      } - -      {:ok, valid_update, []} = Builder.update(user, object) - -      %{user: user, valid_update: valid_update} -    end - -    test "validates a basic object", %{valid_update: valid_update} do -      assert {:ok, _update, []} = ObjectValidator.validate(valid_update, []) -    end - -    test "returns an error if the object can't be updated by the actor", %{ -      valid_update: valid_update -    } do -      other_user = insert(:user) - -      update = -        valid_update -        |> Map.put("actor", other_user.ap_id) - -      assert {:error, _cng} = ObjectValidator.validate(update, []) -    end -  end - -  describe "blocks" do -    setup do -      user = insert(:user, local: false) -      blocked = insert(:user) - -      {:ok, valid_block, []} = Builder.block(user, blocked) - -      %{user: user, valid_block: valid_block} -    end - -    test "validates a basic object", %{ -      valid_block: valid_block -    } do -      assert {:ok, _block, []} = ObjectValidator.validate(valid_block, []) -    end - -    test "returns an error if we don't know the blocked user", %{ -      valid_block: valid_block -    } do -      block = -        valid_block -        |> Map.put("object", "https://gensokyo.2hu/users/raymoo") - -      assert {:error, _cng} = ObjectValidator.validate(block, []) -    end -  end -end diff --git a/test/web/activity_pub/object_validators/announce_validation_test.exs b/test/web/activity_pub/object_validators/announce_validation_test.exs new file mode 100644 index 000000000..623342f76 --- /dev/null +++ b/test/web/activity_pub/object_validators/announce_validation_test.exs @@ -0,0 +1,106 @@ +# 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.ObjectValidators.AnnouncValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "announces" do +    setup do +      user = insert(:user) +      announcer = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) + +      object = Object.normalize(post_activity, false) +      {:ok, valid_announce, []} = Builder.announce(announcer, object) + +      %{ +        valid_announce: valid_announce, +        user: user, +        post_activity: post_activity, +        announcer: announcer +      } +    end + +    test "returns ok for a valid announce", %{valid_announce: valid_announce} do +      assert {:ok, _object, _meta} = ObjectValidator.validate(valid_announce, []) +    end + +    test "returns an error if the object can't be found", %{valid_announce: valid_announce} do +      without_object = +        valid_announce +        |> Map.delete("object") + +      {:error, cng} = ObjectValidator.validate(without_object, []) + +      assert {:object, {"can't be blank", [validation: :required]}} in cng.errors + +      nonexisting_object = +        valid_announce +        |> Map.put("object", "https://gensokyo.2hu/objects/99999999") + +      {:error, cng} = ObjectValidator.validate(nonexisting_object, []) + +      assert {:object, {"can't find object", []}} in cng.errors +    end + +    test "returns an error if we don't have the actor", %{valid_announce: valid_announce} do +      nonexisting_actor = +        valid_announce +        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + +      {:error, cng} = ObjectValidator.validate(nonexisting_actor, []) + +      assert {:actor, {"can't find user", []}} in cng.errors +    end + +    test "returns an error if the actor already announced the object", %{ +      valid_announce: valid_announce, +      announcer: announcer, +      post_activity: post_activity +    } do +      _announce = CommonAPI.repeat(post_activity.id, announcer) + +      {:error, cng} = ObjectValidator.validate(valid_announce, []) + +      assert {:actor, {"already announced this object", []}} in cng.errors +      assert {:object, {"already announced by this actor", []}} in cng.errors +    end + +    test "returns an error if the actor can't announce the object", %{ +      announcer: announcer, +      user: user +    } do +      {:ok, post_activity} = +        CommonAPI.post(user, %{status: "a secret post", visibility: "private"}) + +      object = Object.normalize(post_activity, false) + +      # Another user can't announce it +      {:ok, announce, []} = Builder.announce(announcer, object, public: false) + +      {:error, cng} = ObjectValidator.validate(announce, []) + +      assert {:actor, {"can not announce this object", []}} in cng.errors + +      # The actor of the object can announce it +      {:ok, announce, []} = Builder.announce(user, object, public: false) + +      assert {:ok, _, _} = ObjectValidator.validate(announce, []) + +      # The actor of the object can not announce it publicly +      {:ok, announce, []} = Builder.announce(user, object, public: true) + +      {:error, cng} = ObjectValidator.validate(announce, []) + +      assert {:actor, {"can not announce this object publicly", []}} in cng.errors +    end +  end +end diff --git a/test/web/activity_pub/object_validators/attachment_validator_test.exs b/test/web/activity_pub/object_validators/attachment_validator_test.exs new file mode 100644 index 000000000..558bb3131 --- /dev/null +++ b/test/web/activity_pub/object_validators/attachment_validator_test.exs @@ -0,0 +1,74 @@ +# 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.ObjectValidators.AttachmentValidatorTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator + +  import Pleroma.Factory + +  describe "attachments" do +    test "works with honkerific attachments" do +      attachment = %{ +        "mediaType" => "", +        "name" => "", +        "summary" => "298p3RG7j27tfsZ9RQ.jpg", +        "type" => "Document", +        "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg" +      } + +      assert {:ok, attachment} = +               AttachmentValidator.cast_and_validate(attachment) +               |> Ecto.Changeset.apply_action(:insert) + +      assert attachment.mediaType == "application/octet-stream" +    end + +    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 + +      assert attachment.mediaType == "image/jpeg" +    end + +    test "it handles our own uploads" do +      user = insert(:user) + +      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) + +      {:ok, attachment} = +        attachment.data +        |> AttachmentValidator.cast_and_validate() +        |> Ecto.Changeset.apply_action(:insert) + +      assert attachment.mediaType == "image/jpeg" +    end +  end +end diff --git a/test/web/activity_pub/object_validators/block_validation_test.exs b/test/web/activity_pub/object_validators/block_validation_test.exs new file mode 100644 index 000000000..c08d4b2e8 --- /dev/null +++ b/test/web/activity_pub/object_validators/block_validation_test.exs @@ -0,0 +1,39 @@ +# 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.ObjectValidators.BlockValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator + +  import Pleroma.Factory + +  describe "blocks" do +    setup do +      user = insert(:user, local: false) +      blocked = insert(:user) + +      {:ok, valid_block, []} = Builder.block(user, blocked) + +      %{user: user, valid_block: valid_block} +    end + +    test "validates a basic object", %{ +      valid_block: valid_block +    } do +      assert {:ok, _block, []} = ObjectValidator.validate(valid_block, []) +    end + +    test "returns an error if we don't know the blocked user", %{ +      valid_block: valid_block +    } do +      block = +        valid_block +        |> Map.put("object", "https://gensokyo.2hu/users/raymoo") + +      assert {:error, _cng} = ObjectValidator.validate(block, []) +    end +  end +end diff --git a/test/web/activity_pub/object_validators/chat_validation_test.exs b/test/web/activity_pub/object_validators/chat_validation_test.exs new file mode 100644 index 000000000..ec1e497fa --- /dev/null +++ b/test/web/activity_pub/object_validators/chat_validation_test.exs @@ -0,0 +1,200 @@ +# 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.ObjectValidators.ChatValidationTest do +  use Pleroma.DataCase +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.ActivityPub +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  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 "let's through some basic html", %{user: user, recipient: recipient} do +      {:ok, valid_chat_message, _} = +        Builder.chat_message( +          user, +          recipient.ap_id, +          "hey <a href='https://example.org'>example</a> <script>alert('uguu')</script>" +        ) + +      assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + +      assert object["content"] == +               "hey <a href=\"https://example.org\">example</a> alert('uguu')" +    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 in an array", %{ +      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 +end diff --git a/test/web/activity_pub/object_validators/delete_validation_test.exs b/test/web/activity_pub/object_validators/delete_validation_test.exs new file mode 100644 index 000000000..42cd18298 --- /dev/null +++ b/test/web/activity_pub/object_validators/delete_validation_test.exs @@ -0,0 +1,106 @@ +# 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.ObjectValidators.DeleteValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "deletes" do +    setup do +      user = insert(:user) +      {: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) + +      %{user: user, valid_post_delete: valid_post_delete, valid_user_delete: valid_user_delete} +    end + +    test "it is valid for a post deletion", %{valid_post_delete: valid_post_delete} do +      {:ok, valid_post_delete, _} = ObjectValidator.validate(valid_post_delete, []) + +      assert valid_post_delete["deleted_activity_id"] +    end + +    test "it is invalid if the object isn't in a list of certain types", %{ +      valid_post_delete: valid_post_delete +    } do +      object = Object.get_by_ap_id(valid_post_delete["object"]) + +      data = +        object.data +        |> Map.put("type", "Like") + +      {:ok, _object} = +        object +        |> Ecto.Changeset.change(%{data: data}) +        |> Object.update_and_set_cache() + +      {:error, cng} = ObjectValidator.validate(valid_post_delete, []) +      assert {:object, {"object not in allowed types", []}} in cng.errors +    end + +    test "it is valid for a user deletion", %{valid_user_delete: valid_user_delete} do +      assert match?({:ok, _, _}, ObjectValidator.validate(valid_user_delete, [])) +    end + +    test "it's invalid if the id is missing", %{valid_post_delete: valid_post_delete} do +      no_id = +        valid_post_delete +        |> Map.delete("id") + +      {:error, cng} = ObjectValidator.validate(no_id, []) + +      assert {:id, {"can't be blank", [validation: :required]}} in cng.errors +    end + +    test "it's invalid if the object doesn't exist", %{valid_post_delete: valid_post_delete} do +      missing_object = +        valid_post_delete +        |> Map.put("object", "http://does.not/exist") + +      {:error, cng} = ObjectValidator.validate(missing_object, []) + +      assert {:object, {"can't find object", []}} in cng.errors +    end + +    test "it's invalid if the actor of the object and the actor of delete are from different domains", +         %{valid_post_delete: valid_post_delete} do +      valid_user = insert(:user) + +      valid_other_actor = +        valid_post_delete +        |> Map.put("actor", valid_user.ap_id) + +      assert match?({:ok, _, _}, ObjectValidator.validate(valid_other_actor, [])) + +      invalid_other_actor = +        valid_post_delete +        |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + +      {:error, cng} = ObjectValidator.validate(invalid_other_actor, []) + +      assert {:actor, {"is not allowed to delete object", []}} in cng.errors +    end + +    test "it's valid if the actor of the object is a local superuser", +         %{valid_post_delete: valid_post_delete} do +      user = +        insert(:user, local: true, is_moderator: true, ap_id: "https://gensokyo.2hu/users/raymoo") + +      valid_other_actor = +        valid_post_delete +        |> Map.put("actor", user.ap_id) + +      {:ok, _, meta} = ObjectValidator.validate(valid_other_actor, []) +      assert meta[:do_not_federate] +    end +  end +end diff --git a/test/web/activity_pub/object_validators/emoji_react_validation_test.exs b/test/web/activity_pub/object_validators/emoji_react_validation_test.exs new file mode 100644 index 000000000..582e6d785 --- /dev/null +++ b/test/web/activity_pub/object_validators/emoji_react_validation_test.exs @@ -0,0 +1,53 @@ +# 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.ObjectValidators.EmojiReactHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  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 +end diff --git a/test/web/activity_pub/object_validators/follow_validation_test.exs b/test/web/activity_pub/object_validators/follow_validation_test.exs new file mode 100644 index 000000000..6e1378be2 --- /dev/null +++ b/test/web/activity_pub/object_validators/follow_validation_test.exs @@ -0,0 +1,26 @@ +# 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.ObjectValidators.FollowValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator + +  import Pleroma.Factory + +  describe "Follows" do +    setup do +      follower = insert(:user) +      followed = insert(:user) + +      {:ok, valid_follow, []} = Builder.follow(follower, followed) +      %{follower: follower, followed: followed, valid_follow: valid_follow} +    end + +    test "validates a basic follow object", %{valid_follow: valid_follow} do +      assert {:ok, _follow, []} = ObjectValidator.validate(valid_follow, []) +    end +  end +end diff --git a/test/web/activity_pub/object_validators/like_validation_test.exs b/test/web/activity_pub/object_validators/like_validation_test.exs new file mode 100644 index 000000000..2c033b7e2 --- /dev/null +++ b/test/web/activity_pub/object_validators/like_validation_test.exs @@ -0,0 +1,113 @@ +# 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.ObjectValidators.LikeValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator +  alias Pleroma.Web.ActivityPub.Utils +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "likes" do +    setup do +      user = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) + +      valid_like = %{ +        "to" => [user.ap_id], +        "cc" => [], +        "type" => "Like", +        "id" => Utils.generate_activity_id(), +        "object" => post_activity.data["object"], +        "actor" => user.ap_id, +        "context" => "a context" +      } + +      %{valid_like: valid_like, user: user, post_activity: post_activity} +    end + +    test "returns ok when called in the ObjectValidator", %{valid_like: valid_like} do +      {:ok, object, _meta} = ObjectValidator.validate(valid_like, []) + +      assert "id" in Map.keys(object) +    end + +    test "is valid for a valid object", %{valid_like: valid_like} do +      assert LikeValidator.cast_and_validate(valid_like).valid? +    end + +    test "sets the 'to' field to the object actor if no recipients are given", %{ +      valid_like: valid_like, +      user: user +    } do +      without_recipients = +        valid_like +        |> Map.delete("to") + +      {:ok, object, _meta} = ObjectValidator.validate(without_recipients, []) + +      assert object["to"] == [user.ap_id] +    end + +    test "sets the context field to the context of the object if no context is given", %{ +      valid_like: valid_like, +      post_activity: post_activity +    } do +      without_context = +        valid_like +        |> Map.delete("context") + +      {:ok, object, _meta} = ObjectValidator.validate(without_context, []) + +      assert object["context"] == post_activity.data["context"] +    end + +    test "it errors when the actor is missing or not known", %{valid_like: valid_like} do +      without_actor = Map.delete(valid_like, "actor") + +      refute LikeValidator.cast_and_validate(without_actor).valid? + +      with_invalid_actor = Map.put(valid_like, "actor", "invalidactor") + +      refute LikeValidator.cast_and_validate(with_invalid_actor).valid? +    end + +    test "it errors when the object is missing or not known", %{valid_like: valid_like} do +      without_object = Map.delete(valid_like, "object") + +      refute LikeValidator.cast_and_validate(without_object).valid? + +      with_invalid_object = Map.put(valid_like, "object", "invalidobject") + +      refute LikeValidator.cast_and_validate(with_invalid_object).valid? +    end + +    test "it errors when the actor has already like the object", %{ +      valid_like: valid_like, +      user: user, +      post_activity: post_activity +    } do +      _like = CommonAPI.favorite(user, post_activity.id) + +      refute LikeValidator.cast_and_validate(valid_like).valid? +    end + +    test "it works when actor or object are wrapped in maps", %{valid_like: valid_like} do +      wrapped_like = +        valid_like +        |> Map.put("actor", %{"id" => valid_like["actor"]}) +        |> Map.put("object", %{"id" => valid_like["object"]}) + +      validated = LikeValidator.cast_and_validate(wrapped_like) + +      assert validated.valid? + +      assert {:actor, valid_like["actor"]} in validated.changes +      assert {:object, valid_like["object"]} in validated.changes +    end +  end +end diff --git a/test/web/activity_pub/object_validators/undo_validation_test.exs b/test/web/activity_pub/object_validators/undo_validation_test.exs new file mode 100644 index 000000000..75bbcc4b6 --- /dev/null +++ b/test/web/activity_pub/object_validators/undo_validation_test.exs @@ -0,0 +1,53 @@ +# 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.ObjectValidators.UndoHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  describe "Undos" do +    setup do +      user = insert(:user) +      {:ok, post_activity} = CommonAPI.post(user, %{status: "uguu"}) +      {:ok, like} = CommonAPI.favorite(user, post_activity.id) +      {:ok, valid_like_undo, []} = Builder.undo(user, like) + +      %{user: user, like: like, valid_like_undo: valid_like_undo} +    end + +    test "it validates a basic like undo", %{valid_like_undo: valid_like_undo} do +      assert {:ok, _, _} = ObjectValidator.validate(valid_like_undo, []) +    end + +    test "it does not validate if the actor of the undo is not the actor of the object", %{ +      valid_like_undo: valid_like_undo +    } do +      other_user = insert(:user, ap_id: "https://gensokyo.2hu/users/raymoo") + +      bad_actor = +        valid_like_undo +        |> Map.put("actor", other_user.ap_id) + +      {:error, cng} = ObjectValidator.validate(bad_actor, []) + +      assert {:actor, {"not the same as object actor", []}} in cng.errors +    end + +    test "it does not validate if the object is missing", %{valid_like_undo: valid_like_undo} do +      missing_object = +        valid_like_undo +        |> Map.put("object", "https://gensokyo.2hu/objects/1") + +      {:error, cng} = ObjectValidator.validate(missing_object, []) + +      assert {:object, {"can't find object", []}} in cng.errors +      assert length(cng.errors) == 1 +    end +  end +end diff --git a/test/web/activity_pub/object_validators/update_validation_test.exs b/test/web/activity_pub/object_validators/update_validation_test.exs new file mode 100644 index 000000000..5e80cf731 --- /dev/null +++ b/test/web/activity_pub/object_validators/update_validation_test.exs @@ -0,0 +1,44 @@ +# 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.ObjectValidators.UpdateHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator + +  import Pleroma.Factory + +  describe "updates" do +    setup do +      user = insert(:user) + +      object = %{ +        "id" => user.ap_id, +        "name" => "A new name", +        "summary" => "A new bio" +      } + +      {:ok, valid_update, []} = Builder.update(user, object) + +      %{user: user, valid_update: valid_update} +    end + +    test "validates a basic object", %{valid_update: valid_update} do +      assert {:ok, _update, []} = ObjectValidator.validate(valid_update, []) +    end + +    test "returns an error if the object can't be updated by the actor", %{ +      valid_update: valid_update +    } do +      other_user = insert(:user) + +      update = +        valid_update +        |> Map.put("actor", other_user.ap_id) + +      assert {:error, _cng} = ObjectValidator.validate(update, []) +    end +  end +end | 
