diff options
Diffstat (limited to 'test/web/activity_pub/transmogrifier')
5 files changed, 573 insertions, 1 deletions
| diff --git a/test/web/activity_pub/transmogrifier/announce_handling_test.exs b/test/web/activity_pub/transmogrifier/announce_handling_test.exs new file mode 100644 index 000000000..e895636b5 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/announce_handling_test.exs @@ -0,0 +1,172 @@ +# 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.AnnounceHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Transmogrifier +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  test "it works for incoming honk announces" do +    user = insert(:user, ap_id: "https://honktest/u/test", local: false) +    other_user = insert(:user) +    {:ok, post} = CommonAPI.post(other_user, %{status: "bonkeronk"}) + +    announce = %{ +      "@context" => "https://www.w3.org/ns/activitystreams", +      "actor" => "https://honktest/u/test", +      "id" => "https://honktest/u/test/bonk/1793M7B9MQ48847vdx", +      "object" => post.data["object"], +      "published" => "2019-06-25T19:33:58Z", +      "to" => "https://www.w3.org/ns/activitystreams#Public", +      "type" => "Announce" +    } + +    {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(announce) + +    object = Object.get_by_ap_id(post.data["object"]) + +    assert length(object.data["announcements"]) == 1 +    assert user.ap_id in object.data["announcements"] +  end + +  test "it works for incoming announces with actor being inlined (kroeg)" do +    data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!() + +    _user = insert(:user, local: false, ap_id: data["actor"]["id"]) +    other_user = insert(:user) + +    {:ok, post} = CommonAPI.post(other_user, %{status: "kroegeroeg"}) + +    data = +      data +      |> put_in(["object", "id"], post.data["object"]) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    assert data["actor"] == "https://puckipedia.com/" +  end + +  test "it works for incoming announces, fetching the announced object" do +    data = +      File.read!("test/fixtures/mastodon-announce.json") +      |> Poison.decode!() +      |> Map.put("object", "http://mastodon.example.org/users/admin/statuses/99541947525187367") + +    Tesla.Mock.mock(fn +      %{method: :get} -> +        %Tesla.Env{status: 200, body: File.read!("test/fixtures/mastodon-note-object.json")} +    end) + +    _user = insert(:user, local: false, ap_id: data["actor"]) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    assert data["actor"] == "http://mastodon.example.org/users/admin" +    assert data["type"] == "Announce" + +    assert data["id"] == +             "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" + +    assert data["object"] == +             "http://mastodon.example.org/users/admin/statuses/99541947525187367" + +    assert(Activity.get_create_by_object_ap_id(data["object"])) +  end + +  @tag capture_log: true +  test "it works for incoming announces with an existing activity" do +    user = insert(:user) +    {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) + +    data = +      File.read!("test/fixtures/mastodon-announce.json") +      |> Poison.decode!() +      |> Map.put("object", activity.data["object"]) + +    _user = insert(:user, local: false, ap_id: data["actor"]) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    assert data["actor"] == "http://mastodon.example.org/users/admin" +    assert data["type"] == "Announce" + +    assert data["id"] == +             "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" + +    assert data["object"] == activity.data["object"] + +    assert Activity.get_create_by_object_ap_id(data["object"]).id == activity.id +  end + +  # Ignore inlined activities for now +  @tag skip: true +  test "it works for incoming announces with an inlined activity" do +    data = +      File.read!("test/fixtures/mastodon-announce-private.json") +      |> Poison.decode!() + +    _user = +      insert(:user, +        local: false, +        ap_id: data["actor"], +        follower_address: data["actor"] <> "/followers" +      ) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    assert data["actor"] == "http://mastodon.example.org/users/admin" +    assert data["type"] == "Announce" + +    assert data["id"] == +             "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" + +    object = Object.normalize(data["object"]) + +    assert object.data["id"] == "http://mastodon.example.org/@admin/99541947525187368" +    assert object.data["content"] == "this is a private toot" +  end + +  @tag capture_log: true +  test "it rejects incoming announces with an inlined activity from another origin" do +    Tesla.Mock.mock(fn +      %{method: :get} -> %Tesla.Env{status: 404, body: ""} +    end) + +    data = +      File.read!("test/fixtures/bogus-mastodon-announce.json") +      |> Poison.decode!() + +    _user = insert(:user, local: false, ap_id: data["actor"]) + +    assert {:error, e} = Transmogrifier.handle_incoming(data) +  end + +  test "it does not clobber the addressing on announce activities" do +    user = insert(:user) +    {:ok, activity} = CommonAPI.post(user, %{status: "hey"}) + +    data = +      File.read!("test/fixtures/mastodon-announce.json") +      |> Poison.decode!() +      |> Map.put("object", Object.normalize(activity).data["id"]) +      |> Map.put("to", ["http://mastodon.example.org/users/admin/followers"]) +      |> Map.put("cc", []) + +    _user = +      insert(:user, +        local: false, +        ap_id: data["actor"], +        follower_address: "http://mastodon.example.org/users/admin/followers" +      ) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    assert data["to"] == ["http://mastodon.example.org/users/admin/followers"] +  end +end diff --git a/test/web/activity_pub/transmogrifier/block_handling_test.exs b/test/web/activity_pub/transmogrifier/block_handling_test.exs new file mode 100644 index 000000000..71f1a0ed5 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/block_handling_test.exs @@ -0,0 +1,63 @@ +# 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.BlockHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.User +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  import Pleroma.Factory + +  test "it works for incoming blocks" do +    user = insert(:user) + +    data = +      File.read!("test/fixtures/mastodon-block-activity.json") +      |> Poison.decode!() +      |> Map.put("object", user.ap_id) + +    blocker = insert(:user, ap_id: data["actor"]) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    assert data["type"] == "Block" +    assert data["object"] == user.ap_id +    assert data["actor"] == "http://mastodon.example.org/users/admin" + +    assert User.blocks?(blocker, user) +  end + +  test "incoming blocks successfully tear down any follow relationship" do +    blocker = insert(:user) +    blocked = insert(:user) + +    data = +      File.read!("test/fixtures/mastodon-block-activity.json") +      |> Poison.decode!() +      |> Map.put("object", blocked.ap_id) +      |> Map.put("actor", blocker.ap_id) + +    {:ok, blocker} = User.follow(blocker, blocked) +    {:ok, blocked} = User.follow(blocked, blocker) + +    assert User.following?(blocker, blocked) +    assert User.following?(blocked, blocker) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +    assert data["type"] == "Block" +    assert data["object"] == blocked.ap_id +    assert data["actor"] == blocker.ap_id + +    blocker = User.get_cached_by_ap_id(data["actor"]) +    blocked = User.get_cached_by_ap_id(data["object"]) + +    assert User.blocks?(blocker, blocked) + +    refute User.following?(blocker, blocked) +    refute User.following?(blocked, blocker) +  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..d6736dc3e --- /dev/null +++ b/test/web/activity_pub/transmogrifier/chat_message_test.exs @@ -0,0 +1,153 @@ +# 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 "handles chonks with attachment" do +      data = %{ +        "@context" => "https://www.w3.org/ns/activitystreams", +        "actor" => "https://honk.tedunangst.com/u/tedu", +        "id" => "https://honk.tedunangst.com/u/tedu/honk/x6gt8X8PcyGkQcXxzg1T", +        "object" => %{ +          "attachment" => [ +            %{ +              "mediaType" => "image/jpeg", +              "name" => "298p3RG7j27tfsZ9RQ.jpg", +              "summary" => "298p3RG7j27tfsZ9RQ.jpg", +              "type" => "Document", +              "url" => "https://honk.tedunangst.com/d/298p3RG7j27tfsZ9RQ.jpg" +            } +          ], +          "attributedTo" => "https://honk.tedunangst.com/u/tedu", +          "content" => "", +          "id" => "https://honk.tedunangst.com/u/tedu/chonk/26L4wl5yCbn4dr4y1b", +          "published" => "2020-05-18T01:13:03Z", +          "to" => [ +            "https://dontbulling.me/users/lain" +          ], +          "type" => "ChatMessage" +        }, +        "published" => "2020-05-18T01:13:03Z", +        "to" => [ +          "https://dontbulling.me/users/lain" +        ], +        "type" => "Create" +      } + +      _user = insert(:user, ap_id: data["actor"]) +      _user = insert(:user, ap_id: hd(data["to"])) + +      assert {:ok, _activity} = Transmogrifier.handle_incoming(data) +    end + +    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 diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs index 967389fae..06c39eed6 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -5,6 +5,7 @@  defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do    use Pleroma.DataCase    alias Pleroma.Activity +  alias Pleroma.Notification    alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.Web.ActivityPub.Transmogrifier @@ -12,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do    import Pleroma.Factory    import Ecto.Query +  import Mock    setup_all do      Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -57,9 +59,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do        activity = Repo.get(Activity, activity.id)        assert activity.data["state"] == "accept"        assert User.following?(User.get_cached_by_ap_id(data["actor"]), user) + +      [notification] = Notification.for_user(user) +      assert notification.type == "follow"      end -    test "with locked accounts, it does not create a follow or an accept" do +    test "with locked accounts, it does create a Follow, but not an Accept" do        user = insert(:user, locked: true)        data = @@ -81,6 +86,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do          |> Repo.all()        assert Enum.empty?(accepts) + +      [notification] = Notification.for_user(user) +      assert notification.type == "follow_request"      end      test "it works for follow requests when you are already followed, creating a new accept activity" do @@ -144,6 +152,23 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do        assert activity.data["state"] == "reject"      end +    test "it rejects incoming follow requests if the following errors for some reason" do +      user = insert(:user) + +      data = +        File.read!("test/fixtures/mastodon-follow-activity.json") +        |> Poison.decode!() +        |> Map.put("object", user.ap_id) + +      with_mock Pleroma.User, [:passthrough], follow: fn _, _ -> {:error, :testing} end do +        {:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data) + +        %Activity{} = activity = Activity.get_by_ap_id(id) + +        assert activity.data["state"] == "reject" +      end +    end +      test "it works for incoming follow requests from hubzilla" do        user = insert(:user) diff --git a/test/web/activity_pub/transmogrifier/user_update_handling_test.exs b/test/web/activity_pub/transmogrifier/user_update_handling_test.exs new file mode 100644 index 000000000..64636656c --- /dev/null +++ b/test/web/activity_pub/transmogrifier/user_update_handling_test.exs @@ -0,0 +1,159 @@ +# 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.UserUpdateHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.User +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  import Pleroma.Factory + +  test "it works for incoming update activities" do +    user = insert(:user, local: false) + +    update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!() + +    object = +      update_data["object"] +      |> Map.put("actor", user.ap_id) +      |> Map.put("id", user.ap_id) + +    update_data = +      update_data +      |> Map.put("actor", user.ap_id) +      |> Map.put("object", object) + +    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data) + +    assert data["id"] == update_data["id"] + +    user = User.get_cached_by_ap_id(data["actor"]) +    assert user.name == "gargle" + +    assert user.avatar["url"] == [ +             %{ +               "href" => +                 "https://cd.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg" +             } +           ] + +    assert user.banner["url"] == [ +             %{ +               "href" => +                 "https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" +             } +           ] + +    assert user.bio == "<p>Some bio</p>" +  end + +  test "it works with alsoKnownAs" do +    %{ap_id: actor} = insert(:user, local: false) + +    assert User.get_cached_by_ap_id(actor).also_known_as == [] + +    {:ok, _activity} = +      "test/fixtures/mastodon-update.json" +      |> File.read!() +      |> Poison.decode!() +      |> Map.put("actor", actor) +      |> Map.update!("object", fn object -> +        object +        |> Map.put("actor", actor) +        |> Map.put("id", actor) +        |> Map.put("alsoKnownAs", [ +          "http://mastodon.example.org/users/foo", +          "http://example.org/users/bar" +        ]) +      end) +      |> Transmogrifier.handle_incoming() + +    assert User.get_cached_by_ap_id(actor).also_known_as == [ +             "http://mastodon.example.org/users/foo", +             "http://example.org/users/bar" +           ] +  end + +  test "it works with custom profile fields" do +    user = insert(:user, local: false) + +    assert user.fields == [] + +    update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!() + +    object = +      update_data["object"] +      |> Map.put("actor", user.ap_id) +      |> Map.put("id", user.ap_id) + +    update_data = +      update_data +      |> Map.put("actor", user.ap_id) +      |> Map.put("object", object) + +    {:ok, _update_activity} = Transmogrifier.handle_incoming(update_data) + +    user = User.get_cached_by_ap_id(user.ap_id) + +    assert user.fields == [ +             %{"name" => "foo", "value" => "updated"}, +             %{"name" => "foo1", "value" => "updated"} +           ] + +    Pleroma.Config.put([:instance, :max_remote_account_fields], 2) + +    update_data = +      update_data +      |> put_in(["object", "attachment"], [ +        %{"name" => "foo", "type" => "PropertyValue", "value" => "bar"}, +        %{"name" => "foo11", "type" => "PropertyValue", "value" => "bar11"}, +        %{"name" => "foo22", "type" => "PropertyValue", "value" => "bar22"} +      ]) +      |> Map.put("id", update_data["id"] <> ".") + +    {:ok, _} = Transmogrifier.handle_incoming(update_data) + +    user = User.get_cached_by_ap_id(user.ap_id) + +    assert user.fields == [ +             %{"name" => "foo", "value" => "updated"}, +             %{"name" => "foo1", "value" => "updated"} +           ] + +    update_data = +      update_data +      |> put_in(["object", "attachment"], []) +      |> Map.put("id", update_data["id"] <> ".") + +    {:ok, _} = Transmogrifier.handle_incoming(update_data) + +    user = User.get_cached_by_ap_id(user.ap_id) + +    assert user.fields == [] +  end + +  test "it works for incoming update activities which lock the account" do +    user = insert(:user, local: false) + +    update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!() + +    object = +      update_data["object"] +      |> Map.put("actor", user.ap_id) +      |> Map.put("id", user.ap_id) +      |> Map.put("manuallyApprovesFollowers", true) + +    update_data = +      update_data +      |> Map.put("actor", user.ap_id) +      |> Map.put("object", object) + +    {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(update_data) + +    user = User.get_cached_by_ap_id(user.ap_id) +    assert user.locked == true +  end +end | 
