diff options
| author | Alex Gleason <alex@alexgleason.me> | 2020-07-16 14:51:36 -0500 | 
|---|---|---|
| committer | Alex Gleason <alex@alexgleason.me> | 2020-07-16 14:51:36 -0500 | 
| commit | 38425ebdbf157377ccb0402f78dc3d02f81c55f5 (patch) | |
| tree | 740f32837d28e918f097c948d89827d99434d5b2 /test/web/activity_pub | |
| parent | 8daacc911498d827fd68ea3d34eb1be9ae4a1ffe (diff) | |
| parent | 3a2b2cb6f2d6ce39ae0d246649189c021c535992 (diff) | |
| download | pleroma-38425ebdbf157377ccb0402f78dc3d02f81c55f5.tar.gz pleroma-38425ebdbf157377ccb0402f78dc3d02f81c55f5.zip | |
Merge remote-tracking branch 'upstream/develop' into linkify
Diffstat (limited to 'test/web/activity_pub')
31 files changed, 1339 insertions, 882 deletions
| diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index e722f7c04..ed900d8f8 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -1082,6 +1082,45 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do        assert object = Object.get_by_ap_id(note_object.data["id"])        assert object.data["like_count"] == 1      end + +    test "it doesn't spreads faulty attributedTo or actor fields", %{ +      conn: conn, +      activity: activity +    } do +      reimu = insert(:user, nickname: "reimu") +      cirno = insert(:user, nickname: "cirno") + +      assert reimu.ap_id +      assert cirno.ap_id + +      activity = +        activity +        |> put_in(["object", "actor"], reimu.ap_id) +        |> put_in(["object", "attributedTo"], reimu.ap_id) +        |> put_in(["actor"], reimu.ap_id) +        |> put_in(["attributedTo"], reimu.ap_id) + +      _reimu_outbox = +        conn +        |> assign(:user, cirno) +        |> put_req_header("content-type", "application/activity+json") +        |> post("/users/#{reimu.nickname}/outbox", activity) +        |> json_response(403) + +      cirno_outbox = +        conn +        |> assign(:user, cirno) +        |> put_req_header("content-type", "application/activity+json") +        |> post("/users/#{cirno.nickname}/outbox", activity) +        |> json_response(201) + +      assert cirno_outbox["attributedTo"] == nil +      assert cirno_outbox["actor"] == cirno.ap_id + +      assert cirno_object = Object.normalize(cirno_outbox["object"]) +      assert cirno_object.data["actor"] == cirno.ap_id +      assert cirno_object.data["attributedTo"] == cirno.ap_id +    end    end    describe "/relay/followers" do diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index be7ab2ae4..f3951462f 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -184,36 +184,43 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert User.invisible?(user)      end -    test "it fetches the appropriate tag-restricted posts" do -      user = insert(:user) +    test "it returns a user that accepts chat messages" do +      user_id = "http://mastodon.example.org/users/admin" +      {:ok, user} = ActivityPub.make_user_from_ap_id(user_id) -      {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"}) -      {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"}) -      {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"}) +      assert user.accepts_chat_messages +    end +  end -      fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"}) +  test "it fetches the appropriate tag-restricted posts" do +    user = insert(:user) -      fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]}) +    {:ok, status_one} = CommonAPI.post(user, %{status: ". #test"}) +    {:ok, status_two} = CommonAPI.post(user, %{status: ". #essais"}) +    {:ok, status_three} = CommonAPI.post(user, %{status: ". #test #reject"}) -      fetch_three = -        ActivityPub.fetch_activities([], %{ -          type: "Create", -          tag: ["test", "essais"], -          tag_reject: ["reject"] -        }) +    fetch_one = ActivityPub.fetch_activities([], %{type: "Create", tag: "test"}) -      fetch_four = -        ActivityPub.fetch_activities([], %{ -          type: "Create", -          tag: ["test"], -          tag_all: ["test", "reject"] -        }) +    fetch_two = ActivityPub.fetch_activities([], %{type: "Create", tag: ["test", "essais"]}) -      assert fetch_one == [status_one, status_three] -      assert fetch_two == [status_one, status_two, status_three] -      assert fetch_three == [status_one, status_two] -      assert fetch_four == [status_three] -    end +    fetch_three = +      ActivityPub.fetch_activities([], %{ +        type: "Create", +        tag: ["test", "essais"], +        tag_reject: ["reject"] +      }) + +    fetch_four = +      ActivityPub.fetch_activities([], %{ +        type: "Create", +        tag: ["test"], +        tag_all: ["test", "reject"] +      }) + +    assert fetch_one == [status_one, status_three] +    assert fetch_two == [status_one, status_two, status_three] +    assert fetch_three == [status_one, status_two] +    assert fetch_four == [status_three]    end    describe "insertion" do @@ -507,6 +514,33 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        activities = ActivityPub.fetch_activities_for_context("2hu", %{blocking_user: user})        assert activities == [activity_two, activity]      end + +    test "doesn't return activities with filtered words" do +      user = insert(:user) +      user_two = insert(:user) +      insert(:filter, user: user, phrase: "test", hide: true) + +      {:ok, %{id: id1, data: %{"context" => context}}} = CommonAPI.post(user, %{status: "1"}) + +      {:ok, %{id: id2}} = CommonAPI.post(user_two, %{status: "2", in_reply_to_status_id: id1}) + +      {:ok, %{id: id3} = user_activity} = +        CommonAPI.post(user, %{status: "3 test?", in_reply_to_status_id: id2}) + +      {:ok, %{id: id4} = filtered_activity} = +        CommonAPI.post(user_two, %{status: "4 test!", in_reply_to_status_id: id3}) + +      {:ok, _} = CommonAPI.post(user, %{status: "5", in_reply_to_status_id: id4}) + +      activities = +        context +        |> ActivityPub.fetch_activities_for_context(%{user: user}) +        |> Enum.map(& &1.id) + +      assert length(activities) == 4 +      assert user_activity.id in activities +      refute filtered_activity.id in activities +    end    end    test "doesn't return blocked activities" do @@ -642,7 +676,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      refute activity in activities      followed_user = insert(:user) -    ActivityPub.follow(user, followed_user) +    CommonAPI.follow(user, followed_user)      {:ok, repeat_activity} = CommonAPI.repeat(activity.id, followed_user)      activities = ActivityPub.fetch_activities([], %{blocking_user: user, skip_preload: true}) @@ -785,6 +819,75 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      assert activity == expected_activity    end +  describe "irreversible filters" do +    setup do +      user = insert(:user) +      user_two = insert(:user) + +      insert(:filter, user: user_two, phrase: "cofe", hide: true) +      insert(:filter, user: user_two, phrase: "ok boomer", hide: true) +      insert(:filter, user: user_two, phrase: "test", hide: false) + +      params = %{ +        type: ["Create", "Announce"], +        user: user_two +      } + +      {:ok, %{user: user, user_two: user_two, params: params}} +    end + +    test "it returns statuses if they don't contain exact filter words", %{ +      user: user, +      params: params +    } do +      {:ok, _} = CommonAPI.post(user, %{status: "hey"}) +      {:ok, _} = CommonAPI.post(user, %{status: "got cofefe?"}) +      {:ok, _} = CommonAPI.post(user, %{status: "I am not a boomer"}) +      {:ok, _} = CommonAPI.post(user, %{status: "ok boomers"}) +      {:ok, _} = CommonAPI.post(user, %{status: "ccofee is not a word"}) +      {:ok, _} = CommonAPI.post(user, %{status: "this is a test"}) + +      activities = ActivityPub.fetch_activities([], params) + +      assert Enum.count(activities) == 6 +    end + +    test "it does not filter user's own statuses", %{user_two: user_two, params: params} do +      {:ok, _} = CommonAPI.post(user_two, %{status: "Give me some cofe!"}) +      {:ok, _} = CommonAPI.post(user_two, %{status: "ok boomer"}) + +      activities = ActivityPub.fetch_activities([], params) + +      assert Enum.count(activities) == 2 +    end + +    test "it excludes statuses with filter words", %{user: user, params: params} do +      {:ok, _} = CommonAPI.post(user, %{status: "Give me some cofe!"}) +      {:ok, _} = CommonAPI.post(user, %{status: "ok boomer"}) +      {:ok, _} = CommonAPI.post(user, %{status: "is it a cOfE?"}) +      {:ok, _} = CommonAPI.post(user, %{status: "cofe is all I need"}) +      {:ok, _} = CommonAPI.post(user, %{status: "— ok BOOMER\n"}) + +      activities = ActivityPub.fetch_activities([], params) + +      assert Enum.empty?(activities) +    end + +    test "it returns all statuses if user does not have any filters" do +      another_user = insert(:user) +      {:ok, _} = CommonAPI.post(another_user, %{status: "got cofe?"}) +      {:ok, _} = CommonAPI.post(another_user, %{status: "test!"}) + +      activities = +        ActivityPub.fetch_activities([], %{ +          type: ["Create", "Announce"], +          user: another_user +        }) + +      assert Enum.count(activities) == 2 +    end +  end +    describe "public fetch activities" do      test "doesn't retrieve unlisted activities" do        user = insert(:user) @@ -917,24 +1020,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      end    end -  describe "following / unfollowing" do -    test "it reverts follow activity" do -      follower = insert(:user) -      followed = insert(:user) - -      with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do -        assert {:error, :reverted} = ActivityPub.follow(follower, followed) -      end - -      assert Repo.aggregate(Activity, :count, :id) == 0 -      assert Repo.aggregate(Object, :count, :id) == 0 -    end - +  describe "unfollowing" do      test "it reverts unfollow activity" do        follower = insert(:user)        followed = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do          assert {:error, :reverted} = ActivityPub.unfollow(follower, followed) @@ -947,21 +1038,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert activity.data["object"] == followed.ap_id      end -    test "creates a follow activity" do -      follower = insert(:user) -      followed = insert(:user) - -      {:ok, activity} = ActivityPub.follow(follower, followed) -      assert activity.data["type"] == "Follow" -      assert activity.data["actor"] == follower.ap_id -      assert activity.data["object"] == followed.ap_id -    end -      test "creates an undo activity for the last follow" do        follower = insert(:user)        followed = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        {:ok, activity} = ActivityPub.unfollow(follower, followed)        assert activity.data["type"] == "Undo" @@ -978,7 +1059,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        follower = insert(:user)        followed = insert(:user, %{locked: true}) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        {:ok, activity} = ActivityPub.unfollow(follower, followed)        assert activity.data["type"] == "Undo" @@ -992,54 +1073,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      end    end -  describe "blocking" do -    test "reverts block activity on error" do -      [blocker, blocked] = insert_list(2, :user) - -      with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do -        assert {:error, :reverted} = ActivityPub.block(blocker, blocked) -      end - -      assert Repo.aggregate(Activity, :count, :id) == 0 -      assert Repo.aggregate(Object, :count, :id) == 0 -    end - -    test "creates a block activity" do -      clear_config([:instance, :federating], true) -      blocker = insert(:user) -      blocked = insert(:user) - -      with_mock Pleroma.Web.Federator, -        publish: fn _ -> nil end do -        {:ok, activity} = ActivityPub.block(blocker, blocked) - -        assert activity.data["type"] == "Block" -        assert activity.data["actor"] == blocker.ap_id -        assert activity.data["object"] == blocked.ap_id - -        assert called(Pleroma.Web.Federator.publish(activity)) -      end -    end - -    test "works with outgoing blocks disabled, but doesn't federate" do -      clear_config([:instance, :federating], true) -      clear_config([:activitypub, :outgoing_blocks], false) -      blocker = insert(:user) -      blocked = insert(:user) - -      with_mock Pleroma.Web.Federator, -        publish: fn _ -> nil end do -        {:ok, activity} = ActivityPub.block(blocker, blocked) - -        assert activity.data["type"] == "Block" -        assert activity.data["actor"] == blocker.ap_id -        assert activity.data["object"] == blocked.ap_id - -        refute called(Pleroma.Web.Federator.publish(:_)) -      end -    end -  end -    describe "timeline post-processing" do      test "it filters broken threads" do        user1 = insert(:user) @@ -1411,7 +1444,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params) -      Pleroma.Workers.BackgroundWorker.perform(params, nil) +      Pleroma.Workers.BackgroundWorker.perform(%Oban.Job{args: params})        refute User.following?(follower, old_user)        assert User.following?(follower, new_user) @@ -2023,4 +2056,46 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do        assert [%{activity_id: ^id_create}] = Pleroma.ActivityExpiration |> Repo.all()      end    end + +  describe "handling of clashing nicknames" do +    test "renames an existing user with a clashing nickname and a different ap id" do +      orig_user = +        insert( +          :user, +          local: false, +          nickname: "admin@mastodon.example.org", +          ap_id: "http://mastodon.example.org/users/harinezumigari" +        ) + +      %{ +        nickname: orig_user.nickname, +        ap_id: orig_user.ap_id <> "part_2" +      } +      |> ActivityPub.maybe_handle_clashing_nickname() + +      user = User.get_by_id(orig_user.id) + +      assert user.nickname == "#{orig_user.id}.admin@mastodon.example.org" +    end + +    test "does nothing with a clashing nickname and the same ap id" do +      orig_user = +        insert( +          :user, +          local: false, +          nickname: "admin@mastodon.example.org", +          ap_id: "http://mastodon.example.org/users/harinezumigari" +        ) + +      %{ +        nickname: orig_user.nickname, +        ap_id: orig_user.ap_id +      } +      |> ActivityPub.maybe_handle_clashing_nickname() + +      user = User.get_by_id(orig_user.id) + +      assert user.nickname == orig_user.nickname +    end +  end  end diff --git a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs index fca0de7c6..3c795f5ac 100644 --- a/test/web/activity_pub/mrf/anti_followbot_policy_test.exs +++ b/test/web/activity_pub/mrf/anti_followbot_policy_test.exs @@ -21,7 +21,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do          "id" => "https://example.com/activities/1234"        } -      {:reject, nil} = AntiFollowbotPolicy.filter(message) +      assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)      end      test "matches followbots by display name" do @@ -36,7 +36,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do          "id" => "https://example.com/activities/1234"        } -      {:reject, nil} = AntiFollowbotPolicy.filter(message) +      assert {:reject, "[AntiFollowbotPolicy]" <> _} = AntiFollowbotPolicy.filter(message)      end    end diff --git a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs index 1a13699be..6867c9853 100644 --- a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs +++ b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs @@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do    describe "with new user" do      test "it allows posts without links" do -      user = insert(:user) +      user = insert(:user, local: false)        assert user.note_count == 0 @@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do      end      test "it disallows posts with links" do -      user = insert(:user) +      user = insert(:user, local: false)        assert user.note_count == 0 @@ -55,6 +55,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do        {:reject, _} = AntiLinkSpamPolicy.filter(message)      end + +    test "it allows posts with links for local users" do +      user = insert(:user) + +      assert user.note_count == 0 + +      message = +        @linkful_message +        |> Map.put("actor", user.ap_id) + +      {:ok, _message} = AntiLinkSpamPolicy.filter(message) +    end    end    describe "with old user" do diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs index 6e9daa7f9..26f5bcdaa 100644 --- a/test/web/activity_pub/mrf/hellthread_policy_test.exs +++ b/test/web/activity_pub/mrf/hellthread_policy_test.exs @@ -50,7 +50,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do      } do        Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2}) -      {:reject, nil} = filter(message) +      assert {:reject, "[HellthreadPolicy] 3 recipients is over the limit of 2"} == +               filter(message)      end      test "does not reject the message if the recipient count is below reject_threshold", %{ diff --git a/test/web/activity_pub/mrf/keyword_policy_test.exs b/test/web/activity_pub/mrf/keyword_policy_test.exs index fd1f7aec8..b3d0f3d90 100644 --- a/test/web/activity_pub/mrf/keyword_policy_test.exs +++ b/test/web/activity_pub/mrf/keyword_policy_test.exs @@ -25,7 +25,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do          }        } -      assert {:reject, nil} == KeywordPolicy.filter(message) +      assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} = +               KeywordPolicy.filter(message)      end      test "rejects if string matches in summary" do @@ -39,7 +40,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do          }        } -      assert {:reject, nil} == KeywordPolicy.filter(message) +      assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} = +               KeywordPolicy.filter(message)      end      test "rejects if regex matches in content" do @@ -55,7 +57,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do                     }                   } -                 {:reject, nil} == KeywordPolicy.filter(message) +                 {:reject, "[KeywordPolicy] Matches with rejected keyword"} == +                   KeywordPolicy.filter(message)                 end)      end @@ -72,7 +75,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do                     }                   } -                 {:reject, nil} == KeywordPolicy.filter(message) +                 {:reject, "[KeywordPolicy] Matches with rejected keyword"} == +                   KeywordPolicy.filter(message)                 end)      end    end diff --git a/test/web/activity_pub/mrf/mention_policy_test.exs b/test/web/activity_pub/mrf/mention_policy_test.exs index aa003bef5..220309cc9 100644 --- a/test/web/activity_pub/mrf/mention_policy_test.exs +++ b/test/web/activity_pub/mrf/mention_policy_test.exs @@ -76,7 +76,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do          "to" => ["https://example.com/blocked"]        } -      assert MentionPolicy.filter(message) == {:reject, nil} +      assert MentionPolicy.filter(message) == +               {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}      end      test "cc" do @@ -88,7 +89,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicyTest do          "cc" => ["https://example.com/blocked"]        } -      assert MentionPolicy.filter(message) == {:reject, nil} +      assert MentionPolicy.filter(message) == +               {:reject, "[MentionPolicy] Rejected for mention of https://example.com/blocked"}      end    end  end diff --git a/test/web/activity_pub/mrf/reject_non_public_test.exs b/test/web/activity_pub/mrf/reject_non_public_test.exs index f36299b86..58b46b9a2 100644 --- a/test/web/activity_pub/mrf/reject_non_public_test.exs +++ b/test/web/activity_pub/mrf/reject_non_public_test.exs @@ -64,7 +64,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do        }        Pleroma.Config.put([:mrf_rejectnonpublic, :allow_followersonly], false) -      assert {:reject, nil} = RejectNonPublic.filter(message) +      assert {:reject, _} = RejectNonPublic.filter(message)      end    end @@ -94,7 +94,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublicTest do        }        Pleroma.Config.put([:mrf_rejectnonpublic, :allow_direct], false) -      assert {:reject, nil} = RejectNonPublic.filter(message) +      assert {:reject, _} = RejectNonPublic.filter(message)      end    end  end diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs index b7b9bc6a2..e842d8d8d 100644 --- a/test/web/activity_pub/mrf/simple_policy_test.exs +++ b/test/web/activity_pub/mrf/simple_policy_test.exs @@ -124,7 +124,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        report_message = build_report_message()        local_message = build_local_message() -      assert SimplePolicy.filter(report_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(report_message)        assert SimplePolicy.filter(local_message) == {:ok, local_message}      end @@ -133,7 +133,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        report_message = build_report_message()        local_message = build_local_message() -      assert SimplePolicy.filter(report_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(report_message)        assert SimplePolicy.filter(local_message) == {:ok, local_message}      end    end @@ -241,7 +241,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_message = build_remote_message() -      assert SimplePolicy.filter(remote_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_message)      end      test "activity matches with wildcard domain" do @@ -249,7 +249,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_message = build_remote_message() -      assert SimplePolicy.filter(remote_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_message)      end      test "actor has a matching host" do @@ -257,7 +257,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_user = build_remote_user() -      assert SimplePolicy.filter(remote_user) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_user)      end    end @@ -279,7 +279,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do        remote_message = build_remote_message()        assert SimplePolicy.filter(local_message) == {:ok, local_message} -      assert SimplePolicy.filter(remote_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(remote_message)      end      test "activity has a matching host" do @@ -429,7 +429,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do      test "it rejects the deletion" do        deletion_message = build_remote_deletion_message() -      assert SimplePolicy.filter(deletion_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(deletion_message)      end    end @@ -439,7 +439,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do      test "it rejects the deletion" do        deletion_message = build_remote_deletion_message() -      assert SimplePolicy.filter(deletion_message) == {:reject, nil} +      assert {:reject, _} = SimplePolicy.filter(deletion_message)      end    end diff --git a/test/web/activity_pub/mrf/tag_policy_test.exs b/test/web/activity_pub/mrf/tag_policy_test.exs index e7793641a..6ff71d640 100644 --- a/test/web/activity_pub/mrf/tag_policy_test.exs +++ b/test/web/activity_pub/mrf/tag_policy_test.exs @@ -12,8 +12,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do    describe "mrf_tag:disable-any-subscription" do      test "rejects message" do        actor = insert(:user, tags: ["mrf_tag:disable-any-subscription"]) -      message = %{"object" => actor.ap_id, "type" => "Follow"} -      assert {:reject, nil} = TagPolicy.filter(message) +      message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => actor.ap_id} +      assert {:reject, _} = TagPolicy.filter(message)      end    end @@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do        actor = insert(:user, tags: ["mrf_tag:disable-remote-subscription"])        follower = insert(:user, tags: ["mrf_tag:disable-remote-subscription"], local: false)        message = %{"object" => actor.ap_id, "type" => "Follow", "actor" => follower.ap_id} -      assert {:reject, nil} = TagPolicy.filter(message) +      assert {:reject, _} = TagPolicy.filter(message)      end      test "allows non-local follow requests" do diff --git a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs index ba1b69658..8e1ad5bc8 100644 --- a/test/web/activity_pub/mrf/user_allowlist_policy_test.exs +++ b/test/web/activity_pub/mrf/user_allowlist_policy_test.exs @@ -26,6 +26,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicyTest do      actor = insert(:user)      Pleroma.Config.put([:mrf_user_allowlist], %{"localhost" => ["test-ap-id"]})      message = %{"actor" => actor.ap_id} -    assert UserAllowListPolicy.filter(message) == {:reject, nil} +    assert {:reject, _} = UserAllowListPolicy.filter(message)    end  end diff --git a/test/web/activity_pub/mrf/vocabulary_policy_test.exs b/test/web/activity_pub/mrf/vocabulary_policy_test.exs index 69f22bb77..2bceb67ee 100644 --- a/test/web/activity_pub/mrf/vocabulary_policy_test.exs +++ b/test/web/activity_pub/mrf/vocabulary_policy_test.exs @@ -46,7 +46,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          }        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end      test "it does not accept disallowed parent types" do @@ -60,7 +60,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          }        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end    end @@ -75,7 +75,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          "object" => "whatever"        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end      test "it rejects based on child object type" do @@ -89,7 +89,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicyTest do          }        } -      {:reject, nil} = VocabularyPolicy.filter(message) +      {:reject, _} = VocabularyPolicy.filter(message)      end      test "it passes through objects that aren't disallowed" do 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 770a8dcf8..000000000 --- a/test/web/activity_pub/object_validator_test.exs +++ /dev/null @@ -1,657 +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 -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..50bf03515 --- /dev/null +++ b/test/web/activity_pub/object_validators/chat_validation_test.exs @@ -0,0 +1,211 @@ +# 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 recipient is not accepting chat messages", %{ +      valid_chat_message: valid_chat_message, +      recipient: recipient +    } do +      recipient +      |> Ecto.Changeset.change(%{accepts_chat_messages: false}) +      |> Pleroma.Repo.update!() + +      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 diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs index c2bc38d52..b9388b966 100644 --- a/test/web/activity_pub/publisher_test.exs +++ b/test/web/activity_pub/publisher_test.exs @@ -123,6 +123,39 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do    end    describe "publish_one/1" do +    test "publish to url with with different ports" do +      inbox80 = "http://42.site/users/nick1/inbox" +      inbox42 = "http://42.site:42/users/nick1/inbox" + +      mock(fn +        %{method: :post, url: "http://42.site:42/users/nick1/inbox"} -> +          {:ok, %Tesla.Env{status: 200, body: "port 42"}} + +        %{method: :post, url: "http://42.site/users/nick1/inbox"} -> +          {:ok, %Tesla.Env{status: 200, body: "port 80"}} +      end) + +      actor = insert(:user) + +      assert {:ok, %{body: "port 42"}} = +               Publisher.publish_one(%{ +                 inbox: inbox42, +                 json: "{}", +                 actor: actor, +                 id: 1, +                 unreachable_since: true +               }) + +      assert {:ok, %{body: "port 80"}} = +               Publisher.publish_one(%{ +                 inbox: inbox80, +                 json: "{}", +                 actor: actor, +                 id: 1, +                 unreachable_since: true +               }) +    end +      test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",                     Instances,                     [:passthrough], @@ -131,7 +164,6 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do        inbox = "http://200.site/users/nick1/inbox"        assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1}) -        assert called(Instances.set_reachable(inbox))      end diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs index b3b573c9b..9d657ac4f 100644 --- a/test/web/activity_pub/relay_test.exs +++ b/test/web/activity_pub/relay_test.exs @@ -7,8 +7,8 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do    alias Pleroma.Activity    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Relay +  alias Pleroma.Web.CommonAPI    import ExUnit.CaptureLog    import Pleroma.Factory @@ -53,8 +53,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do      test "returns activity" do        user = insert(:user)        service_actor = Relay.get_actor() -      ActivityPub.follow(service_actor, user) -      Pleroma.User.follow(service_actor, user) +      CommonAPI.follow(service_actor, user)        assert "#{user.ap_id}/followers" in User.following(service_actor)        assert {:ok, %Activity{} = activity} = Relay.unfollow(user.ap_id)        assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay" @@ -74,6 +73,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do        assert Relay.publish(activity) == {:error, "Not implemented"}      end +    @tag capture_log: true      test "returns error when activity not public" do        activity = insert(:direct_note_activity)        assert Relay.publish(activity) == {:error, false} diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs index 12c9ef1da..2649b060a 100644 --- a/test/web/activity_pub/side_effects_test.exs +++ b/test/web/activity_pub/side_effects_test.exs @@ -64,6 +64,47 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do      end    end +  describe "blocking users" do +    setup do +      user = insert(:user) +      blocked = insert(:user) +      User.follow(blocked, user) +      User.follow(user, blocked) + +      {:ok, block_data, []} = Builder.block(user, blocked) +      {:ok, block, _meta} = ActivityPub.persist(block_data, local: true) + +      %{user: user, blocked: blocked, block: block} +    end + +    test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do +      assert User.following?(user, blocked) +      assert User.following?(blocked, user) + +      {:ok, _, _} = SideEffects.handle(block) + +      refute User.following?(user, blocked) +      refute User.following?(blocked, user) +      assert User.blocks?(user, blocked) +    end + +    test "it blocks but does not unfollow if the relevant setting is set", %{ +      user: user, +      blocked: blocked, +      block: block +    } do +      clear_config([:activitypub, :unfollow_blocked], false) +      assert User.following?(user, blocked) +      assert User.following?(blocked, user) + +      {:ok, _, _} = SideEffects.handle(block) + +      refute User.following?(user, blocked) +      assert User.following?(blocked, user) +      assert User.blocks?(user, blocked) +    end +  end +    describe "update users" do      setup do        user = insert(:user) @@ -242,8 +283,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do        {:ok, like} = CommonAPI.favorite(user, post.id)        {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")        {:ok, announce} = CommonAPI.repeat(post.id, user) -      {:ok, block} = ActivityPub.block(user, poster) -      User.block(user, poster) +      {:ok, block} = CommonAPI.block(user, poster)        {:ok, undo_data, _meta} = Builder.undo(user, like)        {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true) @@ -549,10 +589,29 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do      end      test "it streams out the announce", %{announce: announce} do -      with_mock Pleroma.Web.ActivityPub.ActivityPub, [:passthrough], stream_out: fn _ -> nil end do +      with_mocks([ +        { +          Pleroma.Web.Streamer, +          [], +          [ +            stream: fn _, _ -> nil end +          ] +        }, +        { +          Pleroma.Web.Push, +          [], +          [ +            send: fn _ -> nil end +          ] +        } +      ]) do          {:ok, announce, _} = SideEffects.handle(announce) -        assert called(Pleroma.Web.ActivityPub.ActivityPub.stream_out(announce)) +        assert called( +                 Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], announce) +               ) + +        assert called(Pleroma.Web.Push.send(:_))        end      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/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs index 06c39eed6..17e764ca1 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -160,7 +160,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do          |> Poison.decode!()          |> Map.put("object", user.ap_id) -      with_mock Pleroma.User, [:passthrough], follow: fn _, _ -> {:error, :testing} end do +      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) diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 100821056..248b410c6 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -11,7 +11,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do    alias Pleroma.Object.Fetcher    alias Pleroma.Tests.ObanHelpers    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Transmogrifier    alias Pleroma.Web.AdminAPI.AccountView    alias Pleroma.Web.CommonAPI @@ -445,56 +444,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert [^pending_follower] = User.get_follow_requests(user)      end -    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) - -      {: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" - -      blocker = User.get_cached_by_ap_id(data["actor"]) - -      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 -      test "it works for incoming accepts which were pre-accepted" do        follower = insert(:user)        followed = insert(:user) @@ -502,7 +451,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        {:ok, follower} = User.follow(follower, followed)        assert User.following?(follower, followed) == true -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        accept_data =          File.read!("test/fixtures/mastodon-accept-activity.json") @@ -532,7 +481,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        follower = insert(:user)        followed = insert(:user, locked: true) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        accept_data =          File.read!("test/fixtures/mastodon-accept-activity.json") @@ -554,7 +503,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        follower = insert(:user)        followed = insert(:user, locked: true) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        accept_data =          File.read!("test/fixtures/mastodon-accept-activity.json") @@ -619,7 +568,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        followed = insert(:user, locked: true)        {:ok, follower} = User.follow(follower, followed) -      {:ok, _follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, followed)        assert User.following?(follower, followed) == true @@ -645,7 +594,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        followed = insert(:user, locked: true)        {:ok, follower} = User.follow(follower, followed) -      {:ok, follow_activity} = ActivityPub.follow(follower, followed) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)        assert User.following?(follower, followed) == true @@ -709,22 +658,44 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do            "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"          ) -      attachment = %{ -        "type" => "Link", -        "mediaType" => "video/mp4", -        "url" => [ -          %{ -            "href" => -              "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", -            "mediaType" => "video/mp4" -          } -        ] -      } -        assert object.data["url"] ==                 "https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3" -      assert object.data["attachment"] == [attachment] +      assert object.data["attachment"] == [ +               %{ +                 "type" => "Link", +                 "mediaType" => "video/mp4", +                 "url" => [ +                   %{ +                     "href" => +                       "https://peertube.moe/static/webseed/df5f464b-be8d-46fb-ad81-2d4c2d1630e3-480.mp4", +                     "mediaType" => "video/mp4" +                   } +                 ] +               } +             ] + +      {:ok, object} = +        Fetcher.fetch_object_from_id( +          "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206" +        ) + +      assert object.data["attachment"] == [ +               %{ +                 "type" => "Link", +                 "mediaType" => "video/mp4", +                 "url" => [ +                   %{ +                     "href" => +                       "https://framatube.org/static/webseed/6050732a-8a7a-43d4-a6cd-809525a1d206-1080.mp4", +                     "mediaType" => "video/mp4" +                   } +                 ] +               } +             ] + +      assert object.data["url"] == +               "https://framatube.org/videos/watch/6050732a-8a7a-43d4-a6cd-809525a1d206"      end      test "it accepts Flag activities" do @@ -803,6 +774,29 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do        assert [user.follower_address] == activity.data["to"]      end +    test "it correctly processes messages with weirdness in address fields" do +      user = insert(:user) + +      message = %{ +        "@context" => "https://www.w3.org/ns/activitystreams", +        "to" => [nil, user.follower_address], +        "cc" => ["https://www.w3.org/ns/activitystreams#Public", ["¿"]], +        "type" => "Create", +        "object" => %{ +          "content" => "…", +          "type" => "Note", +          "attributedTo" => user.ap_id, +          "inReplyTo" => nil +        }, +        "actor" => user.ap_id +      } + +      assert {:ok, activity} = Transmogrifier.handle_incoming(message) + +      assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"] +      assert [user.follower_address] == activity.data["to"] +    end +      test "it accepts Move activities" do        old_user = insert(:user)        new_user = insert(:user) diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index 15f03f193..361dc5a41 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do    alias Pleroma.Object    alias Pleroma.Repo    alias Pleroma.User -  alias Pleroma.Web.ActivityPub.ActivityPub    alias Pleroma.Web.ActivityPub.Utils    alias Pleroma.Web.AdminAPI.AccountView    alias Pleroma.Web.CommonAPI @@ -27,16 +26,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do      end    end -  describe "fetch the latest Block" do -    test "fetches the latest Block activity" do -      blocker = insert(:user) -      blocked = insert(:user) -      {:ok, activity} = ActivityPub.block(blocker, blocked) - -      assert activity == Utils.fetch_latest_block(blocker, blocked) -    end -  end -    describe "determine_explicit_mentions()" do      test "works with an object that has mentions" do        object = %{ @@ -207,8 +196,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user = insert(:user, locked: true)        follower = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_two} = ActivityPub.follow(follower, user) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)        data =          follow_activity_two.data @@ -231,8 +220,8 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user = insert(:user, locked: true)        follower = insert(:user) -      {:ok, follow_activity} = ActivityPub.follow(follower, user) -      {:ok, follow_activity_two} = ActivityPub.follow(follower, user) +      {:ok, _, _, follow_activity} = CommonAPI.follow(follower, user) +      {:ok, _, _, follow_activity_two} = CommonAPI.follow(follower, user)        data =          follow_activity_two.data @@ -344,9 +333,9 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do        user1 = insert(:user)        user2 = insert(:user) -      assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2) -      assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2) -      assert {:ok, %Activity{} = activity} = ActivityPub.block(user1, user2) +      assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2) +      assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2) +      assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)        assert Utils.fetch_latest_block(user1, user2) == activity      end diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index bec15a996..98c7c9d09 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -158,4 +158,23 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do        assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user})      end    end + +  describe "acceptsChatMessages" do +    test "it returns this value if it is set" do +      true_user = insert(:user, accepts_chat_messages: true) +      false_user = insert(:user, accepts_chat_messages: false) +      nil_user = insert(:user, accepts_chat_messages: nil) + +      assert %{"capabilities" => %{"acceptsChatMessages" => true}} = +               UserView.render("user.json", user: true_user) + +      assert %{"capabilities" => %{"acceptsChatMessages" => false}} = +               UserView.render("user.json", user: false_user) + +      refute Map.has_key?( +               UserView.render("user.json", user: nil_user)["capabilities"], +               "acceptsChatMessages" +             ) +    end +  end  end | 
