diff options
Diffstat (limited to 'test/web/activity_pub')
5 files changed, 355 insertions, 0 deletions
| diff --git a/test/web/activity_pub/object_validator_test.exs b/test/web/activity_pub/object_validator_test.exs index f382adf3e..6164d176d 100644 --- a/test/web/activity_pub/object_validator_test.exs +++ b/test/web/activity_pub/object_validator_test.exs @@ -2,14 +2,160 @@ 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 "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 "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) diff --git a/test/web/activity_pub/object_validators/types/object_id_test.exs b/test/web/activity_pub/object_validators/types/object_id_test.exs index 834213182..c8911948e 100644 --- a/test/web/activity_pub/object_validators/types/object_id_test.exs +++ b/test/web/activity_pub/object_validators/types/object_id_test.exs @@ -1,3 +1,7 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only +  defmodule Pleroma.Web.ObjectValidators.Types.ObjectIDTest do    alias Pleroma.Web.ActivityPub.ObjectValidators.Types.ObjectID    use Pleroma.DataCase diff --git a/test/web/activity_pub/object_validators/types/safe_text_test.exs b/test/web/activity_pub/object_validators/types/safe_text_test.exs new file mode 100644 index 000000000..59ed0a1fe --- /dev/null +++ b/test/web/activity_pub/object_validators/types/safe_text_test.exs @@ -0,0 +1,23 @@ +# 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.Types.SafeTextTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.ObjectValidators.Types.SafeText + +  test "it lets normal text go through" do +    text = "hey how are you" +    assert {:ok, text} == SafeText.cast(text) +  end + +  test "it removes html tags from text" do +    text = "hey look xss <script>alert('foo')</script>" +    assert {:ok, "hey look xss alert('foo')"} == SafeText.cast(text) +  end + +  test "errors for non-text" do +    assert :error == SafeText.cast(1) +  end +end diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index b29a7a7be..b618d3322 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do    use Pleroma.DataCase    alias Pleroma.Activity +  alias Pleroma.Chat    alias Pleroma.Notification    alias Pleroma.Object    alias Pleroma.Repo @@ -223,4 +224,69 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do        assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)      end    end + +  describe "creation of ChatMessages" do +    test "notifies the recipient" do +      author = insert(:user, local: false) +      recipient = insert(:user, local: true) + +      {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + +      {:ok, create_activity_data, _meta} = +        Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + +      {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + +      {:ok, _create_activity, _meta} = +        SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + +      assert Repo.get_by(Notification, user_id: recipient.id, activity_id: create_activity.id) +    end + +    test "it creates a Chat for the local users and bumps the unread count" do +      author = insert(:user, local: false) +      recipient = insert(:user, local: true) + +      {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + +      {:ok, create_activity_data, _meta} = +        Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + +      {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + +      {:ok, _create_activity, _meta} = +        SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + +      # An object is created +      assert Object.get_by_ap_id(chat_message_data["id"]) + +      # The remote user won't get a chat +      chat = Chat.get(author.id, recipient.ap_id) +      refute chat + +      # The local user will get a chat +      chat = Chat.get(recipient.id, author.ap_id) +      assert chat + +      author = insert(:user, local: true) +      recipient = insert(:user, local: true) + +      {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey") + +      {:ok, create_activity_data, _meta} = +        Builder.create(author, chat_message_data["id"], [recipient.ap_id]) + +      {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + +      {:ok, _create_activity, _meta} = +        SideEffects.handle(create_activity, local: false, object_data: chat_message_data) + +      # Both users are local and get the chat +      chat = Chat.get(author.id, recipient.ap_id) +      assert chat + +      chat = Chat.get(recipient.id, author.ap_id) +      assert chat +    end +  end  end diff --git a/test/web/activity_pub/transmogrifier/chat_message_test.exs b/test/web/activity_pub/transmogrifier/chat_message_test.exs new file mode 100644 index 000000000..85644d787 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/chat_message_test.exs @@ -0,0 +1,116 @@ +# 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.ChatMessageTest do +  use Pleroma.DataCase + +  import Pleroma.Factory + +  alias Pleroma.Activity +  alias Pleroma.Chat +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  describe "handle_incoming" do +    test "it rejects messages that don't contain content" do +      data = +        File.read!("test/fixtures/create-chat-message.json") +        |> Poison.decode!() + +      object = +        data["object"] +        |> Map.delete("content") + +      data = +        data +        |> Map.put("object", object) + +      _author = +        insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) + +      _recipient = +        insert(:user, +          ap_id: List.first(data["to"]), +          local: true, +          last_refreshed_at: DateTime.utc_now() +        ) + +      {:error, _} = Transmogrifier.handle_incoming(data) +    end + +    test "it rejects messages that don't concern local users" do +      data = +        File.read!("test/fixtures/create-chat-message.json") +        |> Poison.decode!() + +      _author = +        insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) + +      _recipient = +        insert(:user, +          ap_id: List.first(data["to"]), +          local: false, +          last_refreshed_at: DateTime.utc_now() +        ) + +      {:error, _} = Transmogrifier.handle_incoming(data) +    end + +    test "it rejects messages where the `to` field of activity and object don't match" do +      data = +        File.read!("test/fixtures/create-chat-message.json") +        |> Poison.decode!() + +      author = insert(:user, ap_id: data["actor"]) +      _recipient = insert(:user, ap_id: List.first(data["to"])) + +      data = +        data +        |> Map.put("to", author.ap_id) + +      assert match?({:error, _}, Transmogrifier.handle_incoming(data)) +      refute Object.get_by_ap_id(data["object"]["id"]) +    end + +    test "it fetches the actor if they aren't in our system" do +      Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end) + +      data = +        File.read!("test/fixtures/create-chat-message.json") +        |> Poison.decode!() +        |> Map.put("actor", "http://mastodon.example.org/users/admin") +        |> put_in(["object", "actor"], "http://mastodon.example.org/users/admin") + +      _recipient = insert(:user, ap_id: List.first(data["to"]), local: true) + +      {:ok, %Activity{} = _activity} = Transmogrifier.handle_incoming(data) +    end + +    test "it inserts it and creates a chat" do +      data = +        File.read!("test/fixtures/create-chat-message.json") +        |> Poison.decode!() + +      author = +        insert(:user, ap_id: data["actor"], local: false, last_refreshed_at: DateTime.utc_now()) + +      recipient = insert(:user, ap_id: List.first(data["to"]), local: true) + +      {:ok, %Activity{} = activity} = Transmogrifier.handle_incoming(data) +      assert activity.local == false + +      assert activity.actor == author.ap_id +      assert activity.recipients == [recipient.ap_id, author.ap_id] + +      %Object{} = object = Object.get_by_ap_id(activity.data["object"]) + +      assert object +      assert object.data["content"] == "You expected a cute girl? Too bad. alert('XSS')" +      assert match?(%{"firefox" => _}, object.data["emoji"]) + +      refute Chat.get(author.id, recipient.ap_id) +      assert Chat.get(recipient.id, author.ap_id) +    end +  end +end | 
