diff options
| author | lain <lain@soykaf.club> | 2020-08-25 11:44:51 +0200 | 
|---|---|---|
| committer | lain <lain@soykaf.club> | 2020-08-25 11:44:51 +0200 | 
| commit | c1d51944c71ff90650b1a631241daf0d8be5b861 (patch) | |
| tree | 2e78efaeb892c4b09cac0439f268d6a60637b4dc /test/web/activity_pub | |
| parent | 199ad47c22e5d72741f5809eb015bac9b00cca03 (diff) | |
| parent | 5722b0e2e5e7113f0422798a6ea8cc40d1953291 (diff) | |
| download | pleroma-c1d51944c71ff90650b1a631241daf0d8be5b861.tar.gz pleroma-c1d51944c71ff90650b1a631241daf0d8be5b861.zip | |
Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into frontend-bundles-downloads
Diffstat (limited to 'test/web/activity_pub')
15 files changed, 687 insertions, 312 deletions
| diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index ed900d8f8..57988dc1e 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -533,7 +533,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        end)        :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) -      assert_receive {:mix_shell, :info, ["relay.mastodon.host"]} +      assert_receive {:mix_shell, :info, ["https://relay.mastodon.host/actor"]}      end      @tag capture_log: true diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index d6eab7337..03f968aaf 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -990,13 +990,39 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do    end    describe "uploading files" do -    test "copies the file to the configured folder" do -      file = %Plug.Upload{ +    setup do +      test_file = %Plug.Upload{          content_type: "image/jpg",          path: Path.absname("test/fixtures/image.jpg"),          filename: "an_image.jpg"        } +      %{test_file: test_file} +    end + +    test "sets a description if given", %{test_file: file} do +      {:ok, %Object{} = object} = ActivityPub.upload(file, description: "a cool file") +      assert object.data["name"] == "a cool file" +    end + +    test "it sets the default description depending on the configuration", %{test_file: file} do +      clear_config([Pleroma.Upload, :default_description]) + +      Pleroma.Config.put([Pleroma.Upload, :default_description], nil) +      {:ok, %Object{} = object} = ActivityPub.upload(file) +      assert object.data["name"] == "" + +      Pleroma.Config.put([Pleroma.Upload, :default_description], :filename) +      {:ok, %Object{} = object} = ActivityPub.upload(file) +      assert object.data["name"] == "an_image.jpg" + +      Pleroma.Config.put([Pleroma.Upload, :default_description], "unnamed attachment") +      {:ok, %Object{} = object} = ActivityPub.upload(file) +      assert object.data["name"] == "unnamed attachment" +    end + +    test "copies the file to the configured folder", %{test_file: file} do +      clear_config([Pleroma.Upload, :default_description], :filename)        {:ok, %Object{} = object} = ActivityPub.upload(file)        assert object.data["name"] == "an_image.jpg"      end diff --git a/test/web/activity_pub/object_validators/accept_validation_test.exs b/test/web/activity_pub/object_validators/accept_validation_test.exs new file mode 100644 index 000000000..d6111ba41 --- /dev/null +++ b/test/web/activity_pub/object_validators/accept_validation_test.exs @@ -0,0 +1,56 @@ +# 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.AcceptValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.ActivityPub.Pipeline + +  import Pleroma.Factory + +  setup do +    follower = insert(:user) +    followed = insert(:user, local: false) + +    {:ok, follow_data, _} = Builder.follow(follower, followed) +    {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true) + +    {:ok, accept_data, _} = Builder.accept(followed, follow_activity) + +    %{accept_data: accept_data, followed: followed} +  end + +  test "it validates a basic 'accept'", %{accept_data: accept_data} do +    assert {:ok, _, _} = ObjectValidator.validate(accept_data, []) +  end + +  test "it fails when the actor doesn't exist", %{accept_data: accept_data} do +    accept_data = +      accept_data +      |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + +    assert {:error, _} = ObjectValidator.validate(accept_data, []) +  end + +  test "it fails when the accepted activity doesn't exist", %{accept_data: accept_data} do +    accept_data = +      accept_data +      |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1") + +    assert {:error, _} = ObjectValidator.validate(accept_data, []) +  end + +  test "for an accepted follow, it only validates if the actor of the accept is the followed actor", +       %{accept_data: accept_data} do +    stranger = insert(:user) + +    accept_data = +      accept_data +      |> Map.put("actor", stranger.ap_id) + +    assert {:error, _} = ObjectValidator.validate(accept_data, []) +  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 index 42cd18298..02683b899 100644 --- a/test/web/activity_pub/object_validators/delete_validation_test.exs +++ b/test/web/activity_pub/object_validators/delete_validation_test.exs @@ -87,7 +87,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidationTest do        {:error, cng} = ObjectValidator.validate(invalid_other_actor, []) -      assert {:actor, {"is not allowed to delete object", []}} in cng.errors +      assert {:actor, {"is not allowed to modify object", []}} in cng.errors      end      test "it's valid if the actor of the object is a local superuser", diff --git a/test/web/activity_pub/object_validators/reject_validation_test.exs b/test/web/activity_pub/object_validators/reject_validation_test.exs new file mode 100644 index 000000000..370bb6e5c --- /dev/null +++ b/test/web/activity_pub/object_validators/reject_validation_test.exs @@ -0,0 +1,56 @@ +# 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.RejectValidationTest do +  use Pleroma.DataCase + +  alias Pleroma.Web.ActivityPub.Builder +  alias Pleroma.Web.ActivityPub.ObjectValidator +  alias Pleroma.Web.ActivityPub.Pipeline + +  import Pleroma.Factory + +  setup do +    follower = insert(:user) +    followed = insert(:user, local: false) + +    {:ok, follow_data, _} = Builder.follow(follower, followed) +    {:ok, follow_activity, _} = Pipeline.common_pipeline(follow_data, local: true) + +    {:ok, reject_data, _} = Builder.reject(followed, follow_activity) + +    %{reject_data: reject_data, followed: followed} +  end + +  test "it validates a basic 'reject'", %{reject_data: reject_data} do +    assert {:ok, _, _} = ObjectValidator.validate(reject_data, []) +  end + +  test "it fails when the actor doesn't exist", %{reject_data: reject_data} do +    reject_data = +      reject_data +      |> Map.put("actor", "https://gensokyo.2hu/users/raymoo") + +    assert {:error, _} = ObjectValidator.validate(reject_data, []) +  end + +  test "it fails when the rejected activity doesn't exist", %{reject_data: reject_data} do +    reject_data = +      reject_data +      |> Map.put("object", "https://gensokyo.2hu/users/raymoo/follows/1") + +    assert {:error, _} = ObjectValidator.validate(reject_data, []) +  end + +  test "for an rejected follow, it only validates if the actor of the reject is the followed actor", +       %{reject_data: reject_data} do +    stranger = insert(:user) + +    reject_data = +      reject_data +      |> Map.put("actor", stranger.ap_id) + +    assert {:error, _} = ObjectValidator.validate(reject_data, []) +  end +end diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 4a08eb7ee..9efbaad04 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -19,8 +19,9 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do    alias Pleroma.Web.ActivityPub.SideEffects    alias Pleroma.Web.CommonAPI -  import Pleroma.Factory +  import ExUnit.CaptureLog    import Mock +  import Pleroma.Factory    describe "handle_after_transaction" do      test "it streams out notifications and streams" do @@ -221,6 +222,22 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do        assert User.get_cached_by_ap_id(user.ap_id).deactivated      end + +    test "it logs issues with objects deletion", %{ +      delete: delete, +      object: object +    } do +      {:ok, object} = +        object +        |> Object.change(%{data: Map.delete(object.data, "actor")}) +        |> Repo.update() + +      Object.invalid_object_cache(object) + +      assert capture_log(fn -> +               {:error, :no_object_actor} = SideEffects.handle(delete) +             end) =~ "object doesn't have an actor" +    end    end    describe "EmojiReact objects" do diff --git a/test/web/activity_pub/transmogrifier/accept_handling_test.exs b/test/web/activity_pub/transmogrifier/accept_handling_test.exs new file mode 100644 index 000000000..77d468f5c --- /dev/null +++ b/test/web/activity_pub/transmogrifier/accept_handling_test.exs @@ -0,0 +1,91 @@ +# 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.AcceptHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.User +  alias Pleroma.Web.ActivityPub.Transmogrifier +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  test "it works for incoming accepts which were pre-accepted" do +    follower = insert(:user) +    followed = insert(:user) + +    {:ok, follower} = User.follow(follower, followed) +    assert User.following?(follower, followed) == true + +    {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) + +    accept_data = +      File.read!("test/fixtures/mastodon-accept-activity.json") +      |> Poison.decode!() +      |> Map.put("actor", followed.ap_id) + +    object = +      accept_data["object"] +      |> Map.put("actor", follower.ap_id) +      |> Map.put("id", follow_activity.data["id"]) + +    accept_data = Map.put(accept_data, "object", object) + +    {:ok, activity} = Transmogrifier.handle_incoming(accept_data) +    refute activity.local + +    assert activity.data["object"] == follow_activity.data["id"] + +    assert activity.data["id"] == accept_data["id"] + +    follower = User.get_cached_by_id(follower.id) + +    assert User.following?(follower, followed) == true +  end + +  test "it works for incoming accepts which are referenced by IRI only" do +    follower = insert(:user) +    followed = insert(:user, locked: true) + +    {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) + +    accept_data = +      File.read!("test/fixtures/mastodon-accept-activity.json") +      |> Poison.decode!() +      |> Map.put("actor", followed.ap_id) +      |> Map.put("object", follow_activity.data["id"]) + +    {:ok, activity} = Transmogrifier.handle_incoming(accept_data) +    assert activity.data["object"] == follow_activity.data["id"] + +    follower = User.get_cached_by_id(follower.id) + +    assert User.following?(follower, followed) == true + +    follower = User.get_by_id(follower.id) +    assert follower.following_count == 1 + +    followed = User.get_by_id(followed.id) +    assert followed.follower_count == 1 +  end + +  test "it fails for incoming accepts which cannot be correlated" do +    follower = insert(:user) +    followed = insert(:user, locked: true) + +    accept_data = +      File.read!("test/fixtures/mastodon-accept-activity.json") +      |> Poison.decode!() +      |> Map.put("actor", followed.ap_id) + +    accept_data = +      Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) + +    {:error, _} = Transmogrifier.handle_incoming(accept_data) + +    follower = User.get_cached_by_id(follower.id) + +    refute User.following?(follower, followed) == true +  end +end diff --git a/test/web/activity_pub/transmogrifier/answer_handling_test.exs b/test/web/activity_pub/transmogrifier/answer_handling_test.exs new file mode 100644 index 000000000..0f6605c3f --- /dev/null +++ b/test/web/activity_pub/transmogrifier/answer_handling_test.exs @@ -0,0 +1,78 @@ +# 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.AnswerHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Transmogrifier +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  setup_all do +    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  test "incoming, rewrites Note to Answer and increments vote counters" do +    user = insert(:user) + +    {:ok, activity} = +      CommonAPI.post(user, %{ +        status: "suya...", +        poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} +      }) + +    object = Object.normalize(activity) + +    data = +      File.read!("test/fixtures/mastodon-vote.json") +      |> Poison.decode!() +      |> Kernel.put_in(["to"], user.ap_id) +      |> Kernel.put_in(["object", "inReplyTo"], object.data["id"]) +      |> Kernel.put_in(["object", "to"], user.ap_id) + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) +    answer_object = Object.normalize(activity) +    assert answer_object.data["type"] == "Answer" +    assert answer_object.data["inReplyTo"] == object.data["id"] + +    new_object = Object.get_by_ap_id(object.data["id"]) +    assert new_object.data["replies_count"] == object.data["replies_count"] + +    assert Enum.any?( +             new_object.data["oneOf"], +             fn +               %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true +               _ -> false +             end +           ) +  end + +  test "outgoing, rewrites Answer to Note" do +    user = insert(:user) + +    {:ok, poll_activity} = +      CommonAPI.post(user, %{ +        status: "suya...", +        poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} +      }) + +    poll_object = Object.normalize(poll_activity) +    # TODO: Replace with CommonAPI vote creation when implemented +    data = +      File.read!("test/fixtures/mastodon-vote.json") +      |> Poison.decode!() +      |> Kernel.put_in(["to"], user.ap_id) +      |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"]) +      |> Kernel.put_in(["object", "to"], user.ap_id) + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) +    {:ok, data} = Transmogrifier.prepare_outgoing(activity.data) + +    assert data["object"]["type"] == "Note" +  end +end diff --git a/test/web/activity_pub/transmogrifier/audio_handling_test.exs b/test/web/activity_pub/transmogrifier/audio_handling_test.exs new file mode 100644 index 000000000..0636d00c5 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/audio_handling_test.exs @@ -0,0 +1,83 @@ +# 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.AudioHandlingTest do +  use Oban.Testing, repo: Pleroma.Repo +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Transmogrifier + +  import Pleroma.Factory + +  test "it works for incoming listens" do +    _user = insert(:user, ap_id: "http://mastodon.example.org/users/admin") + +    data = %{ +      "@context" => "https://www.w3.org/ns/activitystreams", +      "to" => ["https://www.w3.org/ns/activitystreams#Public"], +      "cc" => [], +      "type" => "Listen", +      "id" => "http://mastodon.example.org/users/admin/listens/1234/activity", +      "actor" => "http://mastodon.example.org/users/admin", +      "object" => %{ +        "type" => "Audio", +        "id" => "http://mastodon.example.org/users/admin/listens/1234", +        "attributedTo" => "http://mastodon.example.org/users/admin", +        "title" => "lain radio episode 1", +        "artist" => "lain", +        "album" => "lain radio", +        "length" => 180_000 +      } +    } + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    object = Object.normalize(activity) + +    assert object.data["title"] == "lain radio episode 1" +    assert object.data["artist"] == "lain" +    assert object.data["album"] == "lain radio" +    assert object.data["length"] == 180_000 +  end + +  test "Funkwhale Audio object" do +    Tesla.Mock.mock(fn +      %{url: "https://channels.tests.funkwhale.audio/federation/actors/compositions"} -> +        %Tesla.Env{ +          status: 200, +          body: File.read!("test/fixtures/tesla_mock/funkwhale_channel.json") +        } +    end) + +    data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Poison.decode!() + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert object = Object.normalize(activity, false) + +    assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] + +    assert object.data["cc"] == [] + +    assert object.data["url"] == "https://channels.tests.funkwhale.audio/library/tracks/74" + +    assert object.data["attachment"] == [ +             %{ +               "mediaType" => "audio/ogg", +               "type" => "Link", +               "name" => nil, +               "url" => [ +                 %{ +                   "href" => +                     "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false", +                   "mediaType" => "audio/ogg", +                   "type" => "Link" +                 } +               ] +             } +           ] +  end +end diff --git a/test/web/activity_pub/transmogrifier/event_handling_test.exs b/test/web/activity_pub/transmogrifier/event_handling_test.exs new file mode 100644 index 000000000..7f1ef2cbd --- /dev/null +++ b/test/web/activity_pub/transmogrifier/event_handling_test.exs @@ -0,0 +1,40 @@ +# 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.EventHandlingTest do +  use Oban.Testing, repo: Pleroma.Repo +  use Pleroma.DataCase + +  alias Pleroma.Object.Fetcher + +  test "Mobilizon Event object" do +    Tesla.Mock.mock(fn +      %{url: "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39"} -> +        %Tesla.Env{ +          status: 200, +          body: File.read!("test/fixtures/tesla_mock/mobilizon.org-event.json") +        } + +      %{url: "https://mobilizon.org/@tcit"} -> +        %Tesla.Env{ +          status: 200, +          body: File.read!("test/fixtures/tesla_mock/mobilizon.org-user.json") +        } +    end) + +    assert {:ok, object} = +             Fetcher.fetch_object_from_id( +               "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39" +             ) + +    assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"] +    assert object.data["cc"] == [] + +    assert object.data["url"] == +             "https://mobilizon.org/events/252d5816-00a3-4a89-a66f-15bf65c33e39" + +    assert object.data["published"] == "2019-12-17T11:33:56Z" +    assert object.data["name"] == "Mobilizon Launching Party" +  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 17e764ca1..757d90941 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -185,5 +185,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do        assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"        assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)      end + +    test "it works for incoming follows to locked account" do +      pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin") +      user = insert(:user, locked: true) + +      data = +        File.read!("test/fixtures/mastodon-follow-activity.json") +        |> Poison.decode!() +        |> Map.put("object", user.ap_id) + +      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + +      assert data["type"] == "Follow" +      assert data["object"] == user.ap_id +      assert data["state"] == "pending" +      assert data["actor"] == "http://mastodon.example.org/users/admin" + +      assert [^pending_follower] = User.get_follow_requests(user) +    end    end  end diff --git a/test/web/activity_pub/transmogrifier/question_handling_test.exs b/test/web/activity_pub/transmogrifier/question_handling_test.exs new file mode 100644 index 000000000..c82361828 --- /dev/null +++ b/test/web/activity_pub/transmogrifier/question_handling_test.exs @@ -0,0 +1,125 @@ +# 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.QuestionHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.Object +  alias Pleroma.Web.ActivityPub.Transmogrifier +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  setup_all do +    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) +    :ok +  end + +  test "Mastodon Question activity" do +    data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    object = Object.normalize(activity, false) + +    assert object.data["url"] == "https://mastodon.sdf.org/@rinpatch/102070944809637304" + +    assert object.data["closed"] == "2019-05-11T09:03:36Z" + +    assert object.data["context"] == activity.data["context"] + +    assert object.data["context"] == +             "tag:mastodon.sdf.org,2019-05-10:objectId=15095122:objectType=Conversation" + +    assert object.data["context_id"] + +    assert object.data["anyOf"] == [] + +    assert Enum.sort(object.data["oneOf"]) == +             Enum.sort([ +               %{ +                 "name" => "25 char limit is dumb", +                 "replies" => %{"totalItems" => 0, "type" => "Collection"}, +                 "type" => "Note" +               }, +               %{ +                 "name" => "Dunno", +                 "replies" => %{"totalItems" => 0, "type" => "Collection"}, +                 "type" => "Note" +               }, +               %{ +                 "name" => "Everyone knows that!", +                 "replies" => %{"totalItems" => 1, "type" => "Collection"}, +                 "type" => "Note" +               }, +               %{ +                 "name" => "I can't even fit a funny", +                 "replies" => %{"totalItems" => 1, "type" => "Collection"}, +                 "type" => "Note" +               } +             ]) + +    user = insert(:user) + +    {:ok, reply_activity} = CommonAPI.post(user, %{status: "hewwo", in_reply_to_id: activity.id}) + +    reply_object = Object.normalize(reply_activity, false) + +    assert reply_object.data["context"] == object.data["context"] +    assert reply_object.data["context_id"] == object.data["context_id"] +  end + +  test "Mastodon Question activity with HTML tags in plaintext" do +    options = [ +      %{ +        "type" => "Note", +        "name" => "<input type=\"date\">", +        "replies" => %{"totalItems" => 0, "type" => "Collection"} +      }, +      %{ +        "type" => "Note", +        "name" => "<input type=\"date\"/>", +        "replies" => %{"totalItems" => 0, "type" => "Collection"} +      }, +      %{ +        "type" => "Note", +        "name" => "<input type=\"date\" />", +        "replies" => %{"totalItems" => 1, "type" => "Collection"} +      }, +      %{ +        "type" => "Note", +        "name" => "<input type=\"date\"></input>", +        "replies" => %{"totalItems" => 1, "type" => "Collection"} +      } +    ] + +    data = +      File.read!("test/fixtures/mastodon-question-activity.json") +      |> Poison.decode!() +      |> Kernel.put_in(["object", "oneOf"], options) + +    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) +    object = Object.normalize(activity, false) + +    assert Enum.sort(object.data["oneOf"]) == Enum.sort(options) +  end + +  test "returns an error if received a second time" do +    data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() + +    assert {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) + +    assert {:error, {:validate_object, {:error, _}}} = Transmogrifier.handle_incoming(data) +  end + +  test "accepts a Question with no content" do +    data = +      File.read!("test/fixtures/mastodon-question-activity.json") +      |> Poison.decode!() +      |> Kernel.put_in(["object", "content"], "") + +    assert {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data) +  end +end diff --git a/test/web/activity_pub/transmogrifier/reject_handling_test.exs b/test/web/activity_pub/transmogrifier/reject_handling_test.exs new file mode 100644 index 000000000..7592fbe1c --- /dev/null +++ b/test/web/activity_pub/transmogrifier/reject_handling_test.exs @@ -0,0 +1,67 @@ +# 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.RejectHandlingTest do +  use Pleroma.DataCase + +  alias Pleroma.Activity +  alias Pleroma.User +  alias Pleroma.Web.ActivityPub.Transmogrifier +  alias Pleroma.Web.CommonAPI + +  import Pleroma.Factory + +  test "it fails for incoming rejects which cannot be correlated" do +    follower = insert(:user) +    followed = insert(:user, locked: true) + +    accept_data = +      File.read!("test/fixtures/mastodon-reject-activity.json") +      |> Poison.decode!() +      |> Map.put("actor", followed.ap_id) + +    accept_data = +      Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) + +    {:error, _} = Transmogrifier.handle_incoming(accept_data) + +    follower = User.get_cached_by_id(follower.id) + +    refute User.following?(follower, followed) == true +  end + +  test "it works for incoming rejects which are referenced by IRI only" do +    follower = insert(:user) +    followed = insert(:user, locked: true) + +    {:ok, follower} = User.follow(follower, followed) +    {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) + +    assert User.following?(follower, followed) == true + +    reject_data = +      File.read!("test/fixtures/mastodon-reject-activity.json") +      |> Poison.decode!() +      |> Map.put("actor", followed.ap_id) +      |> Map.put("object", follow_activity.data["id"]) + +    {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data) + +    follower = User.get_cached_by_id(follower.id) + +    assert User.following?(follower, followed) == false +  end + +  test "it rejects activities without a valid ID" do +    user = insert(:user) + +    data = +      File.read!("test/fixtures/mastodon-follow-activity.json") +      |> Poison.decode!() +      |> Map.put("object", user.ap_id) +      |> Map.put("id", "") + +    :error = Transmogrifier.handle_incoming(data) +  end +end diff --git a/test/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/web/activity_pub/transmogrifier/undo_handling_test.exs index 01dd6c370..8683f7135 100644 --- a/test/web/activity_pub/transmogrifier/undo_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -130,7 +130,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do               "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"    end -  test "it works for incomming unfollows with an existing follow" do +  test "it works for incoming unfollows with an existing follow" do      user = insert(:user)      follow_data = diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 828964a36..3fa41b0c7 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -225,84 +225,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert Enum.at(object.data["tag"], 2) == "moo"      end -    test "it works for incoming questions" do -      data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!() - -      {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - -      object = Object.normalize(activity) - -      assert Enum.all?(object.data["oneOf"], fn choice -> -               choice["name"] in [ -                 "Dunno", -                 "Everyone knows that!", -                 "25 char limit is dumb", -                 "I can't even fit a funny" -               ] -             end) -    end - -    test "it works for incoming listens" do -      data = %{ -        "@context" => "https://www.w3.org/ns/activitystreams", -        "to" => ["https://www.w3.org/ns/activitystreams#Public"], -        "cc" => [], -        "type" => "Listen", -        "id" => "http://mastodon.example.org/users/admin/listens/1234/activity", -        "actor" => "http://mastodon.example.org/users/admin", -        "object" => %{ -          "type" => "Audio", -          "id" => "http://mastodon.example.org/users/admin/listens/1234", -          "attributedTo" => "http://mastodon.example.org/users/admin", -          "title" => "lain radio episode 1", -          "artist" => "lain", -          "album" => "lain radio", -          "length" => 180_000 -        } -      } - -      {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) - -      object = Object.normalize(activity) - -      assert object.data["title"] == "lain radio episode 1" -      assert object.data["artist"] == "lain" -      assert object.data["album"] == "lain radio" -      assert object.data["length"] == 180_000 -    end - -    test "it rewrites Note votes to Answers and increments vote counters on question activities" do -      user = insert(:user) - -      {:ok, activity} = -        CommonAPI.post(user, %{ -          status: "suya...", -          poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} -        }) - -      object = Object.normalize(activity) - -      data = -        File.read!("test/fixtures/mastodon-vote.json") -        |> Poison.decode!() -        |> Kernel.put_in(["to"], user.ap_id) -        |> Kernel.put_in(["object", "inReplyTo"], object.data["id"]) -        |> Kernel.put_in(["object", "to"], user.ap_id) - -      {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) -      answer_object = Object.normalize(activity) -      assert answer_object.data["type"] == "Answer" -      object = Object.get_by_ap_id(object.data["id"]) - -      assert Enum.any?( -               object.data["oneOf"], -               fn -                 %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true -                 _ -> false -               end -             ) -    end -      test "it works for incoming notices with contentMap" do        data =          File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!() @@ -408,7 +330,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        refute Map.has_key?(object_data, "reaction_count")      end -    test "it works for incomming unfollows with an existing follow" do +    test "it works for incoming unfollows with an existing follow" do        user = insert(:user)        follow_data = @@ -433,204 +355,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)      end -    test "it works for incoming follows to locked account" do -      pending_follower = insert(:user, ap_id: "http://mastodon.example.org/users/admin") -      user = insert(:user, locked: true) - -      data = -        File.read!("test/fixtures/mastodon-follow-activity.json") -        |> Poison.decode!() -        |> Map.put("object", user.ap_id) - -      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - -      assert data["type"] == "Follow" -      assert data["object"] == user.ap_id -      assert data["state"] == "pending" -      assert data["actor"] == "http://mastodon.example.org/users/admin" - -      assert [^pending_follower] = User.get_follow_requests(user) -    end - -    test "it works for incoming accepts which were pre-accepted" do -      follower = insert(:user) -      followed = insert(:user) - -      {:ok, follower} = User.follow(follower, followed) -      assert User.following?(follower, followed) == true - -      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - -      accept_data = -        File.read!("test/fixtures/mastodon-accept-activity.json") -        |> Poison.decode!() -        |> Map.put("actor", followed.ap_id) - -      object = -        accept_data["object"] -        |> Map.put("actor", follower.ap_id) -        |> Map.put("id", follow_activity.data["id"]) - -      accept_data = Map.put(accept_data, "object", object) - -      {:ok, activity} = Transmogrifier.handle_incoming(accept_data) -      refute activity.local - -      assert activity.data["object"] == follow_activity.data["id"] - -      assert activity.data["id"] == accept_data["id"] - -      follower = User.get_cached_by_id(follower.id) - -      assert User.following?(follower, followed) == true -    end - -    test "it works for incoming accepts which were orphaned" do -      follower = insert(:user) -      followed = insert(:user, locked: true) - -      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - -      accept_data = -        File.read!("test/fixtures/mastodon-accept-activity.json") -        |> Poison.decode!() -        |> Map.put("actor", followed.ap_id) - -      accept_data = -        Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - -      {:ok, activity} = Transmogrifier.handle_incoming(accept_data) -      assert activity.data["object"] == follow_activity.data["id"] - -      follower = User.get_cached_by_id(follower.id) - -      assert User.following?(follower, followed) == true -    end - -    test "it works for incoming accepts which are referenced by IRI only" do -      follower = insert(:user) -      followed = insert(:user, locked: true) - -      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - -      accept_data = -        File.read!("test/fixtures/mastodon-accept-activity.json") -        |> Poison.decode!() -        |> Map.put("actor", followed.ap_id) -        |> Map.put("object", follow_activity.data["id"]) - -      {:ok, activity} = Transmogrifier.handle_incoming(accept_data) -      assert activity.data["object"] == follow_activity.data["id"] - -      follower = User.get_cached_by_id(follower.id) - -      assert User.following?(follower, followed) == true - -      follower = User.get_by_id(follower.id) -      assert follower.following_count == 1 - -      followed = User.get_by_id(followed.id) -      assert followed.follower_count == 1 -    end - -    test "it fails for incoming accepts which cannot be correlated" do -      follower = insert(:user) -      followed = insert(:user, locked: true) - -      accept_data = -        File.read!("test/fixtures/mastodon-accept-activity.json") -        |> Poison.decode!() -        |> Map.put("actor", followed.ap_id) - -      accept_data = -        Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - -      :error = Transmogrifier.handle_incoming(accept_data) - -      follower = User.get_cached_by_id(follower.id) - -      refute User.following?(follower, followed) == true -    end - -    test "it fails for incoming rejects which cannot be correlated" do -      follower = insert(:user) -      followed = insert(:user, locked: true) - -      accept_data = -        File.read!("test/fixtures/mastodon-reject-activity.json") -        |> Poison.decode!() -        |> Map.put("actor", followed.ap_id) - -      accept_data = -        Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.ap_id)) - -      :error = Transmogrifier.handle_incoming(accept_data) - -      follower = User.get_cached_by_id(follower.id) - -      refute User.following?(follower, followed) == true -    end - -    test "it works for incoming rejects which are orphaned" do -      follower = insert(:user) -      followed = insert(:user, locked: true) - -      {:ok, follower} = User.follow(follower, followed) -      {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, followed) - -      assert User.following?(follower, followed) == true - -      reject_data = -        File.read!("test/fixtures/mastodon-reject-activity.json") -        |> Poison.decode!() -        |> Map.put("actor", followed.ap_id) - -      reject_data = -        Map.put(reject_data, "object", Map.put(reject_data["object"], "actor", follower.ap_id)) - -      {:ok, activity} = Transmogrifier.handle_incoming(reject_data) -      refute activity.local -      assert activity.data["id"] == reject_data["id"] - -      follower = User.get_cached_by_id(follower.id) - -      assert User.following?(follower, followed) == false -    end - -    test "it works for incoming rejects which are referenced by IRI only" do -      follower = insert(:user) -      followed = insert(:user, locked: true) - -      {:ok, follower} = User.follow(follower, followed) -      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed) - -      assert User.following?(follower, followed) == true - -      reject_data = -        File.read!("test/fixtures/mastodon-reject-activity.json") -        |> Poison.decode!() -        |> Map.put("actor", followed.ap_id) -        |> Map.put("object", follow_activity.data["id"]) - -      {:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data) - -      follower = User.get_cached_by_id(follower.id) - -      assert User.following?(follower, followed) == false -    end - -    test "it rejects activities without a valid ID" do -      user = insert(:user) - -      data = -        File.read!("test/fixtures/mastodon-follow-activity.json") -        |> Poison.decode!() -        |> Map.put("object", user.ap_id) -        |> Map.put("id", "") - -      :error = Transmogrifier.handle_incoming(data) -    end -      test "skip converting the content when it is nil" do        object_id = "https://peertube.social/videos/watch/278d2b7c-0f38-4aaa-afe6-9ecc0c4a34fe" @@ -677,7 +401,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                     %{                       "href" =>                         "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", -                     "mediaType" => "video/mp4" +                     "mediaType" => "video/mp4", +                     "type" => "Link"                     }                   ]                 } @@ -696,7 +421,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                     %{                       "href" =>                         "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", -                     "mediaType" => "video/mp4" +                     "mediaType" => "video/mp4", +                     "type" => "Link"                     }                   ]                 } @@ -1269,30 +995,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do      end    end -  test "Rewrites Answers to Notes" do -    user = insert(:user) - -    {:ok, poll_activity} = -      CommonAPI.post(user, %{ -        status: "suya...", -        poll: %{options: ["suya", "suya.", "suya.."], expires_in: 10} -      }) - -    poll_object = Object.normalize(poll_activity) -    # TODO: Replace with CommonAPI vote creation when implemented -    data = -      File.read!("test/fixtures/mastodon-vote.json") -      |> Poison.decode!() -      |> Kernel.put_in(["to"], user.ap_id) -      |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"]) -      |> Kernel.put_in(["object", "to"], user.ap_id) - -    {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data) -    {:ok, data} = Transmogrifier.prepare_outgoing(activity.data) - -    assert data["object"]["type"] == "Note" -  end -    describe "fix_explicit_addressing" do      setup do        user = insert(:user) @@ -1540,8 +1242,13 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                 "attachment" => [                   %{                     "mediaType" => "video/mp4", +                   "type" => "Document",                     "url" => [ -                     %{"href" => "https://peertube.moe/stat-480.mp4", "mediaType" => "video/mp4"} +                     %{ +                       "href" => "https://peertube.moe/stat-480.mp4", +                       "mediaType" => "video/mp4", +                       "type" => "Link" +                     }                     ]                   }                 ] @@ -1558,14 +1265,24 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do                 "attachment" => [                   %{                     "mediaType" => "video/mp4", +                   "type" => "Document",                     "url" => [ -                     %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"} +                     %{ +                       "href" => "https://pe.er/stat-480.mp4", +                       "mediaType" => "video/mp4", +                       "type" => "Link" +                     }                     ]                   },                   %{                     "mediaType" => "video/mp4", +                   "type" => "Document",                     "url" => [ -                     %{"href" => "https://pe.er/stat-480.mp4", "mediaType" => "video/mp4"} +                     %{ +                       "href" => "https://pe.er/stat-480.mp4", +                       "mediaType" => "video/mp4", +                       "type" => "Link" +                     }                     ]                   }                 ] | 
